cheatorious 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/GEM_VERSION +1 -1
- data/LICENSE +8 -0
- data/README.md +104 -3
- data/bin/cheatorious +19 -0
- data/bin/vim_example.rb +34 -0
- data/lib/cheatorious/cheatsheet.rb +34 -26
- data/lib/cheatorious/search.rb +77 -0
- data/lib/cheatorious/utils.rb +21 -0
- data/lib/cheatorious/writer/text.rb +64 -0
- data/lib/cheatorious/writer.rb +5 -0
- data/lib/cheatorious.rb +3 -0
- metadata +12 -5
data/GEM_VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
v0.
|
1
|
+
v0.1.0
|
data/LICENSE
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
Copyright (c) 2011 Luis Cipriani
|
2
|
+
|
3
|
+
The MIT License (MIT)
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
5
|
+
|
6
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
7
|
+
|
8
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,5 +1,106 @@
|
|
1
|
-
#
|
1
|
+
# cheatorious
|
2
2
|
|
3
|
-
|
3
|
+
_"Being victorious through a means so amazing it cannot possibly be achieved without cheating."_
|
4
|
+
(Urban Dictionary)
|
4
5
|
|
5
|
-
|
6
|
+
[![Build Status](https://secure.travis-ci.org/lfcipriani/cheatorious.png)](http://travis-ci.org/lfcipriani/cheatorious)
|
7
|
+
|
8
|
+
**cheatorious** is a generator of simple, searchable, shareable, modular command-line cheatsheets.
|
9
|
+
|
10
|
+
Cheatsheets are very good to start learning or keep knowledge of some language or tool, but very often you just don't have the proper cheatsheet at hand when you need to remember that cryptic keyboard shortcut. Furthermore, wouldn't be nice to keep or create your own cheatsheets in a neat ruby DSL? Wouldn't be great if you have easy access to them, such as via command-line interface?
|
11
|
+
|
12
|
+
## Install ##
|
13
|
+
|
14
|
+
gem install cheatorious
|
15
|
+
|
16
|
+
Cheatorious is compatible with ruby 1.8.x, 1.9.x, rubinius, jruby, ree and more.
|
17
|
+
|
18
|
+
## Creating your Cheatsheet ##
|
19
|
+
|
20
|
+
Create a file and use the following syntax, shown in the example below:
|
21
|
+
|
22
|
+
cheatsheet_for "Simple VIM" do
|
23
|
+
# put some info about you, if you want to share this later
|
24
|
+
description "A simple VIM cheatsheet for tests"
|
25
|
+
author "Luis Cipriani", "github.com/lfcipriani"
|
26
|
+
version "1.0.0"
|
27
|
+
|
28
|
+
# you can configure some keyboard keys variables
|
29
|
+
key :control, "^"
|
30
|
+
key :esc , "<esc>"
|
31
|
+
key :leader , ","
|
32
|
+
|
33
|
+
# your prefered keyboard keys separators (default is empty string)
|
34
|
+
key_separator " "
|
35
|
+
|
36
|
+
# this is an cheatsheet entry, the first parameter is what the entry does, the other are the shortcuts or descriptions
|
37
|
+
__ "Enter insertion mode", "i"
|
38
|
+
__ "Exit insertion mode" , _esc
|
39
|
+
|
40
|
+
# you can create sections, that will be searchable
|
41
|
+
section "Basic Movement" do
|
42
|
+
__ "character left, right, line up, line down", "h", "l", "k", "j"
|
43
|
+
__ "word/token left, right" , "b", "w"
|
44
|
+
end
|
45
|
+
|
46
|
+
section "Scrolling" do
|
47
|
+
# this is how you use the pre-configured keyboard keys
|
48
|
+
__ "scroll line up, down", (_control "E"), (_control "Y")
|
49
|
+
__ "scroll page up, down", (_control "F"), (_control "B")
|
50
|
+
__ "crazy scroll", (_leader _control "A") # this is just to show you can combine keys \o/
|
51
|
+
end
|
52
|
+
|
53
|
+
section "Files" do
|
54
|
+
__ "Open file", ":e"
|
55
|
+
|
56
|
+
# you can go infinitely deep with sections
|
57
|
+
section "Saving" do
|
58
|
+
__ "Save file", ":w"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
## Compiling your cheatsheet ##
|
64
|
+
|
65
|
+
In this alpha version, the compilation is transparently done by cheatorious, but in future versions you'll be able to:
|
66
|
+
|
67
|
+
* serialize your cheatsheet for exporting
|
68
|
+
* export in Base64 to make the search faster
|
69
|
+
* export a standalone executable script
|
70
|
+
|
71
|
+
## Using cheatorious ##
|
72
|
+
|
73
|
+
The CLI usage goes as follows:
|
74
|
+
|
75
|
+
$ cheatorious cheatsheet_file [keyword]
|
76
|
+
|
77
|
+
Where *cheatsheet_file* is the file you created above using the ruby DSL and a optional *keyword* if you want to filter the cheatsheet (case insensitive). If no keyword is passed, it will return whole cheatsheet.
|
78
|
+
|
79
|
+
I'm working to let this usage even more simple and fast.
|
80
|
+
|
81
|
+
## TODO ##
|
82
|
+
|
83
|
+
* search by sections
|
84
|
+
* reverse search
|
85
|
+
* standalone script generation
|
86
|
+
* case sensitive search
|
87
|
+
* better ouput layout, colored
|
88
|
+
* more features in command line
|
89
|
+
* other output writers
|
90
|
+
|
91
|
+
## Tips ##
|
92
|
+
|
93
|
+
* In Macs, cheatorious is very powerful if used with [DTerm](http://decimus.net/DTerm)
|
94
|
+
|
95
|
+
## Contributing ##
|
96
|
+
|
97
|
+
You can contribute in the Core, with Writers or Cheatsheets, feel free.
|
98
|
+
|
99
|
+
* Fork
|
100
|
+
* Implement tests
|
101
|
+
* Implement feature
|
102
|
+
* Test it
|
103
|
+
* Pull request
|
104
|
+
|
105
|
+
----
|
106
|
+
_Copyright (c) 2011 Luis Cipriani (under MIT license)_
|
data/bin/cheatorious
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
@cheatsheet_model = nil
|
3
|
+
def cheatsheet_for(name, &block)
|
4
|
+
@cheatsheet_model = Cheatorious::CheatSheet.compile(name, &block)
|
5
|
+
end
|
6
|
+
|
7
|
+
if ARGV.size > 0
|
8
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/cheatorious')
|
9
|
+
|
10
|
+
if File.exist?(ARGV[0])
|
11
|
+
load ARGV[0]
|
12
|
+
result = Cheatorious::Search.execute(@cheatsheet_model, ARGV[1] || "")
|
13
|
+
puts result
|
14
|
+
else
|
15
|
+
puts "File not found: #{ARGV[0]}"
|
16
|
+
end
|
17
|
+
else
|
18
|
+
puts "Usage: cheatorious cheatsheet_file [keyword]"
|
19
|
+
end
|
data/bin/vim_example.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
cheatsheet_for "Simple VIM" do
|
2
|
+
|
3
|
+
description "A simple VIM cheatsheet for tests"
|
4
|
+
author "Luis Cipriani", "github.com/lfcipriani"
|
5
|
+
version "1.0.0"
|
6
|
+
|
7
|
+
key_separator " "
|
8
|
+
|
9
|
+
key :control, "^"
|
10
|
+
key :esc , "<esc>"
|
11
|
+
key :leader , ","
|
12
|
+
|
13
|
+
__ "Enter insertion mode", "i"
|
14
|
+
__ "Exit insertion mode" , _esc
|
15
|
+
|
16
|
+
section "Basic Movement" do
|
17
|
+
__ "character left, right, line up, line down", "h", "l", "k", "j"
|
18
|
+
__ "word/token left, right" , "b", "w"
|
19
|
+
end
|
20
|
+
|
21
|
+
section "Scrolling" do
|
22
|
+
__ "scroll line up, down", (_control "E"), (_control "Y")
|
23
|
+
__ "scroll page up, down", (_control "F"), (_control "B")
|
24
|
+
end
|
25
|
+
|
26
|
+
section "Files" do
|
27
|
+
__ "Open file", ":e"
|
28
|
+
|
29
|
+
section "Saving" do
|
30
|
+
__ "Save file", ":w"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -2,9 +2,9 @@ module Cheatorious
|
|
2
2
|
class CheatSheet
|
3
3
|
|
4
4
|
class << self
|
5
|
-
def compile(name, &block)
|
5
|
+
def compile(name, output = nil, &block)
|
6
6
|
c = self.new(name, &block)
|
7
|
-
c.compile!
|
7
|
+
c.compile!(output)
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -15,29 +15,32 @@ module Cheatorious
|
|
15
15
|
@block = block
|
16
16
|
@keys = {}
|
17
17
|
@cheat_hash = {
|
18
|
+
:info => { :name => name },
|
18
19
|
:cheatsheet => {
|
19
|
-
:root
|
20
|
+
:root => [],
|
21
|
+
:reverse => {}
|
20
22
|
}
|
21
23
|
}
|
22
24
|
@current_section = @cheat_hash[:cheatsheet][:root]
|
23
|
-
@
|
25
|
+
@stack = []
|
26
|
+
@separator = ""
|
24
27
|
end
|
25
28
|
|
26
|
-
def compile!
|
29
|
+
def compile!(output = nil)
|
27
30
|
self.instance_eval(&@block)
|
28
|
-
return @cheat_hash
|
31
|
+
return output ? Utils.serialize(@cheat_hash, output) : @cheat_hash
|
29
32
|
end
|
30
33
|
|
31
34
|
def description(info)
|
32
|
-
root[
|
35
|
+
root[:info][:description] = info
|
33
36
|
end
|
34
37
|
|
35
38
|
def version(numbers)
|
36
|
-
root[
|
39
|
+
root[:info][:version] = numbers.to_s
|
37
40
|
end
|
38
41
|
|
39
42
|
def author(*args)
|
40
|
-
root[
|
43
|
+
root[:info][:author] = args
|
41
44
|
end
|
42
45
|
|
43
46
|
def key_separator(separator)
|
@@ -49,22 +52,33 @@ module Cheatorious
|
|
49
52
|
end
|
50
53
|
|
51
54
|
def section(name, &block)
|
52
|
-
@current_section[:sections] = {} unless @current_section.key?(:sections)
|
53
|
-
@current_section[:sections][name] = {} unless @current_section[:sections].key?(name)
|
54
55
|
parent_section = @current_section
|
55
|
-
@current_section = @current_section[:sections][name]
|
56
56
|
|
57
|
+
new_section = { name => [] }
|
58
|
+
@current_section = new_section[name]
|
59
|
+
|
60
|
+
@stack.push(name)
|
57
61
|
self.instance_eval(&block)
|
62
|
+
@stack.pop
|
58
63
|
|
59
64
|
@current_section = parent_section
|
65
|
+
@current_section << new_section
|
60
66
|
end
|
61
67
|
|
62
|
-
def
|
63
|
-
|
64
|
-
|
68
|
+
def __(name, *values)
|
69
|
+
new_entry = [name]
|
70
|
+
|
65
71
|
values.each do |v|
|
66
|
-
|
72
|
+
new_entry << v
|
73
|
+
|
74
|
+
reverse_entry = {
|
75
|
+
:name => name,
|
76
|
+
:section => @stack.dup
|
77
|
+
}
|
78
|
+
reverse_index.key?(v) ? reverse_index[v] << reverse_entry : reverse_index[v] = [reverse_entry]
|
67
79
|
end
|
80
|
+
|
81
|
+
@current_section << new_entry
|
68
82
|
end
|
69
83
|
|
70
84
|
def method_missing(method, *args)
|
@@ -88,15 +102,9 @@ module Cheatorious
|
|
88
102
|
@cheat_hash[:cheatsheet]
|
89
103
|
end
|
90
104
|
|
105
|
+
def reverse_index
|
106
|
+
@cheat_hash[:cheatsheet][:reverse]
|
107
|
+
end
|
108
|
+
|
91
109
|
end
|
92
110
|
end
|
93
|
-
|
94
|
-
# hash = {
|
95
|
-
# "description" => "bla",
|
96
|
-
# "cheatsheet" => {
|
97
|
-
# :root => {
|
98
|
-
# :entries => { "Save File" => [":w"] },
|
99
|
-
# :sections => { "files" => {} }
|
100
|
-
# }
|
101
|
-
# }
|
102
|
-
# }
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Cheatorious
|
2
|
+
class Search
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def execute(cheat_model, query = "", writer = Writer::Text, options = {})
|
6
|
+
s = self.new(cheat_model)
|
7
|
+
s.execute(query, writer, options)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(cheat_model)
|
12
|
+
cheat_model = Utils.deserialize(cheat_model, Utils.serialization_type(cheat_model)) if cheat_model.kind_of?(String)
|
13
|
+
@cheat_model = cheat_model
|
14
|
+
end
|
15
|
+
|
16
|
+
def execute(query = "", writer = Writer::Text, options = {})
|
17
|
+
options[:print] = query.empty? ? :full : :partial
|
18
|
+
|
19
|
+
filtered = @cheat_model[:cheatsheet][:root].dup
|
20
|
+
unless print_full?(options)
|
21
|
+
filtered, results_count = depth_search(query, filtered, options)
|
22
|
+
end
|
23
|
+
|
24
|
+
w = writer.new(@cheat_model[:info])
|
25
|
+
print_full?(options) ? w.header : w.search_header(query, results_count, "")
|
26
|
+
write_contents(filtered, w, options)
|
27
|
+
w.footer if print_full?(options)
|
28
|
+
|
29
|
+
return w.result
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def depth_search(query, section, options)
|
35
|
+
match_count = 0
|
36
|
+
result = section.select do |item|
|
37
|
+
if item.kind_of?(Array) #entry
|
38
|
+
name = item[0]
|
39
|
+
result = match?(query, name)
|
40
|
+
match_count += 1 if result
|
41
|
+
result
|
42
|
+
elsif item.kind_of?(Hash) #section
|
43
|
+
name = item.keys.first
|
44
|
+
item[name], count = depth_search(query, item[name], options)
|
45
|
+
match_count += count
|
46
|
+
item[name].size > 0
|
47
|
+
else
|
48
|
+
false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
return result, match_count
|
52
|
+
end
|
53
|
+
|
54
|
+
def write_contents(section, writer, options)
|
55
|
+
section.each do |item|
|
56
|
+
if item.kind_of?(Array) #entry
|
57
|
+
name = item.shift
|
58
|
+
writer.entry(name, *item)
|
59
|
+
elsif item.kind_of?(Hash) #section
|
60
|
+
name = item.keys.first
|
61
|
+
writer.section_start(name)
|
62
|
+
write_contents(item[name], writer, options)
|
63
|
+
writer.section_end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def match?(query, name)
|
69
|
+
not name.downcase.index(query.downcase).nil?
|
70
|
+
end
|
71
|
+
|
72
|
+
def print_full?(options)
|
73
|
+
options[:print] == :full
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Cheatorious
|
2
|
+
class Utils
|
3
|
+
require "base64"
|
4
|
+
|
5
|
+
def self.serialize(object, to = nil)
|
6
|
+
data = Marshal.dump(object)
|
7
|
+
data = Base64.encode64(data) if to == :base64
|
8
|
+
return data
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.deserialize(data, from = nil)
|
12
|
+
data = Base64.decode64(data) if from == :base64
|
13
|
+
object = Marshal.load(data)
|
14
|
+
return object
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.serialization_type(data)
|
18
|
+
/^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$/ =~ data ? :base64 : :bytes
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Cheatorious
|
2
|
+
module Writer
|
3
|
+
class Text
|
4
|
+
def initialize(cheatsheet_info = {})
|
5
|
+
@info = cheatsheet_info
|
6
|
+
@section_stack = []
|
7
|
+
@result = ""
|
8
|
+
end
|
9
|
+
|
10
|
+
def header
|
11
|
+
line
|
12
|
+
line "-" * 80
|
13
|
+
line "#{@info[:name]} (#{@info[:version]})"
|
14
|
+
line
|
15
|
+
line "Author : #{@info[:author][0]} (#{@info[:author][1]})"
|
16
|
+
line "Description: #{@info[:description]}"
|
17
|
+
line "-" * 80
|
18
|
+
line
|
19
|
+
end
|
20
|
+
|
21
|
+
def search_header(query, results_count, query_type)
|
22
|
+
line
|
23
|
+
line "Your search for '#{query}' returned #{results_count} #{results_count > 1 ? "entries" : "entry"}:" if results_count != 0
|
24
|
+
line "Your search for '#{query}' doesn't returned any entry. Try with another keyword." if results_count == 0
|
25
|
+
line
|
26
|
+
end
|
27
|
+
|
28
|
+
def footer
|
29
|
+
line
|
30
|
+
line "-" * 80
|
31
|
+
line "generated by Cheatorious (https://github.com/lfcipriani/cheatorious)"
|
32
|
+
end
|
33
|
+
|
34
|
+
def section_start(section)
|
35
|
+
@section_stack.push(section)
|
36
|
+
line indentation("-") + " #{section}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def section_end
|
40
|
+
@section_stack.pop
|
41
|
+
end
|
42
|
+
|
43
|
+
def entry(name, *values)
|
44
|
+
e = "#{indentation(" ")} - #{name}: "
|
45
|
+
e << values.join(", ")
|
46
|
+
line e
|
47
|
+
end
|
48
|
+
|
49
|
+
def result
|
50
|
+
@result
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def line(str = "")
|
56
|
+
@result += str + "\n"
|
57
|
+
end
|
58
|
+
|
59
|
+
def indentation(char)
|
60
|
+
char * 2 * @section_stack.size
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/cheatorious.rb
CHANGED
@@ -8,5 +8,8 @@ require "bundler/setup"
|
|
8
8
|
# Gem requirements
|
9
9
|
module Cheatorious
|
10
10
|
autoload :CheatSheet, "cheatorious/cheatsheet"
|
11
|
+
autoload :Utils , "cheatorious/utils"
|
12
|
+
autoload :Search , "cheatorious/search"
|
13
|
+
autoload :Writer , "cheatorious/writer"
|
11
14
|
autoload :VERSION , 'cheatorious/version'
|
12
15
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cheatorious
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-12-
|
12
|
+
date: 2011-12-12 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: step-up
|
16
|
-
requirement: &
|
16
|
+
requirement: &2152580060 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2152580060
|
25
25
|
description:
|
26
26
|
email: lfcipriani@gmail.com
|
27
27
|
executables: []
|
@@ -29,12 +29,19 @@ extensions: []
|
|
29
29
|
extra_rdoc_files: []
|
30
30
|
files:
|
31
31
|
- .travis.yml
|
32
|
+
- LICENSE
|
32
33
|
- README.md
|
34
|
+
- bin/cheatorious
|
35
|
+
- bin/vim_example.rb
|
33
36
|
- cheatorious.gemspec
|
34
37
|
- lib/cheatorious.rb
|
35
38
|
- lib/cheatorious/.gitkeep
|
36
39
|
- lib/cheatorious/cheatsheet.rb
|
40
|
+
- lib/cheatorious/search.rb
|
41
|
+
- lib/cheatorious/utils.rb
|
37
42
|
- lib/cheatorious/version.rb
|
43
|
+
- lib/cheatorious/writer.rb
|
44
|
+
- lib/cheatorious/writer/text.rb
|
38
45
|
- lib/tasks/task_sample.rake
|
39
46
|
- GEM_VERSION
|
40
47
|
homepage: https://github.com/abril/cheatorious
|
@@ -51,7 +58,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
51
58
|
version: '0'
|
52
59
|
segments:
|
53
60
|
- 0
|
54
|
-
hash:
|
61
|
+
hash: 4106099593151906772
|
55
62
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
63
|
none: false
|
57
64
|
requirements:
|