ver 2009.10.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|