vimamsa 0.1.12 → 0.1.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/custom_example.rb +5 -0
- data/lib/vimamsa/ack.rb +5 -5
- data/lib/vimamsa/actions.rb +13 -6
- data/lib/vimamsa/audio.rb +82 -0
- data/lib/vimamsa/buffer.rb +73 -566
- data/lib/vimamsa/buffer_changetext.rb +255 -0
- data/lib/vimamsa/buffer_cursor.rb +303 -0
- data/lib/vimamsa/buffer_list.rb +26 -9
- data/lib/vimamsa/buffer_manager.rb +4 -2
- data/lib/vimamsa/clipboard.rb +35 -0
- data/lib/vimamsa/conf.rb +130 -5
- data/lib/vimamsa/debug.rb +4 -8
- data/lib/vimamsa/editor.rb +61 -125
- data/lib/vimamsa/encrypt.rb +6 -11
- data/lib/vimamsa/file_manager.rb +138 -9
- data/lib/vimamsa/gui.rb +11 -59
- data/lib/vimamsa/gui_dialog.rb +113 -0
- data/lib/vimamsa/gui_select_window.rb +9 -8
- data/lib/vimamsa/gui_sourceview.rb +110 -48
- data/lib/vimamsa/gui_text.rb +19 -0
- data/lib/vimamsa/hyper_plain_text.rb +15 -5
- data/lib/vimamsa/key_actions.rb +19 -195
- data/lib/vimamsa/key_binding_tree.rb +57 -33
- data/lib/vimamsa/key_bindings_vimlike.rb +39 -26
- data/lib/vimamsa/macro.rb +35 -25
- data/lib/vimamsa/main.rb +3 -17
- data/lib/vimamsa/rbvma.rb +11 -17
- data/lib/vimamsa/search.rb +1 -1
- data/lib/vimamsa/search_replace.rb +93 -131
- data/lib/vimamsa/terminal.rb +22 -0
- data/lib/vimamsa/tests.rb +122 -0
- data/lib/vimamsa/util.rb +87 -2
- data/lib/vimamsa/version.rb +1 -1
- data/vimamsa.gemspec +3 -1
- metadata +57 -7
- /data/lib/vimamsa/{form_generator.rb → gui_form_generator.rb} +0 -0
@@ -0,0 +1,255 @@
|
|
1
|
+
# Operations that change the content of the buffer
|
2
|
+
# e.g. insert, delete
|
3
|
+
|
4
|
+
class Buffer < String
|
5
|
+
|
6
|
+
#TODO: change to apply=true as default
|
7
|
+
def add_delta(delta, apply = false, auto_update_cpos = false)
|
8
|
+
return if !is_delta_ok(delta)
|
9
|
+
if delta[1] == DELETE
|
10
|
+
return if delta[0] >= self.size
|
11
|
+
# If go over length of buffer
|
12
|
+
if delta[0] + delta[2] >= self.size
|
13
|
+
delta[2] = self.size - delta[0]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
@edit_version += 1
|
18
|
+
@redo_stack = []
|
19
|
+
if apply
|
20
|
+
delta = run_delta(delta, auto_update_cpos)
|
21
|
+
else
|
22
|
+
@deltas << delta
|
23
|
+
end
|
24
|
+
@edit_history << delta
|
25
|
+
if self[-1] != "\n"
|
26
|
+
add_delta([self.size, INSERT, 1, "\n"], true)
|
27
|
+
end
|
28
|
+
reset_larger_cpos #TODO: correct here?
|
29
|
+
end
|
30
|
+
|
31
|
+
# TODO: rename ot auto-format. separate module?
|
32
|
+
# Indents whole buffer using external program
|
33
|
+
def indent()
|
34
|
+
file = Tempfile.new("out")
|
35
|
+
infile = Tempfile.new("in")
|
36
|
+
file.write(self.to_s)
|
37
|
+
file.flush
|
38
|
+
bufc = "FOO"
|
39
|
+
|
40
|
+
tmppos = @pos
|
41
|
+
|
42
|
+
message("Auto format #{@fname}")
|
43
|
+
|
44
|
+
ftype = get_file_type()
|
45
|
+
if ["chdr", "c", "cpp", "cpphdr"].include?(ftype)
|
46
|
+
|
47
|
+
#C/C++/Java/JavaScript/Objective-C/Protobuf code
|
48
|
+
system("clang-format -style='{BasedOnStyle: LLVM, ColumnLimit: 100, SortIncludes: false}' #{file.path} > #{infile.path}")
|
49
|
+
bufc = IO.read(infile.path)
|
50
|
+
elsif ftype == "Javascript"
|
51
|
+
cmd = "clang-format #{file.path} > #{infile.path}'"
|
52
|
+
debug cmd
|
53
|
+
system(cmd)
|
54
|
+
bufc = IO.read(infile.path)
|
55
|
+
elsif ftype == "ruby"
|
56
|
+
cmd = "rufo #{file.path}"
|
57
|
+
debug cmd
|
58
|
+
system(cmd)
|
59
|
+
bufc = IO.read(file.path)
|
60
|
+
else
|
61
|
+
message("No auto-format handler for file of type: #{ftype}")
|
62
|
+
return
|
63
|
+
end
|
64
|
+
self.update_content(bufc)
|
65
|
+
center_on_current_line #TODO: needed?
|
66
|
+
file.close; file.unlink
|
67
|
+
infile.close; infile.unlink
|
68
|
+
end
|
69
|
+
|
70
|
+
# Create a new line after current line and insert text on that line
|
71
|
+
def put_to_new_next_line(txt)
|
72
|
+
l = current_line_range()
|
73
|
+
insert_txt_at(txt, l.end + 1)
|
74
|
+
set_pos(l.end + 1)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Start asynchronous read of system clipboard
|
78
|
+
def paste_start(at, register)
|
79
|
+
@clipboard_paste_running = true
|
80
|
+
clipboard = vma.gui.window.display.clipboard
|
81
|
+
clipboard.read_text_async do |_clipboard, result|
|
82
|
+
begin
|
83
|
+
text = clipboard.read_text_finish(result)
|
84
|
+
rescue Gio::IOError::NotSupported
|
85
|
+
# Happens when pasting from KeePassX and clipboard cleared
|
86
|
+
debug Gio::IOError::NotSupported
|
87
|
+
else
|
88
|
+
paste_finish(text, at, register)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def paste_finish(text, at, register)
|
94
|
+
debug "PASTE: #{text}"
|
95
|
+
|
96
|
+
# If we did not put this text to clipboard
|
97
|
+
if text != vma.clipboard[-1]
|
98
|
+
@paste_lines = false
|
99
|
+
end
|
100
|
+
|
101
|
+
text = sanitize_input(text)
|
102
|
+
|
103
|
+
vma.clipboard << text
|
104
|
+
|
105
|
+
return if text == ""
|
106
|
+
|
107
|
+
if @paste_lines
|
108
|
+
debug "PASTE LINES"
|
109
|
+
put_to_new_next_line(text)
|
110
|
+
else
|
111
|
+
debug "PASTE !LINES"
|
112
|
+
if at_end_of_buffer? or at_end_of_line? or at == BEFORE
|
113
|
+
pos = @pos
|
114
|
+
else
|
115
|
+
pos = @pos + 1
|
116
|
+
end
|
117
|
+
insert_txt_at(text, pos)
|
118
|
+
set_pos(pos + text.size)
|
119
|
+
end
|
120
|
+
set_pos(@pos)
|
121
|
+
@clipboard_paste_running = false
|
122
|
+
end
|
123
|
+
|
124
|
+
def paste(at = AFTER, register = nil)
|
125
|
+
# Macro's don't work with asynchronous call using GTK
|
126
|
+
# TODO: implement as synchronous?
|
127
|
+
# Use internal clipboard
|
128
|
+
if vma.macro.running_macro
|
129
|
+
text = vma.clipboard.get()
|
130
|
+
paste_finish(text, at, register)
|
131
|
+
else
|
132
|
+
# Get clipboard using GUI
|
133
|
+
paste_start(at, register)
|
134
|
+
end
|
135
|
+
return true
|
136
|
+
end
|
137
|
+
|
138
|
+
def delete2(range_id, mark = nil)
|
139
|
+
@paste_lines = false
|
140
|
+
range = get_range(range_id, mark: mark)
|
141
|
+
return if range == nil
|
142
|
+
debug "RANGE"
|
143
|
+
debug range.inspect
|
144
|
+
debug range.inspect
|
145
|
+
debug "------"
|
146
|
+
delete_range(range.first, range.last)
|
147
|
+
pos = [range.first, @pos].min
|
148
|
+
set_pos(pos)
|
149
|
+
end
|
150
|
+
|
151
|
+
def delete(op, x = nil)
|
152
|
+
@paste_lines = false
|
153
|
+
# Delete selection
|
154
|
+
if op == SELECTION && visual_mode?
|
155
|
+
(startpos, endpos) = get_visual_mode_range2
|
156
|
+
delete_range(startpos, endpos, x)
|
157
|
+
@pos = [@pos, @selection_start].min
|
158
|
+
end_visual_mode
|
159
|
+
#return
|
160
|
+
|
161
|
+
# Delete current char
|
162
|
+
elsif op == CURRENT_CHAR_FORWARD
|
163
|
+
return if @pos >= self.size - 1 # May not delete last '\n'
|
164
|
+
add_delta([@pos, DELETE, 1], true)
|
165
|
+
|
166
|
+
# Delete current char and then move backward
|
167
|
+
elsif op == CURRENT_CHAR_BACKWARD
|
168
|
+
add_delta([@pos, DELETE, 1], true)
|
169
|
+
@pos -= 1
|
170
|
+
|
171
|
+
# Delete the char before current char and move backward
|
172
|
+
elsif op == BACKWARD_CHAR and @pos > 0
|
173
|
+
add_delta([@pos - 1, DELETE, 1], true)
|
174
|
+
@pos -= 1
|
175
|
+
elsif op == FORWARD_CHAR #TODO: ok?
|
176
|
+
add_delta([@pos + 1, DELETE, 1], true)
|
177
|
+
end
|
178
|
+
set_pos(@pos)
|
179
|
+
#recalc_line_ends
|
180
|
+
calculate_line_and_column_pos
|
181
|
+
#need_redraw!
|
182
|
+
end
|
183
|
+
|
184
|
+
def delete_range(startpos, endpos, x = nil)
|
185
|
+
s = self[startpos..endpos]
|
186
|
+
if startpos == endpos or s == ""
|
187
|
+
return
|
188
|
+
end
|
189
|
+
if x == :append
|
190
|
+
debug "APPEND"
|
191
|
+
s += "\n" + vma.clipboard.get()
|
192
|
+
end
|
193
|
+
vma.clipboard.set(s)
|
194
|
+
add_delta([startpos, DELETE, (endpos - startpos + 1)], true)
|
195
|
+
#recalc_line_ends
|
196
|
+
calculate_line_and_column_pos
|
197
|
+
end
|
198
|
+
|
199
|
+
def is_delta_ok(delta)
|
200
|
+
ret = true
|
201
|
+
pos = delta[0]
|
202
|
+
if pos < 0
|
203
|
+
ret = false
|
204
|
+
debug "pos=#{pos} < 0"
|
205
|
+
elsif pos > self.size
|
206
|
+
debug "pos=#{pos} > self.size=#{self.size}"
|
207
|
+
ret = false
|
208
|
+
end
|
209
|
+
if ret == false
|
210
|
+
# crash("DELTA OK=#{ret}")
|
211
|
+
end
|
212
|
+
return ret
|
213
|
+
end
|
214
|
+
|
215
|
+
def delete_line()
|
216
|
+
vma.kbd.method_handles_repeat = true
|
217
|
+
num_lines = 1
|
218
|
+
if !vma.kbd.next_command_count.nil? and vma.kbd.next_command_count > 0
|
219
|
+
num_lines = vma.kbd.next_command_count
|
220
|
+
debug "copy num_lines:#{num_lines}"
|
221
|
+
end
|
222
|
+
lrange = line_range(@lpos, num_lines)
|
223
|
+
s = self[lrange]
|
224
|
+
add_delta([lrange.begin, DELETE, lrange.end - lrange.begin + 1], true)
|
225
|
+
vma.clipboard.set(s)
|
226
|
+
update_pos(lrange.begin)
|
227
|
+
@paste_lines = true
|
228
|
+
#recalc_line_ends
|
229
|
+
end
|
230
|
+
|
231
|
+
def insert_tab
|
232
|
+
convert = conf(:tab_to_spaces_default)
|
233
|
+
convert = true if conf(:tab_to_spaces_languages).include?(@lang)
|
234
|
+
convert = false if conf(:tab_to_spaces_not_languages).include?(@lang)
|
235
|
+
tw = conf(:tab_width)
|
236
|
+
if convert
|
237
|
+
indent_to = (@cpos / tw) * tw + tw
|
238
|
+
indentdiff = indent_to - @cpos
|
239
|
+
insert_txt(" " * indentdiff)
|
240
|
+
else
|
241
|
+
insert_txt("\t")
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def insert_image_after_current_line(fname)
|
246
|
+
lr = current_line_range()
|
247
|
+
a = "⟦img:#{fname}⟧\n"
|
248
|
+
b = " \n"
|
249
|
+
txt = a + b
|
250
|
+
insert_txt_at(txt, lr.end + 1)
|
251
|
+
buf.view.handle_deltas
|
252
|
+
imgpos = lr.end + 1 + a.size
|
253
|
+
add_image(fname, imgpos)
|
254
|
+
end
|
255
|
+
end
|
@@ -0,0 +1,303 @@
|
|
1
|
+
# Buffer operations related to cursor position, e.g. moving the cursor (backward, forward, next line etc.)
|
2
|
+
class Buffer < String
|
3
|
+
|
4
|
+
def line(lpos)
|
5
|
+
if @line_ends.size == 0
|
6
|
+
return self
|
7
|
+
end
|
8
|
+
|
9
|
+
#TODO: implement using line_range()
|
10
|
+
if lpos >= @line_ends.size
|
11
|
+
debug("lpos too large") #TODO
|
12
|
+
return ""
|
13
|
+
elsif lpos == @line_ends.size
|
14
|
+
end
|
15
|
+
start = @line_ends[lpos - 1] + 1 if lpos > 0
|
16
|
+
start = 0 if lpos == 0
|
17
|
+
_end = @line_ends[lpos]
|
18
|
+
debug "start: _#{start}, end: #{_end}"
|
19
|
+
return self[start.._end]
|
20
|
+
end
|
21
|
+
|
22
|
+
def at_end_of_line?()
|
23
|
+
return (self[@pos] == "\n" or at_end_of_buffer?)
|
24
|
+
end
|
25
|
+
|
26
|
+
def at_end_of_buffer?()
|
27
|
+
return @pos == self.size
|
28
|
+
end
|
29
|
+
|
30
|
+
def refresh_cursor
|
31
|
+
self.view.set_cursor_pos(@pos)
|
32
|
+
end
|
33
|
+
|
34
|
+
def set_pos(new_pos)
|
35
|
+
if new_pos >= self.size
|
36
|
+
@pos = self.size - 1 # TODO:??right side of last char
|
37
|
+
elsif new_pos >= 0
|
38
|
+
@pos = new_pos
|
39
|
+
end
|
40
|
+
self.view.set_cursor_pos(pos)
|
41
|
+
# gui_set_cursor_pos(@id, @pos)
|
42
|
+
calculate_line_and_column_pos
|
43
|
+
|
44
|
+
check_if_modified_outside
|
45
|
+
end
|
46
|
+
|
47
|
+
# Get the line number of character position
|
48
|
+
def get_line_pos(pos)
|
49
|
+
lpos = @line_ends.bsearch_index { |x, _| x >= pos }
|
50
|
+
return lpos
|
51
|
+
end
|
52
|
+
|
53
|
+
# Calculate the two dimensional column and line positions based on
|
54
|
+
# (one dimensional) position in the buffer.
|
55
|
+
def get_line_and_col_pos(pos)
|
56
|
+
pos = self.size if pos > self.size
|
57
|
+
pos = 0 if pos < 0
|
58
|
+
|
59
|
+
lpos = get_line_pos(pos)
|
60
|
+
|
61
|
+
lpos = @line_ends.size if lpos == nil
|
62
|
+
cpos = pos
|
63
|
+
cpos -= @line_ends[lpos - 1] + 1 if lpos > 0
|
64
|
+
|
65
|
+
return [lpos, cpos]
|
66
|
+
end
|
67
|
+
|
68
|
+
def calculate_line_and_column_pos(reset = true)
|
69
|
+
@lpos, @cpos = get_line_and_col_pos(@pos)
|
70
|
+
reset_larger_cpos if reset
|
71
|
+
end
|
72
|
+
|
73
|
+
def set_line_and_column_pos(lpos, cpos, _reset_larger_cpos = true)
|
74
|
+
@lpos = lpos if !lpos.nil?
|
75
|
+
@cpos = cpos if !cpos.nil?
|
76
|
+
if @lpos > 0
|
77
|
+
new_pos = @line_ends[@lpos - 1] + 1
|
78
|
+
else
|
79
|
+
new_pos = 0
|
80
|
+
end
|
81
|
+
|
82
|
+
if @cpos > (line(@lpos).size - 1)
|
83
|
+
debug("$cpos too large: #{@cpos} #{@lpos}")
|
84
|
+
if @larger_cpos < @cpos
|
85
|
+
@larger_cpos = @cpos
|
86
|
+
end
|
87
|
+
@cpos = line(@lpos).size - 1
|
88
|
+
end
|
89
|
+
new_pos += @cpos
|
90
|
+
set_pos(new_pos)
|
91
|
+
reset_larger_cpos if _reset_larger_cpos
|
92
|
+
end
|
93
|
+
|
94
|
+
# Calculate the one dimensional array index based on column and line positions
|
95
|
+
def calculate_pos_from_cpos_lpos(reset = true)
|
96
|
+
set_line_and_column_pos(nil, nil)
|
97
|
+
end
|
98
|
+
|
99
|
+
def update_pos(pos)
|
100
|
+
@pos = pos
|
101
|
+
calculate_line_and_column_pos
|
102
|
+
end
|
103
|
+
|
104
|
+
def is_legal_pos(pos, op = :read)
|
105
|
+
return false if pos < 0
|
106
|
+
if op == :add
|
107
|
+
return false if pos > self.size
|
108
|
+
elsif op == :read
|
109
|
+
return false if pos >= self.size
|
110
|
+
end
|
111
|
+
return true
|
112
|
+
end
|
113
|
+
|
114
|
+
def jump_to_last_edit()
|
115
|
+
return if @edit_pos_history.empty?
|
116
|
+
@edit_pos_history_i += 1
|
117
|
+
|
118
|
+
if @edit_pos_history_i > @edit_pos_history.size
|
119
|
+
@edit_pos_history_i = 0
|
120
|
+
end
|
121
|
+
|
122
|
+
# if @edit_pos_history.size >= @edit_pos_history_i
|
123
|
+
set_pos(@edit_pos_history[-@edit_pos_history_i])
|
124
|
+
center_on_current_line
|
125
|
+
return true
|
126
|
+
# end
|
127
|
+
end
|
128
|
+
|
129
|
+
def jump_to_next_edit()
|
130
|
+
return if @edit_pos_history.empty?
|
131
|
+
@edit_pos_history_i -= 1
|
132
|
+
@edit_pos_history_i = @edit_pos_history.size - 1 if @edit_pos_history_i < 0
|
133
|
+
debug "@edit_pos_history_i=#{@edit_pos_history_i}"
|
134
|
+
set_pos(@edit_pos_history[-@edit_pos_history_i])
|
135
|
+
center_on_current_line
|
136
|
+
return true
|
137
|
+
end
|
138
|
+
|
139
|
+
def jump_to_random_pos()
|
140
|
+
set_pos(rand(self.size))
|
141
|
+
end
|
142
|
+
|
143
|
+
def jump_to_next_instance_of_word()
|
144
|
+
if $kbd.last_action == $kbd.cur_action and @current_word != nil
|
145
|
+
# debug "REPEATING *"
|
146
|
+
else
|
147
|
+
start_search = [@pos - 150, 0].max
|
148
|
+
|
149
|
+
search_str1 = self[start_search..(@pos)]
|
150
|
+
wsmarks = scan_indexes(search_str1, /(?<=[^\p{Word}])\p{Word}/)
|
151
|
+
a = wsmarks[-1]
|
152
|
+
a = 0 if a == nil
|
153
|
+
|
154
|
+
search_str2 = self[(@pos)..(@pos + 150)]
|
155
|
+
wemarks = scan_indexes(search_str2, /(?<=\p{Word})[^\p{Word}]/)
|
156
|
+
b = wemarks[0]
|
157
|
+
word_start = (@pos - search_str1.size + a + 1)
|
158
|
+
word_start = 0 if !(word_start >= 0)
|
159
|
+
@current_word = self[word_start..(@pos + b - 1)]
|
160
|
+
end
|
161
|
+
|
162
|
+
#TODO: search for /[^\p{Word}]WORD[^\p{Word}]/
|
163
|
+
position_of_next_word = self.index(@current_word, @pos + 1)
|
164
|
+
if position_of_next_word != nil
|
165
|
+
set_pos(position_of_next_word)
|
166
|
+
else #Search from beginning
|
167
|
+
position_of_next_word = self.index(@current_word)
|
168
|
+
set_pos(position_of_next_word) if position_of_next_word != nil
|
169
|
+
end
|
170
|
+
center_on_current_line
|
171
|
+
return true
|
172
|
+
end
|
173
|
+
|
174
|
+
def jump_word(direction, wordpos)
|
175
|
+
offset = 0
|
176
|
+
if direction == FORWARD
|
177
|
+
debug "POS: #{@pos},"
|
178
|
+
search_str = self[(@pos)..(@pos + 250)]
|
179
|
+
return if search_str == nil
|
180
|
+
if wordpos == WORD_START # vim 'w'
|
181
|
+
wsmarks = scan_indexes(search_str, /(?<=[^\p{Word}])\p{Word}|\Z/) # \Z = end of string, just before last newline.
|
182
|
+
wsmarks2 = scan_indexes(search_str, /\n[ \t]*\n/) # "empty" lines that have whitespace
|
183
|
+
wsmarks2 = wsmarks2.collect { |x| x + 1 }
|
184
|
+
wsmarks = (wsmarks2 + wsmarks).sort.uniq
|
185
|
+
offset = 0
|
186
|
+
if wsmarks.any?
|
187
|
+
next_pos = @pos + wsmarks[0] + offset
|
188
|
+
set_pos(next_pos)
|
189
|
+
end
|
190
|
+
elsif wordpos == WORD_END
|
191
|
+
search_str = self[(@pos + 1)..(@pos + 150)]
|
192
|
+
wsmarks = scan_indexes(search_str, /(?<=\p{Word})[^\p{Word}]/)
|
193
|
+
offset = -1
|
194
|
+
if wsmarks.any?
|
195
|
+
next_pos = @pos + 1 + wsmarks[0] + offset
|
196
|
+
set_pos(next_pos)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
if direction == BACKWARD # vim 'b'
|
201
|
+
start_search = @pos - 150 #TODO 150 length limit
|
202
|
+
start_search = 0 if start_search < 0
|
203
|
+
search_str = self[start_search..(@pos - 1)]
|
204
|
+
return if search_str == nil
|
205
|
+
wsmarks = scan_indexes(search_str,
|
206
|
+
#/(^|(\W)\w|\n)/) #TODO 150 length limit
|
207
|
+
#/^|(?<=[^\p{Word}])\p{Word}|(?<=\n)\n/) #include empty lines?
|
208
|
+
/\A|(?<=[^\p{Word}])\p{Word}/) # Start of string or nonword,word.
|
209
|
+
|
210
|
+
offset = 0
|
211
|
+
|
212
|
+
if wsmarks.any?
|
213
|
+
next_pos = start_search + wsmarks.last + offset
|
214
|
+
set_pos(next_pos)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def jump_to_mark(mark_char)
|
220
|
+
p = @marks[mark_char]
|
221
|
+
set_pos(p) if p
|
222
|
+
center_on_current_line
|
223
|
+
return true
|
224
|
+
end
|
225
|
+
|
226
|
+
def jump(target)
|
227
|
+
if target == START_OF_BUFFER
|
228
|
+
set_pos(0)
|
229
|
+
end
|
230
|
+
if target == END_OF_BUFFER
|
231
|
+
set_pos(self.size - 1)
|
232
|
+
end
|
233
|
+
if target == BEGINNING_OF_LINE
|
234
|
+
@cpos = 0
|
235
|
+
calculate_pos_from_cpos_lpos
|
236
|
+
end
|
237
|
+
if target == END_OF_LINE
|
238
|
+
@cpos = line(@lpos).size - 1
|
239
|
+
calculate_pos_from_cpos_lpos
|
240
|
+
end
|
241
|
+
|
242
|
+
if target == FIRST_NON_WHITESPACE
|
243
|
+
l = current_line()
|
244
|
+
debug l.inspect
|
245
|
+
@cpos = line(@lpos).size - 1
|
246
|
+
a = scan_indexes(l, /\S/)
|
247
|
+
debug a.inspect
|
248
|
+
if a.any?
|
249
|
+
@cpos = a[0]
|
250
|
+
else
|
251
|
+
@cpos = 0
|
252
|
+
end
|
253
|
+
calculate_pos_from_cpos_lpos
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def jump_to_line(line_n = 1)
|
258
|
+
|
259
|
+
# $method_handles_repeat = true
|
260
|
+
# if !$next_command_count.nil? and $next_command_count > 0
|
261
|
+
# line_n = $next_command_count
|
262
|
+
# debug "jump to line:#{line_n}"
|
263
|
+
# end
|
264
|
+
debug "jump to line:#{line_n}"
|
265
|
+
line_n = get_repeat_num() if line_n == 1
|
266
|
+
|
267
|
+
if line_n > @line_ends.size
|
268
|
+
debug("lpos too large") #TODO
|
269
|
+
return
|
270
|
+
end
|
271
|
+
if line_n == 1
|
272
|
+
set_pos(0)
|
273
|
+
else
|
274
|
+
set_pos(@line_ends[line_n - 2] + 1)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def jump_to_next_instance_of_char(char, direction = FORWARD)
|
279
|
+
if direction == FORWARD
|
280
|
+
position_of_next_char = self.index(char, @pos + 1)
|
281
|
+
if position_of_next_char != nil
|
282
|
+
@pos = position_of_next_char
|
283
|
+
end
|
284
|
+
elsif direction == BACKWARD
|
285
|
+
start_search = @pos - 250
|
286
|
+
start_search = 0 if start_search < 0
|
287
|
+
search_substr = self[start_search..(@pos - 1)]
|
288
|
+
_pos = search_substr.reverse.index(char)
|
289
|
+
if _pos != nil
|
290
|
+
@pos -= (_pos + 1)
|
291
|
+
end
|
292
|
+
end
|
293
|
+
m = method("jump_to_next_instance_of_char")
|
294
|
+
set_last_command({ method: m, params: [char, direction] })
|
295
|
+
$last_find_command = { char: char, direction: direction }
|
296
|
+
set_pos(@pos)
|
297
|
+
return true
|
298
|
+
end
|
299
|
+
|
300
|
+
def jump_to_pos(new_pos)
|
301
|
+
set_pos(new_pos)
|
302
|
+
end
|
303
|
+
end
|
data/lib/vimamsa/buffer_list.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
def save_buffer_list()
|
3
2
|
message("Save buffer list")
|
4
3
|
buffn = get_dot_path("buffers.txt")
|
@@ -21,13 +20,13 @@ def load_buffer_list()
|
|
21
20
|
end
|
22
21
|
|
23
22
|
class BufferList < Array
|
24
|
-
attr_reader :current_buf, :last_dir, :buffer_history
|
23
|
+
attr_reader :current_buf, :last_dir, :last_file, :buffer_history
|
25
24
|
|
26
25
|
def initialize()
|
27
26
|
@last_dir = File.expand_path(".")
|
28
27
|
@buffer_history = []
|
29
28
|
super
|
30
|
-
@current_buf=0
|
29
|
+
@current_buf = 0
|
31
30
|
end
|
32
31
|
|
33
32
|
# lastdir = File.expand_path(".") if lastdir.nil?
|
@@ -39,7 +38,8 @@ class BufferList < Array
|
|
39
38
|
@recent_ind = 0
|
40
39
|
$hook.call(:change_buffer, vma.buf)
|
41
40
|
vma.gui.set_current_buffer(vma.buf.id)
|
42
|
-
gui_set_cursor_pos(vma.buf.id, vma.buf.pos)
|
41
|
+
# gui_set_cursor_pos(vma.buf.id, vma.buf.pos)
|
42
|
+
vma.buf.view.set_cursor_pos(vma.buf.pos)
|
43
43
|
update_last_dir(_buf)
|
44
44
|
end
|
45
45
|
|
@@ -111,8 +111,13 @@ class BufferList < Array
|
|
111
111
|
def set_current_buffer(buffer_i, update_history = true)
|
112
112
|
buffer_i = self.size -1 if buffer_i > self.size
|
113
113
|
buffer_i = 0 if buffer_i < 0
|
114
|
+
if !vma.buf.nil? and vma.kbd.get_mode != :browse #TODO
|
115
|
+
# Save keyboard mode status of old buffer when switching buffer
|
116
|
+
vma.buf.mode_stack = vma.kbd.default_mode_stack.clone
|
117
|
+
end
|
114
118
|
vma.buf = self[buffer_i]
|
115
119
|
return if !vma.buf
|
120
|
+
update_last_dir(vma.buf)
|
116
121
|
@current_buf = buffer_i
|
117
122
|
debug "SWITCH BUF2. bufsize:#{self.size}, curbuf: #{@current_buf}"
|
118
123
|
fpath = vma.buf.fname
|
@@ -123,24 +128,36 @@ class BufferList < Array
|
|
123
128
|
if update_history
|
124
129
|
add_current_buf_to_history
|
125
130
|
end
|
126
|
-
|
127
131
|
vma.hook.call(:change_buffer, vma.buf)
|
128
|
-
vma.buf.set_active
|
132
|
+
vma.buf.set_active # TODO
|
129
133
|
|
130
134
|
vma.gui.set_current_buffer(vma.buf.id)
|
131
135
|
|
136
|
+
if !vma.buf.mode_stack.nil? and vma.kbd.get_mode != :browse #TODO
|
137
|
+
debug "set kbd mode stack #{vma.buf.mode_stack} #{vma.buf.id}", 2
|
138
|
+
# Reload previously saved keyboard mode status
|
139
|
+
# vma.kbd.set_mode_stack(vma.buf.mode_stack.clone) #TODO:needed?
|
140
|
+
vma.kbd.set_mode_stack([vma.buf.default_mode])
|
141
|
+
end
|
142
|
+
vma.kbd.set_mode_to_default
|
143
|
+
|
132
144
|
gui_set_window_title(vma.buf.title, vma.buf.subtitle)
|
133
145
|
|
134
146
|
if vma.buf.fname
|
135
147
|
@last_dir = File.dirname(vma.buf.fname)
|
136
148
|
end
|
137
149
|
|
138
|
-
# hpt_scan_images() if
|
150
|
+
# hpt_scan_images() if cnf.debug? # experimental
|
151
|
+
end
|
152
|
+
|
153
|
+
def to_s
|
154
|
+
return self.class.to_s
|
139
155
|
end
|
140
156
|
|
141
157
|
def update_last_dir(buf)
|
142
158
|
if buf.fname
|
143
159
|
@last_dir = File.dirname(buf.fname)
|
160
|
+
@last_file = buf.fname
|
144
161
|
end
|
145
162
|
end
|
146
163
|
|
@@ -213,8 +230,8 @@ class BufferList < Array
|
|
213
230
|
if from_recent
|
214
231
|
@current_buf = jump_to_buf
|
215
232
|
else
|
216
|
-
|
217
|
-
@current_buf = @buffer_history.filter{|x| !vma.gui.is_buffer_open(self[x].id)}.last
|
233
|
+
# Find last edited buffer that is not already open
|
234
|
+
@current_buf = @buffer_history.filter { |x| !vma.gui.is_buffer_open(self[x].id) }.last
|
218
235
|
end
|
219
236
|
end
|
220
237
|
if self.size == 0 or @current_buf.nil?
|
@@ -7,11 +7,12 @@ class BufferManager
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def self.init()
|
10
|
-
vma.kbd.add_minor_mode("bmgr", :buf_mgr, :command)
|
10
|
+
# vma.kbd.add_minor_mode("bmgr", :buf_mgr, :command)
|
11
|
+
vma.kbd.add_minor_mode("bmgr", :bmgr, :command)
|
11
12
|
reg_act(:bmgr_select, proc { buf.module.select_line }, "")
|
12
13
|
reg_act(:bmgr_close, proc { buf.module.close_selected }, "")
|
13
14
|
|
14
|
-
reg_act(:start_buf_manager, proc { BufferManager.new.run; vma.kbd.set_mode(:
|
15
|
+
reg_act(:start_buf_manager, proc { BufferManager.new.run; vma.kbd.set_mode(:bmgr) }, "Buffer manager")
|
15
16
|
|
16
17
|
bindkey "bmgr enter", :bmgr_select
|
17
18
|
bindkey "bmgr c", :bmgr_close
|
@@ -84,6 +85,7 @@ class BufferManager
|
|
84
85
|
|
85
86
|
if @buf.nil?
|
86
87
|
@buf = create_new_buffer(s,"bufmgr")
|
88
|
+
@buf.default_mode = :buf_mgr
|
87
89
|
@buf.module = self
|
88
90
|
@buf.active_kbd_mode = :buf_mgr
|
89
91
|
else
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class Clipboard
|
2
|
+
def initialize
|
3
|
+
@clipboard = []
|
4
|
+
end
|
5
|
+
|
6
|
+
def [](key)
|
7
|
+
return @clipboard[key]
|
8
|
+
end
|
9
|
+
|
10
|
+
def <<(str)
|
11
|
+
return @clipboard << str
|
12
|
+
end
|
13
|
+
|
14
|
+
def set(s)
|
15
|
+
if !(s.class <= String) or s.size == 0
|
16
|
+
debug s.inspect
|
17
|
+
debug [s, s.class, s.size]
|
18
|
+
log_error("s.class != String or s.size == 0")
|
19
|
+
return
|
20
|
+
end
|
21
|
+
@clipboard << s
|
22
|
+
set_system_clipboard(s)
|
23
|
+
vma.register[vma.cur_register] = s
|
24
|
+
debug "SET CLIPBOARD: [#{s}]"
|
25
|
+
debug "REGISTER: #{vma.cur_register}:#{vma.register[vma.cur_register]}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def get()
|
29
|
+
return @clipboard[-1]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def set_system_clipboard(arg)
|
34
|
+
vma.gui.window.display.clipboard.set(arg)
|
35
|
+
end
|