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 CHANGED
@@ -1 +1 @@
1
- v0.0.0+2
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
- # Cheatorious
1
+ # cheatorious
2
2
 
3
- generator of simple, searchable, command line cheatsheets
3
+ _"Being victorious through a means so amazing it cannot possibly be achieved without cheating."_
4
+ (Urban Dictionary)
4
5
 
5
- This gem is not ready yet, more info comming soon...
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
@@ -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
- @separator = ""
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["description"] = info
35
+ root[:info][:description] = info
33
36
  end
34
37
 
35
38
  def version(numbers)
36
- root["version"] = numbers.to_s
39
+ root[:info][:version] = numbers.to_s
37
40
  end
38
41
 
39
42
  def author(*args)
40
- root["author"] = args
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 ___(name, *values)
63
- @current_section[:entries] = {} unless @current_section.key?(:entries)
64
- @current_section[:entries][name] = [] unless @current_section[:entries].key?(name)
68
+ def __(name, *values)
69
+ new_entry = [name]
70
+
65
71
  values.each do |v|
66
- @current_section[:entries][name] << v
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
@@ -0,0 +1,5 @@
1
+ module Cheatorious
2
+ module Writer
3
+ autoload :Text, "cheatorious/writer/text"
4
+ end
5
+ 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.0.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-08 00:00:00.000000000Z
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: &2152980340 !ruby/object:Gem::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: *2152980340
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: -2831247960477896023
61
+ hash: 4106099593151906772
55
62
  required_rubygems_version: !ruby/object:Gem::Requirement
56
63
  none: false
57
64
  requirements: