ver 2009.10.14
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +1404 -0
- data/MANIFEST +187 -0
- data/Rakefile +30 -0
- data/TODO +169 -0
- data/bin/ver +19 -0
- data/config/detect.rb +109 -0
- data/config/keymap/vim.rb +239 -0
- data/config/rc.rb +0 -0
- data/config/scratch +3 -0
- data/config/syntax/ANTLR.json +275 -0
- data/config/syntax/ASP VB.net.json +228 -0
- data/config/syntax/ASP.json +135 -0
- data/config/syntax/ActionScript.json +168 -0
- data/config/syntax/Ada.json +108 -0
- data/config/syntax/Apache.json +342 -0
- data/config/syntax/AppleScript.json +721 -0
- data/config/syntax/Bibtex.json +253 -0
- data/config/syntax/Blog (HTML).json +47 -0
- data/config/syntax/Blog (Markdown).json +50 -0
- data/config/syntax/Blog (Text).json +45 -0
- data/config/syntax/Blog (Textile).json +45 -0
- data/config/syntax/Bulletin Board.json +428 -0
- data/config/syntax/C++.json +323 -0
- data/config/syntax/C.json +694 -0
- data/config/syntax/CSS.json +346 -0
- data/config/syntax/DOT.json +79 -0
- data/config/syntax/Diff.json +136 -0
- data/config/syntax/Dylan.json +104 -0
- data/config/syntax/Eiffel.json +128 -0
- data/config/syntax/Erlang.json +1636 -0
- data/config/syntax/F-Script.json +137 -0
- data/config/syntax/FXScript.json +260 -0
- data/config/syntax/Gri.json +141 -0
- data/config/syntax/HTML (Mason).json +207 -0
- data/config/syntax/HTML (Rails).json +52 -0
- data/config/syntax/HTML (Tcl).json +42 -0
- data/config/syntax/HTML for ASP.net.json +736 -0
- data/config/syntax/HTML-ASP.json +45 -0
- data/config/syntax/HTML.json +614 -0
- data/config/syntax/Haskell.json +407 -0
- data/config/syntax/Inform.json +80 -0
- data/config/syntax/Ini.json +91 -0
- data/config/syntax/Io.json +142 -0
- data/config/syntax/Java.json +745 -0
- data/config/syntax/JavaProperties.json +42 -0
- data/config/syntax/JavaScript.json +446 -0
- data/config/syntax/LaTeX Beamer.json +65 -0
- data/config/syntax/LaTeX Log.json +88 -0
- data/config/syntax/LaTeX.json +962 -0
- data/config/syntax/Lighttpd.json +93 -0
- data/config/syntax/Lisp.json +101 -0
- data/config/syntax/Literate Haskell.json +55 -0
- data/config/syntax/Logtalk.json +289 -0
- data/config/syntax/Lua.json +146 -0
- data/config/syntax/M.json +744 -0
- data/config/syntax/MEL.json +161 -0
- data/config/syntax/MIPS.json +114 -0
- data/config/syntax/Mail.json +224 -0
- data/config/syntax/Makefile.json +66 -0
- data/config/syntax/Markdown.json +644 -0
- data/config/syntax/Modula-3.json +80 -0
- data/config/syntax/Movable Type.json +348 -0
- data/config/syntax/OCaml.json +1391 -0
- data/config/syntax/Objective-C++.json +21 -0
- data/config/syntax/OpenGL.json +24 -0
- data/config/syntax/PHP.json +2184 -0
- data/config/syntax/Pascal.json +128 -0
- data/config/syntax/Perl.json +2091 -0
- data/config/syntax/Plain text.json +49 -0
- data/config/syntax/Processing.json +188 -0
- data/config/syntax/Quake3 Config.json +54 -0
- data/config/syntax/R.json +157 -0
- data/config/syntax/Rez.json +137 -0
- data/config/syntax/Ruby on Rails.json +170 -0
- data/config/syntax/Ruby.json +1753 -0
- data/config/syntax/SQL (Rails).json +31 -0
- data/config/syntax/SQL.json +435 -0
- data/config/syntax/SWIG.json +96 -0
- data/config/syntax/Scheme.json +359 -0
- data/config/syntax/Shell-Unix-Generic.json +1198 -0
- data/config/syntax/Slate.json +265 -0
- data/config/syntax/Smarty.json +110 -0
- data/config/syntax/Standard ML.json +322 -0
- data/config/syntax/Subversion commit message.json +62 -0
- data/config/syntax/Tcl.json +278 -0
- data/config/syntax/TeX Math.json +83 -0
- data/config/syntax/TeX.json +157 -0
- data/config/syntax/Textile.json +273 -0
- data/config/syntax/Twiki.json +436 -0
- data/config/syntax/Vectorscript.json +97 -0
- data/config/syntax/XML strict.json +148 -0
- data/config/syntax/XML.json +301 -0
- data/config/syntax/XSL.json +96 -0
- data/config/syntax/YAML.json +293 -0
- data/config/syntax/iCalendar.json +51 -0
- data/config/syntax/reStructuredText.json +403 -0
- data/config/theme/Active4D.json +260 -0
- data/config/theme/All Hallow's Eve.json +171 -0
- data/config/theme/Amy.json +359 -0
- data/config/theme/BBEdit.json +269 -0
- data/config/theme/Bespin.json +322 -0
- data/config/theme/Blackboard.json +215 -0
- data/config/theme/BoysAndGirls01.json +156 -0
- data/config/theme/Brilliance Black.json +1695 -0
- data/config/theme/Brilliance Dull.json +1451 -0
- data/config/theme/Classic Modified.json +288 -0
- data/config/theme/Cobalt.json +345 -0
- data/config/theme/Cool Glow.json +215 -0
- data/config/theme/Dawn.json +258 -0
- data/config/theme/Eiffel.json +270 -0
- data/config/theme/Espresso Libre.json +247 -0
- data/config/theme/Fluidvision.json +272 -0
- data/config/theme/IDLE.json +159 -0
- data/config/theme/LAZY.json +178 -0
- data/config/theme/Mac Classic.json +277 -0
- data/config/theme/MagicWB (Amiga).json +231 -0
- data/config/theme/Merbivore Soft.json +181 -0
- data/config/theme/Merbivore.json +181 -0
- data/config/theme/Monokai.json +177 -0
- data/config/theme/Notepad2.json +166 -0
- data/config/theme/Pastels on Dark.json +437 -0
- data/config/theme/RubyBlue.json +226 -0
- data/config/theme/Sin City 2.json +361 -0
- data/config/theme/Slate.json +270 -0
- data/config/theme/Slush & Poppies.json +232 -0
- data/config/theme/SpaceCadet.json +143 -0
- data/config/theme/Sunburst.json +415 -0
- data/config/theme/Twilight BG FG.json +633 -0
- data/config/theme/Twilight.json +321 -0
- data/config/theme/Whys Poignant.json +119 -0
- data/config/theme/Zenburnesque.json +237 -0
- data/config/theme/barf.json +155 -0
- data/config/theme/fake.json +418 -0
- data/config/theme/happydeluxe.json +114 -0
- data/config/theme/iLife 05.json +393 -0
- data/config/theme/iPlastic.json +177 -0
- data/config/theme/mintBlue Dark.json +414 -0
- data/config/theme/mintBlue.json +415 -0
- data/config/theme/monoindustrial.json +276 -0
- data/config/theme/starlight.json +67 -0
- data/config/tutorial +74 -0
- data/config/welcome +115 -0
- data/help/index.verh +14 -0
- data/lib/ver.rb +156 -0
- data/lib/ver/entry.rb +97 -0
- data/lib/ver/keymap.rb +96 -0
- data/lib/ver/layout.rb +107 -0
- data/lib/ver/methods.rb +19 -0
- data/lib/ver/methods/completion.rb +116 -0
- data/lib/ver/methods/control.rb +340 -0
- data/lib/ver/methods/insert.rb +6 -0
- data/lib/ver/methods/move.rb +65 -0
- data/lib/ver/methods/search.rb +33 -0
- data/lib/ver/methods/select.rb +145 -0
- data/lib/ver/methods/views.rb +21 -0
- data/lib/ver/mode.rb +160 -0
- data/lib/ver/options.rb +207 -0
- data/lib/ver/plist.rb +106 -0
- data/lib/ver/status.rb +67 -0
- data/lib/ver/syntax.rb +68 -0
- data/lib/ver/syntax/detector.rb +53 -0
- data/lib/ver/syntax/processor.rb +48 -0
- data/lib/ver/text.rb +374 -0
- data/lib/ver/textpow.rb +357 -0
- data/lib/ver/theme.rb +162 -0
- data/lib/ver/vendor/fuzzy_file_finder.rb +340 -0
- data/lib/ver/view.rb +163 -0
- data/lib/ver/view/entry.rb +28 -0
- data/lib/ver/view/list.rb +137 -0
- data/lib/ver/view/list/buffer.rb +27 -0
- data/lib/ver/view/list/fuzzy_file_finder.rb +44 -0
- data/lib/ver/view/list/syntax.rb +13 -0
- data/lib/ver/view/list/theme.rb +13 -0
- data/spec/keymap.rb +224 -0
- data/tasks/bacon.rake +49 -0
- data/tasks/changelog.rake +18 -0
- data/tasks/gem.rake +22 -0
- data/tasks/gem_installer.rake +76 -0
- data/tasks/grancher.rake +12 -0
- data/tasks/install_dependencies.rake +6 -0
- data/tasks/manifest.rake +4 -0
- data/tasks/plist2json.rake +35 -0
- data/tasks/rcov.rake +18 -0
- data/tasks/release.rake +12 -0
- data/tasks/reversion.rake +8 -0
- data/tasks/syntax_list.rake +31 -0
- data/ver.gemspec +29 -0
- metadata +241 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
module VER
|
2
|
+
class View
|
3
|
+
# This sucks, should we go method_missing?
|
4
|
+
class Entry < VER::Entry
|
5
|
+
attr_accessor :list_view
|
6
|
+
|
7
|
+
def pick_first
|
8
|
+
list_view.pick_first
|
9
|
+
end
|
10
|
+
|
11
|
+
def pick_selection
|
12
|
+
list_view.pick_selection
|
13
|
+
end
|
14
|
+
|
15
|
+
def cancel
|
16
|
+
list_view.cancel
|
17
|
+
end
|
18
|
+
|
19
|
+
def go_line_up
|
20
|
+
list_view.go_line_up
|
21
|
+
end
|
22
|
+
|
23
|
+
def go_line_down
|
24
|
+
list_view.go_line_down
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
module VER
|
2
|
+
class View::List < Struct.new(:parent, :frame, :list, :entry, :tag, :callback)
|
3
|
+
autoload :Buffer, 'ver/view/list/buffer'
|
4
|
+
autoload :Window, 'ver/view/list/buffer'
|
5
|
+
autoload :FuzzyFileFinder, 'ver/view/list/fuzzy_file_finder'
|
6
|
+
autoload :Syntax, 'ver/view/list/syntax'
|
7
|
+
autoload :Theme, 'ver/view/list/theme'
|
8
|
+
|
9
|
+
def initialize(parent, &block)
|
10
|
+
self.parent, self.callback = parent, block
|
11
|
+
|
12
|
+
setup_widgets
|
13
|
+
setup_keymap
|
14
|
+
setup_events
|
15
|
+
on_update
|
16
|
+
end
|
17
|
+
|
18
|
+
def setup_widgets
|
19
|
+
self.frame = TkFrame.new{
|
20
|
+
pack fill: :both, expand: true
|
21
|
+
}
|
22
|
+
|
23
|
+
self.list = Tk::Listbox.new(frame){
|
24
|
+
setgrid 'yes'
|
25
|
+
width 0
|
26
|
+
background '#000'
|
27
|
+
foreground '#fff'
|
28
|
+
selectforeground '#000'
|
29
|
+
selectbackground '#fff'
|
30
|
+
font VER.options[:font]
|
31
|
+
pack fill: :both, expand: true
|
32
|
+
}
|
33
|
+
|
34
|
+
self.entry = View::Entry.new(frame){
|
35
|
+
pack fill: :x, expand: false
|
36
|
+
font VER.options[:font]
|
37
|
+
focus
|
38
|
+
}
|
39
|
+
entry.list_view = self
|
40
|
+
end
|
41
|
+
|
42
|
+
def setup_keymap
|
43
|
+
keymap_name = VER.options.fetch(:keymap)
|
44
|
+
|
45
|
+
@list_keymap = Keymap.get(
|
46
|
+
name: keymap_name, receiver: self, widget: list, mode: :list_view_list)
|
47
|
+
|
48
|
+
@entry_keymap = Keymap.get(
|
49
|
+
name: keymap_name, receiver: entry, widget: entry, mode: :list_view_entry)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Setup this event, because Keymap gets very confused when you bind 'Key' and
|
53
|
+
# we don't want to break the event-chain anyway
|
54
|
+
def setup_events
|
55
|
+
entry.bind('<Modified>'){ on_update }
|
56
|
+
end
|
57
|
+
|
58
|
+
def on_update
|
59
|
+
update
|
60
|
+
list.selection_set(0)
|
61
|
+
list.activate(0)
|
62
|
+
end
|
63
|
+
|
64
|
+
def quit
|
65
|
+
Tk.exit
|
66
|
+
end
|
67
|
+
|
68
|
+
def go_line_up
|
69
|
+
index = list.curselection.first - 1
|
70
|
+
|
71
|
+
if index >= 0
|
72
|
+
list.selection_clear(0, 'end')
|
73
|
+
select_index(index)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def go_line_down
|
78
|
+
index = list.curselection.first + 1
|
79
|
+
max = list.size
|
80
|
+
|
81
|
+
if index < max
|
82
|
+
list.selection_clear(0, 'end')
|
83
|
+
select_index(index)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def select_index(index)
|
88
|
+
list.selection_set(index)
|
89
|
+
list.activate(index)
|
90
|
+
list.see(index)
|
91
|
+
end
|
92
|
+
|
93
|
+
def cancel
|
94
|
+
destroy
|
95
|
+
end
|
96
|
+
|
97
|
+
def destroy
|
98
|
+
entry.destroy
|
99
|
+
list.destroy
|
100
|
+
frame.destroy
|
101
|
+
parent.focus
|
102
|
+
end
|
103
|
+
|
104
|
+
def sublist(list, input = entry.value)
|
105
|
+
if input == input.downcase
|
106
|
+
list.select{|item| item.to_s.downcase.include?(input) }
|
107
|
+
else
|
108
|
+
list.select{|item| item.to_s.include?(input) }
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def pick(item)
|
113
|
+
if list.size > 0
|
114
|
+
pick_action(item)
|
115
|
+
destroy
|
116
|
+
else
|
117
|
+
message "VER is confused, what did you actually want to do?"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def pick_first
|
122
|
+
pick list.get(0)
|
123
|
+
end
|
124
|
+
|
125
|
+
def pick_selection
|
126
|
+
pick TkSelection.get
|
127
|
+
end
|
128
|
+
|
129
|
+
def pick_action(item)
|
130
|
+
callback.call(item) if callback
|
131
|
+
end
|
132
|
+
|
133
|
+
def message(string)
|
134
|
+
parent.status.message(string)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module VER
|
2
|
+
class View::List::Window < View::List
|
3
|
+
def update
|
4
|
+
list.value = sublist(windows.keys)
|
5
|
+
end
|
6
|
+
|
7
|
+
def windows
|
8
|
+
path_view = parent.layout.views.map{|view| [view.filename.to_s, view] }
|
9
|
+
Hash[path_view]
|
10
|
+
end
|
11
|
+
|
12
|
+
def pick_action(filename)
|
13
|
+
view = windows[filename]
|
14
|
+
callback.call(view) if callback && view
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class View::List::Buffer < View::List
|
19
|
+
def update
|
20
|
+
list.value = sublist(buffers)
|
21
|
+
end
|
22
|
+
|
23
|
+
def buffers
|
24
|
+
VER.paths.map(&:to_s).select {|b| ! b.empty? }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'ver/vendor/fuzzy_file_finder'
|
2
|
+
|
3
|
+
module VER
|
4
|
+
class View::List::FuzzyFileFinder < View::List
|
5
|
+
FFF = ::FuzzyFileFinder
|
6
|
+
|
7
|
+
def fffinder
|
8
|
+
@fffinder ||= FFF.new(Dir.pwd)
|
9
|
+
rescue FFF::TooManyEntries
|
10
|
+
message "The FuzzyFileFinder is overwhelmed by the amount of files"
|
11
|
+
destroy
|
12
|
+
end
|
13
|
+
|
14
|
+
def update
|
15
|
+
choices = fffinder.find(entry.value.chomp('/'))
|
16
|
+
choices = choices.sort_by{|m| [-m[:score], m[:path]] }
|
17
|
+
|
18
|
+
list.clear
|
19
|
+
|
20
|
+
pwd = Dir.pwd + '/'
|
21
|
+
choices.each do |choice|
|
22
|
+
choice[:path].sub!(pwd, '')
|
23
|
+
insert_choice(choice)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def insert_choice(choice)
|
28
|
+
path, score = choice.values_at(:path, :score)
|
29
|
+
list.insert(:end, path)
|
30
|
+
|
31
|
+
foreground, background =
|
32
|
+
case score
|
33
|
+
when 0 ; ['white', 'black']
|
34
|
+
when 0 ..0.25 ; ['red', 'black']
|
35
|
+
when 0.25..0.75 ; ['yellow', 'black']
|
36
|
+
when 0.75..1 ; ['green', 'black']
|
37
|
+
end
|
38
|
+
|
39
|
+
list.itemconfigure(:end,
|
40
|
+
foreground: foreground, background: background,
|
41
|
+
selectforeground: background, selectbackground: foreground)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/spec/keymap.rb
ADDED
@@ -0,0 +1,224 @@
|
|
1
|
+
require 'bacon'
|
2
|
+
Bacon.summary_on_exit
|
3
|
+
|
4
|
+
module VER
|
5
|
+
class Keyboard
|
6
|
+
end
|
7
|
+
|
8
|
+
class Keymap
|
9
|
+
attr_accessor :modes, :current_mode
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@modes = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def send(*args)
|
16
|
+
@callback.__send__(*args)
|
17
|
+
end
|
18
|
+
|
19
|
+
def enter_key(key)
|
20
|
+
modes[current_mode].enter_key key
|
21
|
+
end
|
22
|
+
|
23
|
+
# TODO: callbacks
|
24
|
+
def current_mode=(cm)
|
25
|
+
@current_mode = cm.to_sym
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_mode(name)
|
29
|
+
@modes[name.to_sym] = mode = Mode.new(self)
|
30
|
+
yield mode if block_given?
|
31
|
+
mode
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Mode
|
36
|
+
def initialize(callback = nil)
|
37
|
+
@callback = callback
|
38
|
+
@stack = []
|
39
|
+
@map = {}
|
40
|
+
@ancestors = []
|
41
|
+
end
|
42
|
+
|
43
|
+
def inherit(other)
|
44
|
+
@ancestors.delete other
|
45
|
+
@ancestors.unshift other
|
46
|
+
end
|
47
|
+
|
48
|
+
def ancestors(&block)
|
49
|
+
([self] + @ancestors).find(&block)
|
50
|
+
end
|
51
|
+
|
52
|
+
def map(sym, *keychain)
|
53
|
+
bind(*keychain.flatten){|*arg| @callback.send(sym, *arg) }
|
54
|
+
end
|
55
|
+
|
56
|
+
def bind(*keychain, &block)
|
57
|
+
keychain = keychain.dup
|
58
|
+
total = hash = {}
|
59
|
+
|
60
|
+
while key = keychain.shift
|
61
|
+
if keychain.empty?
|
62
|
+
hash[key] = block
|
63
|
+
else
|
64
|
+
hash = hash[key] = {}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
@map.replace @map.merge(total, &MERGER)
|
69
|
+
end
|
70
|
+
|
71
|
+
def enter_keys(*keys)
|
72
|
+
keys.flatten.each{|key| enter_key(key) }
|
73
|
+
end
|
74
|
+
|
75
|
+
def enter_key(key)
|
76
|
+
@stack << key
|
77
|
+
ancestors{|ancestor| ancestor.attempt_execute(@stack) }
|
78
|
+
end
|
79
|
+
|
80
|
+
def attempt_execute(original_stack)
|
81
|
+
stack, arg = Mode.split_stack(original_stack)
|
82
|
+
return false if stack.empty?
|
83
|
+
|
84
|
+
executable = stack.inject(@map){|keys, key| keys.fetch(key) }
|
85
|
+
|
86
|
+
if execute(executable, *arg)
|
87
|
+
original_stack.clear
|
88
|
+
return true
|
89
|
+
end
|
90
|
+
|
91
|
+
false
|
92
|
+
rescue KeyError
|
93
|
+
false
|
94
|
+
end
|
95
|
+
|
96
|
+
def execute(executable, *arg)
|
97
|
+
case executable
|
98
|
+
when Proc
|
99
|
+
executable.call(*arg)
|
100
|
+
true
|
101
|
+
when Symbol
|
102
|
+
@callback.send(executable, *arg)
|
103
|
+
else
|
104
|
+
false
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.split_stack(stack)
|
109
|
+
return stack, nil if stack[0] == '0'
|
110
|
+
|
111
|
+
pivot = stack.index{|c| c !~ /\d/ }
|
112
|
+
|
113
|
+
if pivot == 0
|
114
|
+
return stack, nil
|
115
|
+
elsif pivot
|
116
|
+
return stack[pivot..-1], stack[0..pivot].join.to_i
|
117
|
+
else
|
118
|
+
return [], nil
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
MERGER = proc{|key,v1,v2|
|
123
|
+
Hash === v1 && Hash === v2 ? v1.merge(v2, &MERGER) : v2
|
124
|
+
}
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe Mode = VER::Mode do
|
129
|
+
it 'splits stack into argument and keychain' do
|
130
|
+
Mode.split_stack(['4', 'a']).should == [['a'], 4]
|
131
|
+
Mode.split_stack(['4', '2', 'a']).should == [['a'], 42]
|
132
|
+
Mode.split_stack(['4', '2', 'a', 'b']).should == [['a', 'b'], 42]
|
133
|
+
Mode.split_stack(['a', 'b']).should == [['a', 'b'], nil]
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'executes action assigned to key' do
|
137
|
+
done = false
|
138
|
+
mode = Mode.new
|
139
|
+
mode.bind('a'){ done = true }
|
140
|
+
mode.enter_keys 'a'
|
141
|
+
done.should == true
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'executes action assigned to key chain (immediately)' do
|
145
|
+
done = false
|
146
|
+
mode = Mode.new
|
147
|
+
mode.bind('a', 'b', 'c'){ done = true }
|
148
|
+
mode.enter_keys 'a', 'b', 'c'
|
149
|
+
done.should == true
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'executes action assigned to key chain (delayed)' do
|
153
|
+
done = false
|
154
|
+
mode = Mode.new
|
155
|
+
mode.bind('a', 'b', 'c'){ done = true }
|
156
|
+
mode.enter_key 'a'
|
157
|
+
mode.enter_key 'b'
|
158
|
+
mode.enter_key 'c'
|
159
|
+
done.should == true
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'executes action with numeric argument' do
|
163
|
+
done = false
|
164
|
+
mode = Mode.new
|
165
|
+
mode.bind('a', 'b', 'c'){|arg| done = arg }
|
166
|
+
mode.enter_keys '4', '2', 'a', 'b', 'c'
|
167
|
+
done.should == 42
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'executes action on callback' do
|
171
|
+
done = false
|
172
|
+
callback = Class.new{
|
173
|
+
attr_accessor :done
|
174
|
+
|
175
|
+
def foo
|
176
|
+
@done = true
|
177
|
+
end
|
178
|
+
}.new
|
179
|
+
|
180
|
+
mode = Mode.new(callback)
|
181
|
+
mode.map :foo, %w[a b c]
|
182
|
+
mode.enter_keys %w[a b c]
|
183
|
+
callback.done.should == true
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'inherits another mode but executes actions itself' do
|
187
|
+
first_done = second_done = false
|
188
|
+
first, second = Mode.new, Mode.new
|
189
|
+
second.inherit(first)
|
190
|
+
second.bind('a', 'b', 'c'){|arg| second_done = arg }
|
191
|
+
second.enter_keys %w[4 2 a b c]
|
192
|
+
second_done.should == 42
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'inherits another mode that also executes actions' do
|
196
|
+
first_done = second_done = false
|
197
|
+
first, second = Mode.new, Mode.new
|
198
|
+
second.inherit(first)
|
199
|
+
|
200
|
+
first.bind('first-key'){|arg| first_done = arg }
|
201
|
+
second.bind('second-key'){|arg| second_done = arg }
|
202
|
+
|
203
|
+
second.enter_keys %w[4 2 first-key]
|
204
|
+
first_done.should == 42
|
205
|
+
|
206
|
+
second.enter_keys %w[2 4 second-key]
|
207
|
+
second_done.should == 24
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
describe Keymap = VER::Keymap do
|
212
|
+
it 'adds a mode into the keymap' do
|
213
|
+
done = false
|
214
|
+
|
215
|
+
keymap = Keymap.new
|
216
|
+
keymap.add_mode :test do |mode|
|
217
|
+
mode.bind('a'){ done = true }
|
218
|
+
end
|
219
|
+
keymap.current_mode = :test
|
220
|
+
|
221
|
+
keymap.enter_key 'a'
|
222
|
+
done.should == true
|
223
|
+
end
|
224
|
+
end
|