vimamsa 0.1.13 → 0.1.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.
- checksums.yaml +4 -4
- data/custom_example.rb +5 -0
- data/lib/vimamsa/ack.rb +3 -4
- data/lib/vimamsa/audio.rb +25 -1
- data/lib/vimamsa/buffer.rb +43 -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 +41 -78
- data/lib/vimamsa/encrypt.rb +6 -11
- data/lib/vimamsa/file_manager.rb +138 -9
- data/lib/vimamsa/gui.rb +3 -32
- data/lib/vimamsa/gui_dialog.rb +113 -0
- data/lib/vimamsa/gui_sourceview.rb +10 -14
- data/lib/vimamsa/gui_text.rb +19 -0
- data/lib/vimamsa/hyper_plain_text.rb +8 -5
- data/lib/vimamsa/key_actions.rb +17 -197
- data/lib/vimamsa/key_binding_tree.rb +49 -31
- data/lib/vimamsa/key_bindings_vimlike.rb +30 -30
- data/lib/vimamsa/macro.rb +35 -25
- data/lib/vimamsa/main.rb +3 -10
- data/lib/vimamsa/rbvma.rb +11 -11
- data/lib/vimamsa/search.rb +1 -1
- data/lib/vimamsa/search_replace.rb +89 -151
- data/lib/vimamsa/terminal.rb +22 -0
- data/lib/vimamsa/tests.rb +122 -0
- data/lib/vimamsa/util.rb +33 -3
- data/lib/vimamsa/version.rb +1 -1
- data/vimamsa.gemspec +3 -1
- metadata +56 -7
- /data/lib/vimamsa/{form_generator.rb → gui_form_generator.rb} +0 -0
data/lib/vimamsa/buffer.rb
CHANGED
@@ -14,7 +14,7 @@ $ifuncon = false
|
|
14
14
|
class Buffer < String
|
15
15
|
attr_reader :pos, :lpos, :cpos, :deltas, :edit_history, :fname, :call_func, :pathname, :basename, :dirname, :update_highlight, :marks, :is_highlighted, :syntax_detect_failed, :id, :lang, :images, :last_save
|
16
16
|
attr_writer :call_func, :update_highlight
|
17
|
-
attr_accessor :gui_update_highlight, :update_hl_startpos, :update_hl_endpos, :hl_queue, :syntax_parser, :highlights, :gui_reset_highlight, :is_parsing_syntax, :line_ends, :bt, :line_action_handler, :module, :active_kbd_mode, :title, :subtitle, :paste_lines
|
17
|
+
attr_accessor :gui_update_highlight, :update_hl_startpos, :update_hl_endpos, :hl_queue, :syntax_parser, :highlights, :gui_reset_highlight, :is_parsing_syntax, :line_ends, :bt, :line_action_handler, :module, :active_kbd_mode, :title, :subtitle, :paste_lines, :mode_stack, :default_mode
|
18
18
|
|
19
19
|
@@num_buffers = 0
|
20
20
|
|
@@ -28,6 +28,8 @@ class Buffer < String
|
|
28
28
|
@id = @@num_buffers
|
29
29
|
@@num_buffers += 1
|
30
30
|
@version = 0
|
31
|
+
@mode_stack = [:command] # TODO
|
32
|
+
@default_mode = :command # TODO
|
31
33
|
gui_create_buffer(@id, self)
|
32
34
|
debug "NEW BUFFER fn=#{fname} ID:#{@id}"
|
33
35
|
|
@@ -91,15 +93,14 @@ class Buffer < String
|
|
91
93
|
|
92
94
|
def set_active
|
93
95
|
if !@active_kbd_mode.nil?
|
94
|
-
$kbd.set_mode(@active_kbd_mode)
|
96
|
+
# $kbd.set_mode(@active_kbd_mode) #TODO: remove?
|
95
97
|
else
|
96
98
|
$kbd.set_mode_to_default
|
97
99
|
end
|
98
|
-
# gui_set_current_buffer(@id)
|
99
100
|
end
|
100
101
|
|
101
102
|
def set_executable
|
102
|
-
if File.
|
103
|
+
if File.exist?(@fname)
|
103
104
|
FileUtils.chmod("+x", @fname)
|
104
105
|
message("Set executable: #{@fname}")
|
105
106
|
end
|
@@ -213,6 +214,7 @@ class Buffer < String
|
|
213
214
|
$audiof = mf
|
214
215
|
end
|
215
216
|
|
217
|
+
#TODO: remove?
|
216
218
|
def reset_audio_widget_positions
|
217
219
|
debug "reset_audio_widget_positions", 2
|
218
220
|
for mc in @audiofiles
|
@@ -246,16 +248,6 @@ class Buffer < String
|
|
246
248
|
gui_set_current_buffer(@id) #TODO: needed?
|
247
249
|
end
|
248
250
|
|
249
|
-
def is_legal_pos(pos, op = :read)
|
250
|
-
return false if pos < 0
|
251
|
-
if op == :add
|
252
|
-
return false if pos > self.size
|
253
|
-
elsif op == :read
|
254
|
-
return false if pos >= self.size
|
255
|
-
end
|
256
|
-
return true
|
257
|
-
end
|
258
|
-
|
259
251
|
def set_encrypted(password)
|
260
252
|
@crypt = Encrypt.new(password)
|
261
253
|
message("Set buffer encrypted")
|
@@ -265,19 +257,18 @@ class Buffer < String
|
|
265
257
|
@crypt = nil
|
266
258
|
end
|
267
259
|
|
268
|
-
def
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
add_image(fname, imgpos)
|
260
|
+
def unindent
|
261
|
+
debug("unindent", 2)
|
262
|
+
conf(:tab_width).times {
|
263
|
+
p = @pos - 1
|
264
|
+
if p >= 0
|
265
|
+
if self[p] == " "
|
266
|
+
delete(BACKWARD_CHAR)
|
267
|
+
end
|
268
|
+
else
|
269
|
+
break
|
270
|
+
end
|
271
|
+
}
|
281
272
|
end
|
282
273
|
|
283
274
|
def handle_drag_and_drop(fname)
|
@@ -300,13 +291,14 @@ class Buffer < String
|
|
300
291
|
|
301
292
|
def revert()
|
302
293
|
return if !@fname
|
303
|
-
return if !File.
|
294
|
+
return if !File.exist?(@fname)
|
304
295
|
message("Revert buffer #{@fname}")
|
305
296
|
str = read_file("", @fname)
|
306
297
|
self.set_content(str)
|
307
298
|
end
|
308
299
|
|
309
300
|
def decrypt(password)
|
301
|
+
return if @encrypted_str.nil?
|
310
302
|
begin
|
311
303
|
@crypt = Encrypt.new(password)
|
312
304
|
str = @crypt.decrypt(@encrypted_str)
|
@@ -347,11 +339,9 @@ class Buffer < String
|
|
347
339
|
@ftype = nil
|
348
340
|
if str[0..10] == "VMACRYPT001"
|
349
341
|
@encrypted_str = str[11..-1]
|
350
|
-
callback = proc { |x|
|
351
|
-
gui_one_input_action("Decrypt", "Password:", "decrypt", callback, { :hide => true })
|
342
|
+
callback = proc { |x| self.decrypt(x) }
|
343
|
+
gui_one_input_action("Decrypt file \n #{@fname}", "Password:", "decrypt", callback, { :hide => true })
|
352
344
|
str = "ENCRYPTED"
|
353
|
-
else
|
354
|
-
# @crypt = nil
|
355
345
|
end
|
356
346
|
|
357
347
|
if (str[-1] != "\n")
|
@@ -361,10 +351,9 @@ class Buffer < String
|
|
361
351
|
self.replace(str)
|
362
352
|
@line_ends = scan_indexes(self, /\n/)
|
363
353
|
|
364
|
-
|
365
|
-
if $experimental
|
354
|
+
if cnf.btree.experimental?
|
366
355
|
@bt = BufferTree.new(self)
|
367
|
-
if
|
356
|
+
if cnf.debug?
|
368
357
|
sanitycheck_btree()
|
369
358
|
end
|
370
359
|
end
|
@@ -426,65 +415,6 @@ class Buffer < String
|
|
426
415
|
return fpath
|
427
416
|
end
|
428
417
|
|
429
|
-
def line(lpos)
|
430
|
-
if @line_ends.size == 0
|
431
|
-
return self
|
432
|
-
end
|
433
|
-
|
434
|
-
#TODO: implement using line_range()
|
435
|
-
if lpos >= @line_ends.size
|
436
|
-
debug("lpos too large") #TODO
|
437
|
-
return ""
|
438
|
-
elsif lpos == @line_ends.size
|
439
|
-
end
|
440
|
-
start = @line_ends[lpos - 1] + 1 if lpos > 0
|
441
|
-
start = 0 if lpos == 0
|
442
|
-
_end = @line_ends[lpos]
|
443
|
-
debug "start: _#{start}, end: #{_end}"
|
444
|
-
return self[start.._end]
|
445
|
-
end
|
446
|
-
|
447
|
-
def is_delta_ok(delta)
|
448
|
-
ret = true
|
449
|
-
pos = delta[0]
|
450
|
-
if pos < 0
|
451
|
-
ret = false
|
452
|
-
debug "pos=#{pos} < 0"
|
453
|
-
elsif pos > self.size
|
454
|
-
debug "pos=#{pos} > self.size=#{self.size}"
|
455
|
-
ret = false
|
456
|
-
end
|
457
|
-
if ret == false
|
458
|
-
# crash("DELTA OK=#{ret}")
|
459
|
-
end
|
460
|
-
return ret
|
461
|
-
end
|
462
|
-
|
463
|
-
#TODO: change to apply=true as default
|
464
|
-
def add_delta(delta, apply = false, auto_update_cpos = false)
|
465
|
-
return if !is_delta_ok(delta)
|
466
|
-
if delta[1] == DELETE
|
467
|
-
return if delta[0] >= self.size
|
468
|
-
# If go over length of buffer
|
469
|
-
if delta[0] + delta[2] >= self.size
|
470
|
-
delta[2] = self.size - delta[0]
|
471
|
-
end
|
472
|
-
end
|
473
|
-
|
474
|
-
@edit_version += 1
|
475
|
-
@redo_stack = []
|
476
|
-
if apply
|
477
|
-
delta = run_delta(delta, auto_update_cpos)
|
478
|
-
else
|
479
|
-
@deltas << delta
|
480
|
-
end
|
481
|
-
@edit_history << delta
|
482
|
-
if self[-1] != "\n"
|
483
|
-
add_delta([self.size, INSERT, 1, "\n"], true)
|
484
|
-
end
|
485
|
-
reset_larger_cpos #TODO: correct here?
|
486
|
-
end
|
487
|
-
|
488
418
|
def add_hl_update(startpos, endpos)
|
489
419
|
return if @is_highlighted == false
|
490
420
|
|
@@ -501,7 +431,7 @@ class Buffer < String
|
|
501
431
|
# delta[3]: text to add in case of insert
|
502
432
|
|
503
433
|
@version += 1
|
504
|
-
if
|
434
|
+
if cnf.btree.experimental?
|
505
435
|
@bt.handle_delta(Delta.new(delta[0], delta[1], delta[2], delta[3]))
|
506
436
|
end
|
507
437
|
|
@@ -585,34 +515,6 @@ class Buffer < String
|
|
585
515
|
end
|
586
516
|
end
|
587
517
|
|
588
|
-
def jump_to_last_edit()
|
589
|
-
return if @edit_pos_history.empty?
|
590
|
-
@edit_pos_history_i += 1
|
591
|
-
|
592
|
-
if @edit_pos_history_i > @edit_pos_history.size
|
593
|
-
@edit_pos_history_i = 0
|
594
|
-
end
|
595
|
-
|
596
|
-
# if @edit_pos_history.size >= @edit_pos_history_i
|
597
|
-
set_pos(@edit_pos_history[-@edit_pos_history_i])
|
598
|
-
center_on_current_line
|
599
|
-
return true
|
600
|
-
# end
|
601
|
-
end
|
602
|
-
|
603
|
-
def jump_to_next_edit()
|
604
|
-
return if @edit_pos_history.empty?
|
605
|
-
@edit_pos_history_i -= 1
|
606
|
-
@edit_pos_history_i = @edit_pos_history.size - 1 if @edit_pos_history_i < 0
|
607
|
-
debug "@edit_pos_history_i=#{@edit_pos_history_i}"
|
608
|
-
set_pos(@edit_pos_history[-@edit_pos_history_i])
|
609
|
-
center_on_current_line
|
610
|
-
return true
|
611
|
-
end
|
612
|
-
|
613
|
-
def jump_to_random_pos()
|
614
|
-
set_pos(rand(self.size))
|
615
|
-
end
|
616
518
|
|
617
519
|
def undo()
|
618
520
|
debug @edit_history.inspect
|
@@ -757,10 +659,10 @@ class Buffer < String
|
|
757
659
|
end
|
758
660
|
|
759
661
|
def get_repeat_num()
|
760
|
-
|
662
|
+
vma.kbd.method_handles_repeat = true
|
761
663
|
repeat_num = 1
|
762
|
-
if
|
763
|
-
repeat_num =
|
664
|
+
if !vma.kbd.next_command_count.nil? and vma.kbd.next_command_count > 0
|
665
|
+
repeat_num = vma.kbd.next_command_count
|
764
666
|
end
|
765
667
|
return repeat_num
|
766
668
|
end
|
@@ -809,7 +711,7 @@ class Buffer < String
|
|
809
711
|
debug range_id.inspect
|
810
712
|
range = get_range(range_id)
|
811
713
|
debug range.inspect
|
812
|
-
|
714
|
+
vma.clipboard.set(self[range])
|
813
715
|
end
|
814
716
|
|
815
717
|
def recalc_line_ends()
|
@@ -890,149 +792,7 @@ class Buffer < String
|
|
890
792
|
@line_ends.sort!
|
891
793
|
end
|
892
794
|
end
|
893
|
-
|
894
|
-
def at_end_of_line?()
|
895
|
-
return (self[@pos] == "\n" or at_end_of_buffer?)
|
896
|
-
end
|
897
|
-
|
898
|
-
def at_end_of_buffer?()
|
899
|
-
return @pos == self.size
|
900
|
-
end
|
901
|
-
|
902
|
-
def jump_to_pos(new_pos)
|
903
|
-
set_pos(new_pos)
|
904
|
-
end
|
905
|
-
|
906
|
-
def set_pos(new_pos)
|
907
|
-
if new_pos >= self.size
|
908
|
-
@pos = self.size - 1 # TODO:??right side of last char
|
909
|
-
elsif new_pos >= 0
|
910
|
-
@pos = new_pos
|
911
|
-
end
|
912
|
-
gui_set_cursor_pos(@id, @pos)
|
913
|
-
calculate_line_and_column_pos
|
914
|
-
|
915
|
-
check_if_modified_outside
|
916
|
-
end
|
917
|
-
|
918
|
-
# Get the line number of character position
|
919
|
-
def get_line_pos(pos)
|
920
|
-
lpos = @line_ends.bsearch_index { |x, _| x >= pos }
|
921
|
-
return lpos
|
922
|
-
end
|
923
|
-
|
924
|
-
# Calculate the two dimensional column and line positions based on
|
925
|
-
# (one dimensional) position in the buffer.
|
926
|
-
def get_line_and_col_pos(pos)
|
927
|
-
pos = self.size if pos > self.size
|
928
|
-
pos = 0 if pos < 0
|
929
|
-
|
930
|
-
lpos = get_line_pos(pos)
|
931
|
-
|
932
|
-
lpos = @line_ends.size if lpos == nil
|
933
|
-
cpos = pos
|
934
|
-
cpos -= @line_ends[lpos - 1] + 1 if lpos > 0
|
935
|
-
|
936
|
-
return [lpos, cpos]
|
937
|
-
end
|
938
|
-
|
939
|
-
def calculate_line_and_column_pos(reset = true)
|
940
|
-
@lpos, @cpos = get_line_and_col_pos(@pos)
|
941
|
-
reset_larger_cpos if reset
|
942
|
-
end
|
943
|
-
|
944
|
-
def set_line_and_column_pos(lpos, cpos, _reset_larger_cpos = true)
|
945
|
-
@lpos = lpos if !lpos.nil?
|
946
|
-
@cpos = cpos if !cpos.nil?
|
947
|
-
if @lpos > 0
|
948
|
-
new_pos = @line_ends[@lpos - 1] + 1
|
949
|
-
else
|
950
|
-
new_pos = 0
|
951
|
-
end
|
952
|
-
|
953
|
-
if @cpos > (line(@lpos).size - 1)
|
954
|
-
debug("$cpos too large: #{@cpos} #{@lpos}")
|
955
|
-
if @larger_cpos < @cpos
|
956
|
-
@larger_cpos = @cpos
|
957
|
-
end
|
958
|
-
@cpos = line(@lpos).size - 1
|
959
|
-
end
|
960
|
-
new_pos += @cpos
|
961
|
-
set_pos(new_pos)
|
962
|
-
reset_larger_cpos if _reset_larger_cpos
|
963
|
-
end
|
964
|
-
|
965
|
-
# Calculate the one dimensional array index based on column and line positions
|
966
|
-
def calculate_pos_from_cpos_lpos(reset = true)
|
967
|
-
set_line_and_column_pos(nil, nil)
|
968
|
-
end
|
969
|
-
|
970
|
-
def delete2(range_id, mark = nil)
|
971
|
-
# if mark != nil
|
972
|
-
# debug mark, 2
|
973
|
-
# return
|
974
|
-
# end
|
975
|
-
|
976
|
-
@paste_lines = false
|
977
|
-
range = get_range(range_id, mark: mark)
|
978
|
-
return if range == nil
|
979
|
-
debug "RANGE"
|
980
|
-
debug range.inspect
|
981
|
-
debug range.inspect
|
982
|
-
debug "------"
|
983
|
-
delete_range(range.first, range.last)
|
984
|
-
pos = [range.first, @pos].min
|
985
|
-
set_pos(pos)
|
986
|
-
end
|
987
|
-
|
988
|
-
def delete(op, x = nil)
|
989
|
-
@paste_lines = false
|
990
|
-
# Delete selection
|
991
|
-
if op == SELECTION && visual_mode?
|
992
|
-
(startpos, endpos) = get_visual_mode_range2
|
993
|
-
delete_range(startpos, endpos, x)
|
994
|
-
@pos = [@pos, @selection_start].min
|
995
|
-
end_visual_mode
|
996
|
-
#return
|
997
|
-
|
998
|
-
# Delete current char
|
999
|
-
elsif op == CURRENT_CHAR_FORWARD
|
1000
|
-
return if @pos >= self.size - 1 # May not delete last '\n'
|
1001
|
-
add_delta([@pos, DELETE, 1], true)
|
1002
|
-
|
1003
|
-
# Delete current char and then move backward
|
1004
|
-
elsif op == CURRENT_CHAR_BACKWARD
|
1005
|
-
add_delta([@pos, DELETE, 1], true)
|
1006
|
-
@pos -= 1
|
1007
|
-
|
1008
|
-
# Delete the char before current char and move backward
|
1009
|
-
elsif op == BACKWARD_CHAR and @pos > 0
|
1010
|
-
add_delta([@pos - 1, DELETE, 1], true)
|
1011
|
-
@pos -= 1
|
1012
|
-
elsif op == FORWARD_CHAR #TODO: ok?
|
1013
|
-
add_delta([@pos + 1, DELETE, 1], true)
|
1014
|
-
end
|
1015
|
-
set_pos(@pos)
|
1016
|
-
#recalc_line_ends
|
1017
|
-
calculate_line_and_column_pos
|
1018
|
-
#need_redraw!
|
1019
|
-
end
|
1020
|
-
|
1021
|
-
def delete_range(startpos, endpos, x = nil)
|
1022
|
-
s = self[startpos..endpos]
|
1023
|
-
if startpos == endpos or s == ""
|
1024
|
-
return
|
1025
|
-
end
|
1026
|
-
if x == :append
|
1027
|
-
debug "APPEND"
|
1028
|
-
s += "\n" + get_clipboard()
|
1029
|
-
end
|
1030
|
-
set_clipboard(s)
|
1031
|
-
add_delta([startpos, DELETE, (endpos - startpos + 1)], true)
|
1032
|
-
#recalc_line_ends
|
1033
|
-
calculate_line_and_column_pos
|
1034
|
-
end
|
1035
|
-
|
795
|
+
|
1036
796
|
# Ranges to use in delete or copy operations
|
1037
797
|
def get_range(range_id, mark: nil)
|
1038
798
|
range = nil
|
@@ -1040,7 +800,7 @@ class Buffer < String
|
|
1040
800
|
# TODO: better way to make the search than + 150 from current position
|
1041
801
|
wmarks = get_word_end_marks(@pos, @pos + 150)
|
1042
802
|
if wmarks.any?
|
1043
|
-
range = @pos..wmarks[0]
|
803
|
+
range = @pos..(wmarks[0])
|
1044
804
|
end
|
1045
805
|
elsif range_id == :to_next_word # start of
|
1046
806
|
wmarks = get_word_start_marks(@pos, @pos + 150)
|
@@ -1324,141 +1084,6 @@ class Buffer < String
|
|
1324
1084
|
handle_word(wnfo)
|
1325
1085
|
end
|
1326
1086
|
|
1327
|
-
def jump_to_next_instance_of_word()
|
1328
|
-
if $kbd.last_action == $kbd.cur_action and @current_word != nil
|
1329
|
-
# debug "REPEATING *"
|
1330
|
-
else
|
1331
|
-
start_search = [@pos - 150, 0].max
|
1332
|
-
|
1333
|
-
search_str1 = self[start_search..(@pos)]
|
1334
|
-
wsmarks = scan_indexes(search_str1, /(?<=[^\p{Word}])\p{Word}/)
|
1335
|
-
a = wsmarks[-1]
|
1336
|
-
a = 0 if a == nil
|
1337
|
-
|
1338
|
-
search_str2 = self[(@pos)..(@pos + 150)]
|
1339
|
-
wemarks = scan_indexes(search_str2, /(?<=\p{Word})[^\p{Word}]/)
|
1340
|
-
b = wemarks[0]
|
1341
|
-
word_start = (@pos - search_str1.size + a + 1)
|
1342
|
-
word_start = 0 if !(word_start >= 0)
|
1343
|
-
@current_word = self[word_start..(@pos + b - 1)]
|
1344
|
-
end
|
1345
|
-
|
1346
|
-
#TODO: search for /[^\p{Word}]WORD[^\p{Word}]/
|
1347
|
-
position_of_next_word = self.index(@current_word, @pos + 1)
|
1348
|
-
if position_of_next_word != nil
|
1349
|
-
set_pos(position_of_next_word)
|
1350
|
-
else #Search from beginning
|
1351
|
-
position_of_next_word = self.index(@current_word)
|
1352
|
-
set_pos(position_of_next_word) if position_of_next_word != nil
|
1353
|
-
end
|
1354
|
-
center_on_current_line
|
1355
|
-
return true
|
1356
|
-
end
|
1357
|
-
|
1358
|
-
def jump_word(direction, wordpos)
|
1359
|
-
offset = 0
|
1360
|
-
if direction == FORWARD
|
1361
|
-
debug "POS: #{@pos},"
|
1362
|
-
search_str = self[(@pos)..(@pos + 250)]
|
1363
|
-
return if search_str == nil
|
1364
|
-
if wordpos == WORD_START # vim 'w'
|
1365
|
-
wsmarks = scan_indexes(search_str, /(?<=[^\p{Word}])\p{Word}|\Z/) # \Z = end of string, just before last newline.
|
1366
|
-
wsmarks2 = scan_indexes(search_str, /\n[ \t]*\n/) # "empty" lines that have whitespace
|
1367
|
-
wsmarks2 = wsmarks2.collect { |x| x + 1 }
|
1368
|
-
wsmarks = (wsmarks2 + wsmarks).sort.uniq
|
1369
|
-
offset = 0
|
1370
|
-
if wsmarks.any?
|
1371
|
-
next_pos = @pos + wsmarks[0] + offset
|
1372
|
-
set_pos(next_pos)
|
1373
|
-
end
|
1374
|
-
elsif wordpos == WORD_END
|
1375
|
-
search_str = self[(@pos + 1)..(@pos + 150)]
|
1376
|
-
wsmarks = scan_indexes(search_str, /(?<=\p{Word})[^\p{Word}]/)
|
1377
|
-
offset = -1
|
1378
|
-
if wsmarks.any?
|
1379
|
-
next_pos = @pos + 1 + wsmarks[0] + offset
|
1380
|
-
set_pos(next_pos)
|
1381
|
-
end
|
1382
|
-
end
|
1383
|
-
end
|
1384
|
-
if direction == BACKWARD # vim 'b'
|
1385
|
-
start_search = @pos - 150 #TODO 150 length limit
|
1386
|
-
start_search = 0 if start_search < 0
|
1387
|
-
search_str = self[start_search..(@pos - 1)]
|
1388
|
-
return if search_str == nil
|
1389
|
-
wsmarks = scan_indexes(search_str,
|
1390
|
-
#/(^|(\W)\w|\n)/) #TODO 150 length limit
|
1391
|
-
#/^|(?<=[^\p{Word}])\p{Word}|(?<=\n)\n/) #include empty lines?
|
1392
|
-
/\A|(?<=[^\p{Word}])\p{Word}/) # Start of string or nonword,word.
|
1393
|
-
|
1394
|
-
offset = 0
|
1395
|
-
|
1396
|
-
if wsmarks.any?
|
1397
|
-
next_pos = start_search + wsmarks.last + offset
|
1398
|
-
set_pos(next_pos)
|
1399
|
-
end
|
1400
|
-
end
|
1401
|
-
end
|
1402
|
-
|
1403
|
-
def jump_to_mark(mark_char)
|
1404
|
-
p = @marks[mark_char]
|
1405
|
-
set_pos(p) if p
|
1406
|
-
center_on_current_line
|
1407
|
-
return true
|
1408
|
-
end
|
1409
|
-
|
1410
|
-
def jump(target)
|
1411
|
-
if target == START_OF_BUFFER
|
1412
|
-
set_pos(0)
|
1413
|
-
end
|
1414
|
-
if target == END_OF_BUFFER
|
1415
|
-
set_pos(self.size - 1)
|
1416
|
-
end
|
1417
|
-
if target == BEGINNING_OF_LINE
|
1418
|
-
@cpos = 0
|
1419
|
-
calculate_pos_from_cpos_lpos
|
1420
|
-
end
|
1421
|
-
if target == END_OF_LINE
|
1422
|
-
@cpos = line(@lpos).size - 1
|
1423
|
-
calculate_pos_from_cpos_lpos
|
1424
|
-
end
|
1425
|
-
|
1426
|
-
if target == FIRST_NON_WHITESPACE
|
1427
|
-
l = current_line()
|
1428
|
-
debug l.inspect
|
1429
|
-
@cpos = line(@lpos).size - 1
|
1430
|
-
a = scan_indexes(l, /\S/)
|
1431
|
-
debug a.inspect
|
1432
|
-
if a.any?
|
1433
|
-
@cpos = a[0]
|
1434
|
-
else
|
1435
|
-
@cpos = 0
|
1436
|
-
end
|
1437
|
-
calculate_pos_from_cpos_lpos
|
1438
|
-
end
|
1439
|
-
end
|
1440
|
-
|
1441
|
-
def jump_to_line(line_n = 1)
|
1442
|
-
|
1443
|
-
# $method_handles_repeat = true
|
1444
|
-
# if !$next_command_count.nil? and $next_command_count > 0
|
1445
|
-
# line_n = $next_command_count
|
1446
|
-
# debug "jump to line:#{line_n}"
|
1447
|
-
# end
|
1448
|
-
debug "jump to line:#{line_n}"
|
1449
|
-
line_n = get_repeat_num() if line_n == 1
|
1450
|
-
|
1451
|
-
if line_n > @line_ends.size
|
1452
|
-
debug("lpos too large") #TODO
|
1453
|
-
return
|
1454
|
-
end
|
1455
|
-
if line_n == 1
|
1456
|
-
set_pos(0)
|
1457
|
-
else
|
1458
|
-
set_pos(@line_ends[line_n - 2] + 1)
|
1459
|
-
end
|
1460
|
-
end
|
1461
|
-
|
1462
1087
|
def join_lines()
|
1463
1088
|
if @lpos >= @line_ends.size - 1 # Cursor is on last line
|
1464
1089
|
debug("ON LAST LINE")
|
@@ -1472,28 +1097,6 @@ class Buffer < String
|
|
1472
1097
|
end
|
1473
1098
|
end
|
1474
1099
|
|
1475
|
-
def jump_to_next_instance_of_char(char, direction = FORWARD)
|
1476
|
-
|
1477
|
-
#return if at_end_of_line?
|
1478
|
-
if direction == FORWARD
|
1479
|
-
position_of_next_char = self.index(char, @pos + 1)
|
1480
|
-
if position_of_next_char != nil
|
1481
|
-
@pos = position_of_next_char
|
1482
|
-
end
|
1483
|
-
elsif direction == BACKWARD
|
1484
|
-
start_search = @pos - 250
|
1485
|
-
start_search = 0 if start_search < 0
|
1486
|
-
search_substr = self[start_search..(@pos - 1)]
|
1487
|
-
_pos = search_substr.reverse.index(char)
|
1488
|
-
if _pos != nil
|
1489
|
-
@pos -= (_pos + 1)
|
1490
|
-
end
|
1491
|
-
end
|
1492
|
-
m = method("jump_to_next_instance_of_char")
|
1493
|
-
set_last_command({ method: m, params: [char, direction] })
|
1494
|
-
$last_find_command = { char: char, direction: direction }
|
1495
|
-
set_pos(@pos)
|
1496
|
-
end
|
1497
1100
|
|
1498
1101
|
def replace_with_char(char)
|
1499
1102
|
debug "self_pos:'#{self[@pos]}'"
|
@@ -1619,94 +1222,6 @@ class Buffer < String
|
|
1619
1222
|
@need_redraw = false
|
1620
1223
|
end
|
1621
1224
|
|
1622
|
-
# Create a new line after current line and insert text on that line
|
1623
|
-
def put_to_new_next_line(txt)
|
1624
|
-
l = current_line_range()
|
1625
|
-
insert_txt_at(txt, l.end + 1)
|
1626
|
-
set_pos(l.end + 1)
|
1627
|
-
end
|
1628
|
-
|
1629
|
-
# Start asynchronous read of system clipboard
|
1630
|
-
def paste_start(at, register)
|
1631
|
-
@clipboard_paste_running = true
|
1632
|
-
clipboard = vma.gui.window.display.clipboard
|
1633
|
-
clipboard.read_text_async do |_clipboard, result|
|
1634
|
-
begin
|
1635
|
-
text = clipboard.read_text_finish(result)
|
1636
|
-
rescue Gio::IOError::NotSupported
|
1637
|
-
# Happens when pasting from KeePassX and clipboard cleared
|
1638
|
-
debug Gio::IOError::NotSupported
|
1639
|
-
else
|
1640
|
-
paste_finish(text, at, register)
|
1641
|
-
end
|
1642
|
-
end
|
1643
|
-
end
|
1644
|
-
|
1645
|
-
def paste_finish(text, at, register)
|
1646
|
-
debug "PASTE: #{text}"
|
1647
|
-
|
1648
|
-
# If we did not put this text to clipboard
|
1649
|
-
if text != $clipboard[-1]
|
1650
|
-
@paste_lines = false
|
1651
|
-
end
|
1652
|
-
|
1653
|
-
text = sanitize_input(text)
|
1654
|
-
|
1655
|
-
$clipboard << text
|
1656
|
-
|
1657
|
-
return if text == ""
|
1658
|
-
|
1659
|
-
if @paste_lines
|
1660
|
-
debug "PASTE LINES"
|
1661
|
-
put_to_new_next_line(text)
|
1662
|
-
else
|
1663
|
-
if at_end_of_buffer? or at_end_of_line? or at == BEFORE
|
1664
|
-
pos = @pos
|
1665
|
-
else
|
1666
|
-
pos = @pos + 1
|
1667
|
-
end
|
1668
|
-
insert_txt_at(text, pos)
|
1669
|
-
set_pos(pos + text.size)
|
1670
|
-
end
|
1671
|
-
set_pos(@pos)
|
1672
|
-
@clipboard_paste_running = false
|
1673
|
-
end
|
1674
|
-
|
1675
|
-
def paste(at = AFTER, register = nil)
|
1676
|
-
# Macro's don't work with asynchronous call using GTK
|
1677
|
-
# TODO: implement as synchronous?
|
1678
|
-
# Use internal clipboard
|
1679
|
-
if vma.macro.running_macro
|
1680
|
-
text = get_clipboard()
|
1681
|
-
paste_finish(text, at, register)
|
1682
|
-
else
|
1683
|
-
# Get clipboard using GUI
|
1684
|
-
paste_start(at, register)
|
1685
|
-
end
|
1686
|
-
return true
|
1687
|
-
end
|
1688
|
-
|
1689
|
-
def delete_line()
|
1690
|
-
$method_handles_repeat = true
|
1691
|
-
num_lines = 1
|
1692
|
-
if !$next_command_count.nil? and $next_command_count > 0
|
1693
|
-
num_lines = $next_command_count
|
1694
|
-
debug "copy num_lines:#{num_lines}"
|
1695
|
-
end
|
1696
|
-
lrange = line_range(@lpos, num_lines)
|
1697
|
-
s = self[lrange]
|
1698
|
-
add_delta([lrange.begin, DELETE, lrange.end - lrange.begin + 1], true)
|
1699
|
-
set_clipboard(s)
|
1700
|
-
update_pos(lrange.begin)
|
1701
|
-
@paste_lines = true
|
1702
|
-
#recalc_line_ends
|
1703
|
-
end
|
1704
|
-
|
1705
|
-
def update_pos(pos)
|
1706
|
-
@pos = pos
|
1707
|
-
calculate_line_and_column_pos
|
1708
|
-
end
|
1709
|
-
|
1710
1225
|
def start_visual_mode()
|
1711
1226
|
@visual_mode = true
|
1712
1227
|
@selection_start = @pos
|
@@ -1722,10 +1237,10 @@ class Buffer < String
|
|
1722
1237
|
s = self[get_visual_mode_range]
|
1723
1238
|
if x == :append
|
1724
1239
|
debug "APPEND"
|
1725
|
-
s += "\n" +
|
1240
|
+
s += "\n" + vma.clipboard.get()
|
1726
1241
|
end
|
1727
1242
|
|
1728
|
-
|
1243
|
+
vma.clipboard.set(s)
|
1729
1244
|
end_visual_mode
|
1730
1245
|
return true
|
1731
1246
|
end
|
@@ -1788,29 +1303,29 @@ class Buffer < String
|
|
1788
1303
|
end
|
1789
1304
|
|
1790
1305
|
def copy_line()
|
1791
|
-
|
1306
|
+
vma.kbd.method_handles_repeat = true
|
1792
1307
|
num_lines = 1
|
1793
|
-
if
|
1794
|
-
num_lines =
|
1308
|
+
if !vma.kbd.next_command_count.nil? and vma.kbd.next_command_count > 0
|
1309
|
+
num_lines = vma.kbd.next_command_count
|
1795
1310
|
debug "copy num_lines:#{num_lines}"
|
1796
1311
|
end
|
1797
|
-
|
1312
|
+
vma.clipboard.set(self[line_range(@lpos, num_lines)])
|
1798
1313
|
@paste_lines = true
|
1799
1314
|
end
|
1800
1315
|
|
1801
1316
|
def put_file_path_to_clipboard
|
1802
|
-
|
1317
|
+
vma.clipboard.set(self.fname)
|
1803
1318
|
end
|
1804
1319
|
|
1805
1320
|
def put_file_ref_to_clipboard
|
1806
|
-
|
1321
|
+
vma.clipboard.set(self.fname + ":#{@lpos}")
|
1807
1322
|
end
|
1808
1323
|
|
1809
1324
|
def delete_active_selection() #TODO: remove this function
|
1810
1325
|
return if !@visual_mode #TODO: this should not happen
|
1811
1326
|
|
1812
1327
|
_start, _end = get_visual_mode_range
|
1813
|
-
|
1328
|
+
vma.clipboard.set(self[_start, _end])
|
1814
1329
|
end_visual_mode
|
1815
1330
|
end
|
1816
1331
|
|
@@ -1870,7 +1385,7 @@ class Buffer < String
|
|
1870
1385
|
savepath = ""
|
1871
1386
|
|
1872
1387
|
# If current file has fname, save to that fname
|
1873
|
-
# Else search for previously
|
1388
|
+
# Else search for previously opened files and save to the directory of
|
1874
1389
|
# the last viewed file that has a filename
|
1875
1390
|
# selffers[$buffer_history.reverse[1]].fname
|
1876
1391
|
|
@@ -1894,7 +1409,7 @@ class Buffer < String
|
|
1894
1409
|
# Keeping this code from GTK3 in case want to do this manually at some point
|
1895
1410
|
# if !confirmed
|
1896
1411
|
# @unconfirmed_path = fpath
|
1897
|
-
# if File.
|
1412
|
+
# if File.exist?(fpath) and File.file?(fpath)
|
1898
1413
|
# params = {}
|
1899
1414
|
# params["title"] = "The file already exists, overwrite? \r #{fpath}"
|
1900
1415
|
# params["inputs"] = {}
|
@@ -1903,7 +1418,7 @@ class Buffer < String
|
|
1903
1418
|
# params[:callback] = callback
|
1904
1419
|
# PopupFormGenerator.new(params).run
|
1905
1420
|
# return
|
1906
|
-
# elsif File.
|
1421
|
+
# elsif File.exist?(fpath) #and File.directory?(fpath)
|
1907
1422
|
# params = {}
|
1908
1423
|
# params["title"] = "Can't write to the destination.\r #{fpath}"
|
1909
1424
|
# params["inputs"] = {}
|
@@ -1995,44 +1510,6 @@ class Buffer < String
|
|
1995
1510
|
write_contents_to_file(@fname)
|
1996
1511
|
end
|
1997
1512
|
|
1998
|
-
# Indents whole buffer using external program
|
1999
|
-
def indent()
|
2000
|
-
file = Tempfile.new("out")
|
2001
|
-
infile = Tempfile.new("in")
|
2002
|
-
file.write(self.to_s)
|
2003
|
-
file.flush
|
2004
|
-
bufc = "FOO"
|
2005
|
-
|
2006
|
-
tmppos = @pos
|
2007
|
-
|
2008
|
-
message("Auto format #{@fname}")
|
2009
|
-
|
2010
|
-
ftype = get_file_type()
|
2011
|
-
if ["chdr", "c", "cpp", "cpphdr"].include?(ftype)
|
2012
|
-
|
2013
|
-
#C/C++/Java/JavaScript/Objective-C/Protobuf code
|
2014
|
-
system("clang-format -style='{BasedOnStyle: LLVM, ColumnLimit: 100, SortIncludes: false}' #{file.path} > #{infile.path}")
|
2015
|
-
bufc = IO.read(infile.path)
|
2016
|
-
elsif ftype == "Javascript"
|
2017
|
-
cmd = "clang-format #{file.path} > #{infile.path}'"
|
2018
|
-
debug cmd
|
2019
|
-
system(cmd)
|
2020
|
-
bufc = IO.read(infile.path)
|
2021
|
-
elsif ftype == "ruby"
|
2022
|
-
cmd = "rufo #{file.path}"
|
2023
|
-
debug cmd
|
2024
|
-
system(cmd)
|
2025
|
-
bufc = IO.read(file.path)
|
2026
|
-
else
|
2027
|
-
message("No auto-format handler for file of type: #{ftype}")
|
2028
|
-
return
|
2029
|
-
end
|
2030
|
-
self.update_content(bufc)
|
2031
|
-
center_on_current_line #TODO: needed?
|
2032
|
-
file.close; file.unlink
|
2033
|
-
infile.close; infile.unlink
|
2034
|
-
end
|
2035
|
-
|
2036
1513
|
def close()
|
2037
1514
|
idx = vma.buffers.get_buffer_by_id(@id)
|
2038
1515
|
vma.buffers.close_buffer(idx)
|