ver 2009.11.29 → 2009.12.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/AUTHORS +6 -0
- data/CHANGELOG +353 -1
- data/LICENSE +18 -0
- data/MANIFEST +11 -1
- data/Rakefile +2 -1
- data/bin/ver +3 -12
- data/config/detect.rb +1 -1
- data/config/keymap/diakonos.rb +181 -0
- data/config/keymap/emacs.rb +24 -24
- data/config/keymap/vim.rb +162 -127
- data/config/rc.rb +29 -14
- data/config/syntax/Nemerle.json +3 -3
- data/lib/ver.rb +88 -134
- data/lib/ver/entry.rb +5 -0
- data/lib/ver/exception_view.rb +97 -0
- data/lib/ver/hover_completion.rb +14 -7
- data/lib/ver/keymap.rb +30 -1
- data/lib/ver/layout.rb +20 -14
- data/lib/ver/methods.rb +6 -15
- data/lib/ver/methods/bookmark.rb +189 -0
- data/lib/ver/methods/completion.rb +2 -2
- data/lib/ver/methods/control.rb +109 -26
- data/lib/ver/methods/ctags.rb +28 -4
- data/lib/ver/methods/delete.rb +85 -4
- data/lib/ver/methods/insert.rb +73 -52
- data/lib/ver/methods/move.rb +122 -35
- data/lib/ver/methods/open.rb +4 -43
- data/lib/ver/methods/search.rb +46 -17
- data/lib/ver/methods/select.rb +121 -24
- data/lib/ver/methods/undo.rb +23 -0
- data/lib/ver/methods/views.rb +5 -0
- data/lib/ver/mode.rb +18 -17
- data/lib/ver/status.rb +2 -2
- data/lib/ver/status/context.rb +166 -0
- data/lib/ver/text.rb +43 -81
- data/lib/ver/text/index.rb +24 -7
- data/lib/ver/undo.rb +289 -0
- data/lib/ver/vendor/sized_array.rb +70 -0
- data/lib/ver/vendor/textpow.rb +6 -1
- data/lib/ver/version.rb +3 -0
- data/lib/ver/view.rb +11 -8
- data/lib/ver/view/list/grep.rb +15 -4
- data/lib/ver/view/term.rb +9 -3
- data/spec/helper.rb +94 -0
- data/ver.gemspec +9 -6
- metadata +25 -5
- data/spec/keymap.rb +0 -224
data/lib/ver/methods/open.rb
CHANGED
@@ -37,7 +37,8 @@ module VER
|
|
37
37
|
self.filename = path
|
38
38
|
|
39
39
|
begin
|
40
|
-
|
40
|
+
clear
|
41
|
+
insert 1.0, read_file(filename)
|
41
42
|
message "Opened #{short_filename}"
|
42
43
|
rescue Errno::ENOENT
|
43
44
|
delete '1.0', :end
|
@@ -81,6 +82,8 @@ module VER
|
|
81
82
|
mark_set :insert, "#{line.to_i}.0"
|
82
83
|
@pristine = false
|
83
84
|
|
85
|
+
@undoer = VER::Undo::Tree.new(self)
|
86
|
+
|
84
87
|
bind('<Map>') do
|
85
88
|
defer do
|
86
89
|
setup_highlight
|
@@ -152,9 +155,6 @@ module VER
|
|
152
155
|
options[option] = value
|
153
156
|
yield(value) if block_given?
|
154
157
|
end
|
155
|
-
|
156
|
-
require 'pp'
|
157
|
-
pp options
|
158
158
|
end
|
159
159
|
|
160
160
|
def set_filetype(type)
|
@@ -167,42 +167,3 @@ module VER
|
|
167
167
|
end
|
168
168
|
end
|
169
169
|
end
|
170
|
-
|
171
|
-
=begin
|
172
|
-
There are two forms of modelines. The first form:
|
173
|
-
[text]{white}{vi:|vim:|ex:}[white]{options}
|
174
|
-
|
175
|
-
[text] any text or empty
|
176
|
-
{white} at least one blank character (<Space> or <Tab>)
|
177
|
-
{vi:|vim:|ex:} the string "vi:", "vim:" or "ex:"
|
178
|
-
[white] optional white space
|
179
|
-
{options} a list of option settings, separated with white space or ':',
|
180
|
-
where each part between ':' is the argument for a ":set"
|
181
|
-
command (can be empty)
|
182
|
-
|
183
|
-
Example:
|
184
|
-
vi:noai:sw=3 ts=6 ~
|
185
|
-
|
186
|
-
The second form (this is compatible with some versions of Vi):
|
187
|
-
|
188
|
-
[text]{white}{vi:|vim:|ex:}[white]se[t] {options}:[text]
|
189
|
-
|
190
|
-
[text] any text or empty
|
191
|
-
{white} at least one blank character (<Space> or <Tab>)
|
192
|
-
{vi:|vim:|ex:} the string "vi:", "vim:" or "ex:"
|
193
|
-
[white] optional white space
|
194
|
-
se[t] the string "set " or "se " (note the space)
|
195
|
-
{options} a list of options, separated with white space, which is the
|
196
|
-
argument for a ":set" command
|
197
|
-
: a colon
|
198
|
-
[text] any text or empty
|
199
|
-
|
200
|
-
Example:
|
201
|
-
/* vim: set ai tw=75: */ ~
|
202
|
-
|
203
|
-
The white space before {vi:|vim:|ex:} is required. This minimizes the chance
|
204
|
-
that a normal word like "lex:" is caught. There is one exception: "vi:" and
|
205
|
-
"vim:" can also be at the start of the line (for compatibility with version
|
206
|
-
3.0). Using "ex:" at the start of the line will be ignored (this could be
|
207
|
-
short for "example:").
|
208
|
-
=end
|
data/lib/ver/methods/search.rb
CHANGED
@@ -7,40 +7,65 @@ module VER
|
|
7
7
|
}
|
8
8
|
|
9
9
|
def status_search_next
|
10
|
-
status_search_common('/')
|
11
|
-
search_next
|
12
|
-
end
|
10
|
+
status_search_common('/'){ search_next }
|
13
11
|
end
|
14
12
|
|
15
13
|
def status_search_prev
|
16
|
-
status_search_common('?')
|
17
|
-
search_prev
|
18
|
-
end
|
14
|
+
status_search_common('?'){ search_prev }
|
19
15
|
end
|
20
16
|
|
21
17
|
def status_search_common(question)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
rescue RegexpError
|
26
|
-
needle = Regexp.escape(term)
|
27
|
-
end
|
18
|
+
status.bind('<<Modified>>') do
|
19
|
+
search_incremental(status.value)
|
20
|
+
end
|
28
21
|
|
29
|
-
|
22
|
+
status_ask question do |term|
|
23
|
+
status.bind('<<Modified>>'){ }
|
24
|
+
search_incremental(term, force = true)
|
25
|
+
search_prev
|
30
26
|
yield
|
31
27
|
end
|
32
28
|
end
|
33
29
|
|
34
|
-
def
|
35
|
-
|
30
|
+
def search_incremental(term, force = false)
|
31
|
+
return if !term || term.empty?
|
32
|
+
return if !force && term.size <= options.search_incremental_min
|
33
|
+
|
34
|
+
begin
|
35
|
+
needle = Regexp.new(term)
|
36
|
+
rescue RegexpError, SyntaxError
|
37
|
+
needle = Regexp.escape(term)
|
38
|
+
end
|
39
|
+
|
40
|
+
tag_all_matching(:search, needle, SEARCH_HIGHLIGHT)
|
41
|
+
from, to = tag_nextrange('search', '1.0', 'end')
|
42
|
+
see(from) if from
|
43
|
+
end
|
44
|
+
|
45
|
+
def search_first
|
46
|
+
from, to = tag_nextrange('search', '1.0', 'end')
|
36
47
|
mark_set(:insert, from) if from
|
37
48
|
end
|
38
49
|
|
39
|
-
def
|
40
|
-
from, to = tag_prevrange('search', '
|
50
|
+
def search_last
|
51
|
+
from, to = tag_prevrange('search', 'end', '1.0')
|
41
52
|
mark_set(:insert, from) if from
|
42
53
|
end
|
43
54
|
|
55
|
+
def search_next(count = 1)
|
56
|
+
count.times do
|
57
|
+
from, to = tag_nextrange('search', 'insert + 1 chars', 'end')
|
58
|
+
mark_set(:insert, from) if from
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def search_prev(count = 1)
|
63
|
+
count.times do
|
64
|
+
from, to = tag_prevrange('search', 'insert - 1 chars', '1.0')
|
65
|
+
mark_set(:insert, from) if from
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
44
69
|
def search_next_word_under_cursor
|
45
70
|
word = get('insert wordstart', 'insert wordend')
|
46
71
|
return if word.squeeze == ' ' # we don't want to match space
|
@@ -78,6 +103,10 @@ module VER
|
|
78
103
|
end
|
79
104
|
end
|
80
105
|
end
|
106
|
+
|
107
|
+
def search_clear
|
108
|
+
tag_remove('search', '1.0', 'end')
|
109
|
+
end
|
81
110
|
end
|
82
111
|
end
|
83
112
|
end
|
data/lib/ver/methods/select.rb
CHANGED
@@ -48,6 +48,7 @@ module VER
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
# Delete selection without copying it.
|
51
52
|
def delete_selection
|
52
53
|
queue = tag_ranges(:sel).flatten
|
53
54
|
delete(*queue)
|
@@ -56,22 +57,32 @@ module VER
|
|
56
57
|
finish_selection
|
57
58
|
end
|
58
59
|
|
60
|
+
# Copy selection and delete it.
|
61
|
+
def kill_selection
|
62
|
+
queue = tag_ranges(:sel).flatten
|
63
|
+
kill(*queue)
|
64
|
+
mark_set(:insert, queue.first)
|
65
|
+
|
66
|
+
finish_selection
|
67
|
+
end
|
68
|
+
|
59
69
|
def indent_selection
|
60
|
-
indent_size =
|
70
|
+
indent_size = options.shiftwidth
|
61
71
|
indent = ' ' * indent_size
|
62
72
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
73
|
+
undo_record do |record|
|
74
|
+
each_selected_line do |y, fx, tx|
|
75
|
+
tx = fx + indent_size
|
76
|
+
next if get("#{y}.#{fx}", "#{y}.#{tx}").empty?
|
77
|
+
record.insert("#{y}.#{fx}", indent)
|
78
|
+
end
|
67
79
|
end
|
68
80
|
|
69
|
-
edit_separator
|
70
81
|
refresh_selection
|
71
82
|
end
|
72
83
|
|
73
84
|
def unindent_selection
|
74
|
-
indent_size =
|
85
|
+
indent_size = options.shiftwidth
|
75
86
|
indent = ' ' * indent_size
|
76
87
|
queue = []
|
77
88
|
|
@@ -83,7 +94,6 @@ module VER
|
|
83
94
|
end
|
84
95
|
|
85
96
|
delete(*queue)
|
86
|
-
edit_separator
|
87
97
|
refresh_selection
|
88
98
|
end
|
89
99
|
|
@@ -113,20 +123,46 @@ module VER
|
|
113
123
|
end
|
114
124
|
|
115
125
|
def comment_selection
|
126
|
+
comment = "#{options.comment_line} "
|
127
|
+
indent = nil
|
128
|
+
lines = []
|
129
|
+
|
116
130
|
each_selected_line do |y, fx, tx|
|
117
|
-
|
131
|
+
lines << y
|
132
|
+
|
133
|
+
next if indent == 0 # can't get lower
|
134
|
+
|
135
|
+
line = get("#{y}.#{fx}", "#{y}.#{tx}")
|
136
|
+
|
137
|
+
next unless start = line =~ /\S/
|
138
|
+
|
139
|
+
indent ||= start
|
140
|
+
indent = start if start < indent
|
141
|
+
end
|
142
|
+
|
143
|
+
lines.each do |y|
|
144
|
+
insert("#{y}.#{indent}", comment)
|
118
145
|
end
|
119
146
|
|
120
|
-
|
147
|
+
undo_separator
|
121
148
|
refresh_selection
|
122
149
|
end
|
123
150
|
|
124
151
|
def uncomment_selection
|
125
|
-
|
126
|
-
|
152
|
+
comment = "#{options.comment_line} "
|
153
|
+
regex = /#{Regexp.escape(comment)}/
|
154
|
+
|
155
|
+
undo_record do |record|
|
156
|
+
each_selected_line do |y, fx, tx|
|
157
|
+
from, to = "#{y}.#{fx}", "#{y}.#{tx}"
|
158
|
+
line = get(from, to)
|
159
|
+
|
160
|
+
if line.sub!(regex, '')
|
161
|
+
record.replace(from, to, line)
|
162
|
+
end
|
163
|
+
end
|
127
164
|
end
|
128
165
|
|
129
|
-
edit_separator
|
130
166
|
refresh_selection
|
131
167
|
end
|
132
168
|
|
@@ -152,30 +188,52 @@ module VER
|
|
152
188
|
end
|
153
189
|
end
|
154
190
|
|
191
|
+
def replace_selection_with_clipboard
|
192
|
+
string = clipboard_get
|
193
|
+
ranges = tag_ranges(:sel)
|
194
|
+
from, to = ranges.first.first, ranges.last.last
|
195
|
+
replace(from, to, string)
|
196
|
+
finish_selection
|
197
|
+
mark_set :insert, from
|
198
|
+
end
|
199
|
+
|
200
|
+
def refresh_selection
|
201
|
+
return unless start = selection_start
|
202
|
+
|
203
|
+
tag_remove :sel, 1.0, :end
|
204
|
+
|
205
|
+
case selection_mode
|
206
|
+
when :select_char; refresh_selection_char(start)
|
207
|
+
when :select_line; refresh_selection_line(start)
|
208
|
+
when :select_block; refresh_selection_block(start)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
155
212
|
private
|
156
213
|
|
157
214
|
# TODO: find better name for +full+
|
158
215
|
def replace_selection_with(string, full)
|
159
216
|
origin = index(:insert)
|
160
217
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
218
|
+
undo_record do |record|
|
219
|
+
if full
|
220
|
+
each_selected_line do |y, fx, tx|
|
221
|
+
diff = tx - fx
|
222
|
+
record.replace("#{y}.#{fx}", "#{y}.#{tx}", string * diff)
|
223
|
+
end
|
224
|
+
else
|
225
|
+
string_size = string.size
|
226
|
+
each_selected_line do |y, fx, tx|
|
227
|
+
record.replace("#{y}.#{fx}", "#{y}.#{tx}", string)
|
228
|
+
end
|
170
229
|
end
|
171
230
|
end
|
172
231
|
|
173
|
-
edit_separator
|
174
232
|
mark_set :insert, origin
|
175
233
|
end
|
176
234
|
|
177
235
|
def finish_selection(mode = nil)
|
178
|
-
|
236
|
+
undo_separator
|
179
237
|
clear_selection
|
180
238
|
mode ? self.mode = mode : keymap.use_previous_mode
|
181
239
|
apply_mode_style(keymap.mode)
|
@@ -220,6 +278,45 @@ module VER
|
|
220
278
|
insert(queue.first, output)
|
221
279
|
end
|
222
280
|
end
|
281
|
+
|
282
|
+
# FIXME: yes, i know i'm calling `tag add` for every line, which makes
|
283
|
+
# things slower, but it seems like there is a bug in the text widget.
|
284
|
+
# So we aggregate the information into a single eval.
|
285
|
+
def refresh_selection_block(start)
|
286
|
+
ly, lx, ry, rx =
|
287
|
+
if compare('insert', '>', start)
|
288
|
+
[*index('insert').split, *start.split]
|
289
|
+
else
|
290
|
+
[*start.split, *index('insert').split]
|
291
|
+
end
|
292
|
+
|
293
|
+
from_y, to_y = [ly, ry].sort
|
294
|
+
from_x, to_x = [lx, rx].sort
|
295
|
+
|
296
|
+
code = [%(set win "#{tk_pathname}")]
|
297
|
+
|
298
|
+
from_y.upto to_y do |y|
|
299
|
+
code << "$win tag add sel #{y}.#{from_x} #{y}.#{to_x + 1}"
|
300
|
+
end
|
301
|
+
|
302
|
+
Tk.execute_only(Tk::TclString.new(code.join("\n")))
|
303
|
+
end
|
304
|
+
|
305
|
+
def refresh_selection_char(start)
|
306
|
+
if compare('insert', '>', start)
|
307
|
+
tag_add :sel, start, "insert + 1 chars"
|
308
|
+
else
|
309
|
+
tag_add :sel, "insert", "#{start} + 1 chars"
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
def refresh_selection_line(start)
|
314
|
+
if compare('insert', '>', start)
|
315
|
+
tag_add :sel, "#{start} linestart", 'insert lineend'
|
316
|
+
else
|
317
|
+
tag_add :sel, 'insert linestart', "#{start} lineend"
|
318
|
+
end
|
319
|
+
end
|
223
320
|
end
|
224
321
|
end
|
225
322
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module VER
|
2
|
+
module Methods
|
3
|
+
module Undo
|
4
|
+
def redo
|
5
|
+
undoer.redo
|
6
|
+
end
|
7
|
+
|
8
|
+
def undo
|
9
|
+
undoer.undo
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def undo_record(&block)
|
15
|
+
undoer.record_multi(&block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def undo_separator
|
19
|
+
undoer.separate!
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/ver/methods/views.rb
CHANGED
data/lib/ver/mode.rb
CHANGED
@@ -20,7 +20,7 @@ module VER
|
|
20
20
|
@map = {}
|
21
21
|
@ancestors = []
|
22
22
|
@missing = nil
|
23
|
-
@arguments =
|
23
|
+
@arguments = callback.arguments
|
24
24
|
end
|
25
25
|
|
26
26
|
def inherits(*others)
|
@@ -58,7 +58,7 @@ module VER
|
|
58
58
|
bind(keychain.flatten, sym)
|
59
59
|
end
|
60
60
|
end
|
61
|
-
alias
|
61
|
+
alias key map
|
62
62
|
|
63
63
|
def bind(keychain, action_name = nil, &block)
|
64
64
|
keychain = keychain.dup
|
@@ -137,23 +137,24 @@ module VER
|
|
137
137
|
|
138
138
|
case executable
|
139
139
|
when nil
|
140
|
+
return false unless previous.respond_to?(:find)
|
141
|
+
|
140
142
|
# FIXME: this allows only one mode
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
return nil
|
150
|
-
else
|
151
|
-
cmd, cmd_arg = looked
|
152
|
-
return nil if cmd.is_a?(Hash)
|
153
|
-
return execute(action, cmd, arg)
|
154
|
-
end
|
155
|
-
else
|
143
|
+
found = previous.find{|prev_key, prev_value| prev_key.is_a?(Mode) }
|
144
|
+
return false unless found
|
145
|
+
|
146
|
+
mode, action = found
|
147
|
+
looked = mode.attempt_execute([key, *stack], true)
|
148
|
+
|
149
|
+
case looked
|
150
|
+
when false
|
156
151
|
return false
|
152
|
+
when nil
|
153
|
+
return nil
|
154
|
+
else
|
155
|
+
cmd, cmd_arg = looked
|
156
|
+
return nil if cmd.is_a?(Hash)
|
157
|
+
return execute(action, cmd, arg)
|
157
158
|
end
|
158
159
|
end
|
159
160
|
end
|