vimamsa 0.1.12 → 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 +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
data/lib/vimamsa/buffer.rb
CHANGED
@@ -5,7 +5,6 @@ require "pathname"
|
|
5
5
|
require "openssl"
|
6
6
|
require "ripl/multi_line"
|
7
7
|
|
8
|
-
$paste_lines = false
|
9
8
|
$buffer_history = []
|
10
9
|
|
11
10
|
$update_highlight = false
|
@@ -15,7 +14,7 @@ $ifuncon = false
|
|
15
14
|
class Buffer < String
|
16
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
|
17
16
|
attr_writer :call_func, :update_highlight
|
18
|
-
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
|
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
|
19
18
|
|
20
19
|
@@num_buffers = 0
|
21
20
|
|
@@ -29,9 +28,14 @@ class Buffer < String
|
|
29
28
|
@id = @@num_buffers
|
30
29
|
@@num_buffers += 1
|
31
30
|
@version = 0
|
31
|
+
@mode_stack = [:command] # TODO
|
32
|
+
@default_mode = :command # TODO
|
32
33
|
gui_create_buffer(@id, self)
|
33
34
|
debug "NEW BUFFER fn=#{fname} ID:#{@id}"
|
34
35
|
|
36
|
+
# If true, we will create new line after this and paste there
|
37
|
+
@paste_lines = false
|
38
|
+
|
35
39
|
@module = nil
|
36
40
|
|
37
41
|
@last_save = @last_asked_from_user = @file_last_cheked = Time.now
|
@@ -89,15 +93,14 @@ class Buffer < String
|
|
89
93
|
|
90
94
|
def set_active
|
91
95
|
if !@active_kbd_mode.nil?
|
92
|
-
$kbd.set_mode(@active_kbd_mode)
|
96
|
+
# $kbd.set_mode(@active_kbd_mode) #TODO: remove?
|
93
97
|
else
|
94
98
|
$kbd.set_mode_to_default
|
95
99
|
end
|
96
|
-
# gui_set_current_buffer(@id)
|
97
100
|
end
|
98
101
|
|
99
102
|
def set_executable
|
100
|
-
if File.
|
103
|
+
if File.exist?(@fname)
|
101
104
|
FileUtils.chmod("+x", @fname)
|
102
105
|
message("Set executable: #{@fname}")
|
103
106
|
end
|
@@ -211,6 +214,7 @@ class Buffer < String
|
|
211
214
|
$audiof = mf
|
212
215
|
end
|
213
216
|
|
217
|
+
#TODO: remove?
|
214
218
|
def reset_audio_widget_positions
|
215
219
|
debug "reset_audio_widget_positions", 2
|
216
220
|
for mc in @audiofiles
|
@@ -244,16 +248,6 @@ class Buffer < String
|
|
244
248
|
gui_set_current_buffer(@id) #TODO: needed?
|
245
249
|
end
|
246
250
|
|
247
|
-
def is_legal_pos(pos, op = :read)
|
248
|
-
return false if pos < 0
|
249
|
-
if op == :add
|
250
|
-
return false if pos > self.size
|
251
|
-
elsif op == :read
|
252
|
-
return false if pos >= self.size
|
253
|
-
end
|
254
|
-
return true
|
255
|
-
end
|
256
|
-
|
257
251
|
def set_encrypted(password)
|
258
252
|
@crypt = Encrypt.new(password)
|
259
253
|
message("Set buffer encrypted")
|
@@ -263,19 +257,18 @@ class Buffer < String
|
|
263
257
|
@crypt = nil
|
264
258
|
end
|
265
259
|
|
266
|
-
def
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
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
|
+
}
|
279
272
|
end
|
280
273
|
|
281
274
|
def handle_drag_and_drop(fname)
|
@@ -298,13 +291,14 @@ class Buffer < String
|
|
298
291
|
|
299
292
|
def revert()
|
300
293
|
return if !@fname
|
301
|
-
return if !File.
|
294
|
+
return if !File.exist?(@fname)
|
302
295
|
message("Revert buffer #{@fname}")
|
303
296
|
str = read_file("", @fname)
|
304
297
|
self.set_content(str)
|
305
298
|
end
|
306
299
|
|
307
300
|
def decrypt(password)
|
301
|
+
return if @encrypted_str.nil?
|
308
302
|
begin
|
309
303
|
@crypt = Encrypt.new(password)
|
310
304
|
str = @crypt.decrypt(@encrypted_str)
|
@@ -345,11 +339,9 @@ class Buffer < String
|
|
345
339
|
@ftype = nil
|
346
340
|
if str[0..10] == "VMACRYPT001"
|
347
341
|
@encrypted_str = str[11..-1]
|
348
|
-
callback = proc { |x|
|
349
|
-
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 })
|
350
344
|
str = "ENCRYPTED"
|
351
|
-
else
|
352
|
-
# @crypt = nil
|
353
345
|
end
|
354
346
|
|
355
347
|
if (str[-1] != "\n")
|
@@ -359,10 +351,9 @@ class Buffer < String
|
|
359
351
|
self.replace(str)
|
360
352
|
@line_ends = scan_indexes(self, /\n/)
|
361
353
|
|
362
|
-
|
363
|
-
if $experimental
|
354
|
+
if cnf.btree.experimental?
|
364
355
|
@bt = BufferTree.new(self)
|
365
|
-
if
|
356
|
+
if cnf.debug?
|
366
357
|
sanitycheck_btree()
|
367
358
|
end
|
368
359
|
end
|
@@ -398,7 +389,6 @@ class Buffer < String
|
|
398
389
|
gui_set_buffer_contents(@id, self.to_s)
|
399
390
|
@images = [] #TODO: if reload
|
400
391
|
hpt_scan_images(self)
|
401
|
-
hpt_scan_audio(self)
|
402
392
|
|
403
393
|
# add_hl_update(@update_hl_startpos, @update_hl_endpos)
|
404
394
|
end
|
@@ -425,65 +415,6 @@ class Buffer < String
|
|
425
415
|
return fpath
|
426
416
|
end
|
427
417
|
|
428
|
-
def line(lpos)
|
429
|
-
if @line_ends.size == 0
|
430
|
-
return self
|
431
|
-
end
|
432
|
-
|
433
|
-
#TODO: implement using line_range()
|
434
|
-
if lpos >= @line_ends.size
|
435
|
-
debug("lpos too large") #TODO
|
436
|
-
return ""
|
437
|
-
elsif lpos == @line_ends.size
|
438
|
-
end
|
439
|
-
start = @line_ends[lpos - 1] + 1 if lpos > 0
|
440
|
-
start = 0 if lpos == 0
|
441
|
-
_end = @line_ends[lpos]
|
442
|
-
debug "start: _#{start}, end: #{_end}"
|
443
|
-
return self[start.._end]
|
444
|
-
end
|
445
|
-
|
446
|
-
def is_delta_ok(delta)
|
447
|
-
ret = true
|
448
|
-
pos = delta[0]
|
449
|
-
if pos < 0
|
450
|
-
ret = false
|
451
|
-
debug "pos=#{pos} < 0"
|
452
|
-
elsif pos > self.size
|
453
|
-
debug "pos=#{pos} > self.size=#{self.size}"
|
454
|
-
ret = false
|
455
|
-
end
|
456
|
-
if ret == false
|
457
|
-
# crash("DELTA OK=#{ret}")
|
458
|
-
end
|
459
|
-
return ret
|
460
|
-
end
|
461
|
-
|
462
|
-
#TODO: change to apply=true as default
|
463
|
-
def add_delta(delta, apply = false, auto_update_cpos = false)
|
464
|
-
return if !is_delta_ok(delta)
|
465
|
-
if delta[1] == DELETE
|
466
|
-
return if delta[0] >= self.size
|
467
|
-
# If go over length of buffer
|
468
|
-
if delta[0] + delta[2] >= self.size
|
469
|
-
delta[2] = self.size - delta[0]
|
470
|
-
end
|
471
|
-
end
|
472
|
-
|
473
|
-
@edit_version += 1
|
474
|
-
@redo_stack = []
|
475
|
-
if apply
|
476
|
-
delta = run_delta(delta, auto_update_cpos)
|
477
|
-
else
|
478
|
-
@deltas << delta
|
479
|
-
end
|
480
|
-
@edit_history << delta
|
481
|
-
if self[-1] != "\n"
|
482
|
-
add_delta([self.size, INSERT, 1, "\n"], true)
|
483
|
-
end
|
484
|
-
reset_larger_cpos #TODO: correct here?
|
485
|
-
end
|
486
|
-
|
487
418
|
def add_hl_update(startpos, endpos)
|
488
419
|
return if @is_highlighted == false
|
489
420
|
|
@@ -500,7 +431,7 @@ class Buffer < String
|
|
500
431
|
# delta[3]: text to add in case of insert
|
501
432
|
|
502
433
|
@version += 1
|
503
|
-
if
|
434
|
+
if cnf.btree.experimental?
|
504
435
|
@bt.handle_delta(Delta.new(delta[0], delta[1], delta[2], delta[3]))
|
505
436
|
end
|
506
437
|
|
@@ -584,34 +515,6 @@ class Buffer < String
|
|
584
515
|
end
|
585
516
|
end
|
586
517
|
|
587
|
-
def jump_to_last_edit()
|
588
|
-
return if @edit_pos_history.empty?
|
589
|
-
@edit_pos_history_i += 1
|
590
|
-
|
591
|
-
if @edit_pos_history_i > @edit_pos_history.size
|
592
|
-
@edit_pos_history_i = 0
|
593
|
-
end
|
594
|
-
|
595
|
-
# if @edit_pos_history.size >= @edit_pos_history_i
|
596
|
-
set_pos(@edit_pos_history[-@edit_pos_history_i])
|
597
|
-
center_on_current_line
|
598
|
-
return true
|
599
|
-
# end
|
600
|
-
end
|
601
|
-
|
602
|
-
def jump_to_next_edit()
|
603
|
-
return if @edit_pos_history.empty?
|
604
|
-
@edit_pos_history_i -= 1
|
605
|
-
@edit_pos_history_i = @edit_pos_history.size - 1 if @edit_pos_history_i < 0
|
606
|
-
debug "@edit_pos_history_i=#{@edit_pos_history_i}"
|
607
|
-
set_pos(@edit_pos_history[-@edit_pos_history_i])
|
608
|
-
center_on_current_line
|
609
|
-
return true
|
610
|
-
end
|
611
|
-
|
612
|
-
def jump_to_random_pos()
|
613
|
-
set_pos(rand(self.size))
|
614
|
-
end
|
615
518
|
|
616
519
|
def undo()
|
617
520
|
debug @edit_history.inspect
|
@@ -756,10 +659,10 @@ class Buffer < String
|
|
756
659
|
end
|
757
660
|
|
758
661
|
def get_repeat_num()
|
759
|
-
|
662
|
+
vma.kbd.method_handles_repeat = true
|
760
663
|
repeat_num = 1
|
761
|
-
if
|
762
|
-
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
|
763
666
|
end
|
764
667
|
return repeat_num
|
765
668
|
end
|
@@ -803,12 +706,12 @@ class Buffer < String
|
|
803
706
|
end
|
804
707
|
|
805
708
|
def copy(range_id)
|
806
|
-
|
709
|
+
@paste_lines = false
|
807
710
|
debug "range_id: #{range_id}"
|
808
711
|
debug range_id.inspect
|
809
712
|
range = get_range(range_id)
|
810
713
|
debug range.inspect
|
811
|
-
|
714
|
+
vma.clipboard.set(self[range])
|
812
715
|
end
|
813
716
|
|
814
717
|
def recalc_line_ends()
|
@@ -889,152 +792,15 @@ class Buffer < String
|
|
889
792
|
@line_ends.sort!
|
890
793
|
end
|
891
794
|
end
|
892
|
-
|
893
|
-
def at_end_of_line?()
|
894
|
-
return (self[@pos] == "\n" or at_end_of_buffer?)
|
895
|
-
end
|
896
|
-
|
897
|
-
def at_end_of_buffer?()
|
898
|
-
return @pos == self.size
|
899
|
-
end
|
900
|
-
|
901
|
-
def jump_to_pos(new_pos)
|
902
|
-
set_pos(new_pos)
|
903
|
-
end
|
904
|
-
|
905
|
-
def set_pos(new_pos)
|
906
|
-
if new_pos >= self.size
|
907
|
-
@pos = self.size - 1 # TODO:??right side of last char
|
908
|
-
elsif new_pos >= 0
|
909
|
-
@pos = new_pos
|
910
|
-
end
|
911
|
-
gui_set_cursor_pos(@id, @pos)
|
912
|
-
calculate_line_and_column_pos
|
913
|
-
|
914
|
-
check_if_modified_outside
|
915
|
-
end
|
916
|
-
|
917
|
-
# Get the line number of character position
|
918
|
-
def get_line_pos(pos)
|
919
|
-
lpos = @line_ends.bsearch_index { |x, _| x >= pos }
|
920
|
-
return lpos
|
921
|
-
end
|
922
|
-
|
923
|
-
# Calculate the two dimensional column and line positions based on
|
924
|
-
# (one dimensional) position in the buffer.
|
925
|
-
def get_line_and_col_pos(pos)
|
926
|
-
pos = self.size if pos > self.size
|
927
|
-
pos = 0 if pos < 0
|
928
|
-
|
929
|
-
lpos = get_line_pos(pos)
|
930
|
-
|
931
|
-
lpos = @line_ends.size if lpos == nil
|
932
|
-
cpos = pos
|
933
|
-
cpos -= @line_ends[lpos - 1] + 1 if lpos > 0
|
934
|
-
|
935
|
-
return [lpos, cpos]
|
936
|
-
end
|
937
|
-
|
938
|
-
def calculate_line_and_column_pos(reset = true)
|
939
|
-
@lpos, @cpos = get_line_and_col_pos(@pos)
|
940
|
-
reset_larger_cpos if reset
|
941
|
-
end
|
942
|
-
|
943
|
-
def set_line_and_column_pos(lpos, cpos, _reset_larger_cpos = true)
|
944
|
-
@lpos = lpos if !lpos.nil?
|
945
|
-
@cpos = cpos if !cpos.nil?
|
946
|
-
if @lpos > 0
|
947
|
-
new_pos = @line_ends[@lpos - 1] + 1
|
948
|
-
else
|
949
|
-
new_pos = 0
|
950
|
-
end
|
951
|
-
|
952
|
-
if @cpos > (line(@lpos).size - 1)
|
953
|
-
debug("$cpos too large: #{@cpos} #{@lpos}")
|
954
|
-
if @larger_cpos < @cpos
|
955
|
-
@larger_cpos = @cpos
|
956
|
-
end
|
957
|
-
@cpos = line(@lpos).size - 1
|
958
|
-
end
|
959
|
-
new_pos += @cpos
|
960
|
-
set_pos(new_pos)
|
961
|
-
reset_larger_cpos if _reset_larger_cpos
|
962
|
-
end
|
963
|
-
|
964
|
-
# Calculate the one dimensional array index based on column and line positions
|
965
|
-
def calculate_pos_from_cpos_lpos(reset = true)
|
966
|
-
set_line_and_column_pos(nil, nil)
|
967
|
-
end
|
968
|
-
|
969
|
-
def delete2(range_id)
|
970
|
-
$paste_lines = false
|
971
|
-
range = get_range(range_id)
|
972
|
-
return if range == nil
|
973
|
-
debug "RANGE"
|
974
|
-
debug range.inspect
|
975
|
-
debug range.inspect
|
976
|
-
debug "------"
|
977
|
-
delete_range(range.first, range.last)
|
978
|
-
pos = [range.first, @pos].min
|
979
|
-
set_pos(pos)
|
980
|
-
end
|
981
|
-
|
982
|
-
def delete(op, x = nil)
|
983
|
-
$paste_lines = false
|
984
|
-
# Delete selection
|
985
|
-
if op == SELECTION && visual_mode?
|
986
|
-
(startpos, endpos) = get_visual_mode_range2
|
987
|
-
delete_range(startpos, endpos, x)
|
988
|
-
@pos = [@pos, @selection_start].min
|
989
|
-
end_visual_mode
|
990
|
-
#return
|
991
|
-
|
992
|
-
# Delete current char
|
993
|
-
elsif op == CURRENT_CHAR_FORWARD
|
994
|
-
return if @pos >= self.size - 1 # May not delete last '\n'
|
995
|
-
add_delta([@pos, DELETE, 1], true)
|
996
|
-
|
997
|
-
# Delete current char and then move backward
|
998
|
-
elsif op == CURRENT_CHAR_BACKWARD
|
999
|
-
add_delta([@pos, DELETE, 1], true)
|
1000
|
-
@pos -= 1
|
1001
|
-
|
1002
|
-
# Delete the char before current char and move backward
|
1003
|
-
elsif op == BACKWARD_CHAR and @pos > 0
|
1004
|
-
add_delta([@pos - 1, DELETE, 1], true)
|
1005
|
-
@pos -= 1
|
1006
|
-
elsif op == FORWARD_CHAR #TODO: ok?
|
1007
|
-
add_delta([@pos + 1, DELETE, 1], true)
|
1008
|
-
end
|
1009
|
-
set_pos(@pos)
|
1010
|
-
#recalc_line_ends
|
1011
|
-
calculate_line_and_column_pos
|
1012
|
-
#need_redraw!
|
1013
|
-
end
|
1014
|
-
|
1015
|
-
def delete_range(startpos, endpos, x = nil)
|
1016
|
-
s = self[startpos..endpos]
|
1017
|
-
if startpos == endpos or s == ""
|
1018
|
-
return
|
1019
|
-
end
|
1020
|
-
if x == :append
|
1021
|
-
debug "APPEND"
|
1022
|
-
s += "\n" + get_clipboard()
|
1023
|
-
end
|
1024
|
-
set_clipboard(s)
|
1025
|
-
add_delta([startpos, DELETE, (endpos - startpos + 1)], true)
|
1026
|
-
#recalc_line_ends
|
1027
|
-
calculate_line_and_column_pos
|
1028
|
-
end
|
1029
|
-
|
795
|
+
|
1030
796
|
# Ranges to use in delete or copy operations
|
1031
|
-
def get_range(range_id)
|
797
|
+
def get_range(range_id, mark: nil)
|
1032
798
|
range = nil
|
1033
799
|
if range_id == :to_word_end
|
1034
800
|
# TODO: better way to make the search than + 150 from current position
|
1035
801
|
wmarks = get_word_end_marks(@pos, @pos + 150)
|
1036
802
|
if wmarks.any?
|
1037
|
-
range = @pos..wmarks[0]
|
803
|
+
range = @pos..(wmarks[0])
|
1038
804
|
end
|
1039
805
|
elsif range_id == :to_next_word # start of
|
1040
806
|
wmarks = get_word_start_marks(@pos, @pos + 150)
|
@@ -1045,6 +811,16 @@ class Buffer < String
|
|
1045
811
|
range = get_range(:to_word_end)
|
1046
812
|
end
|
1047
813
|
# Ripl.start :binding => binding
|
814
|
+
|
815
|
+
elsif range_id == :to_mark
|
816
|
+
debug "TO MARK"
|
817
|
+
start = @line_ends[@lpos]
|
818
|
+
mpos = @marks[mark]
|
819
|
+
if !mpos.nil?
|
820
|
+
range = start..mpos
|
821
|
+
else
|
822
|
+
return nil
|
823
|
+
end
|
1048
824
|
elsif range_id == :to_line_end
|
1049
825
|
debug "TO LINE END"
|
1050
826
|
range = @pos..(@line_ends[@lpos] - 1)
|
@@ -1068,15 +844,18 @@ class Buffer < String
|
|
1068
844
|
end
|
1069
845
|
return range if range == nil
|
1070
846
|
if range.last < range.first
|
1071
|
-
range
|
847
|
+
range = range.last..range.first
|
848
|
+
# range.last = range.first
|
1072
849
|
end
|
1073
850
|
if range.first < 0
|
1074
|
-
range.first = 0
|
851
|
+
# range.first = 0
|
852
|
+
range = 0..range.last
|
1075
853
|
end
|
1076
854
|
if range.last >= self.size
|
1077
|
-
range.last = self.size - 1
|
855
|
+
# range.last = self.size - 1
|
856
|
+
range = range.first..(self.size - 1)
|
1078
857
|
end
|
1079
|
-
|
858
|
+
debug range, 2
|
1080
859
|
return range
|
1081
860
|
end
|
1082
861
|
|
@@ -1305,141 +1084,6 @@ class Buffer < String
|
|
1305
1084
|
handle_word(wnfo)
|
1306
1085
|
end
|
1307
1086
|
|
1308
|
-
def jump_to_next_instance_of_word()
|
1309
|
-
if $kbd.last_action == $kbd.cur_action and @current_word != nil
|
1310
|
-
# debug "REPEATING *"
|
1311
|
-
else
|
1312
|
-
start_search = [@pos - 150, 0].max
|
1313
|
-
|
1314
|
-
search_str1 = self[start_search..(@pos)]
|
1315
|
-
wsmarks = scan_indexes(search_str1, /(?<=[^\p{Word}])\p{Word}/)
|
1316
|
-
a = wsmarks[-1]
|
1317
|
-
a = 0 if a == nil
|
1318
|
-
|
1319
|
-
search_str2 = self[(@pos)..(@pos + 150)]
|
1320
|
-
wemarks = scan_indexes(search_str2, /(?<=\p{Word})[^\p{Word}]/)
|
1321
|
-
b = wemarks[0]
|
1322
|
-
word_start = (@pos - search_str1.size + a + 1)
|
1323
|
-
word_start = 0 if !(word_start >= 0)
|
1324
|
-
@current_word = self[word_start..(@pos + b - 1)]
|
1325
|
-
end
|
1326
|
-
|
1327
|
-
#TODO: search for /[^\p{Word}]WORD[^\p{Word}]/
|
1328
|
-
position_of_next_word = self.index(@current_word, @pos + 1)
|
1329
|
-
if position_of_next_word != nil
|
1330
|
-
set_pos(position_of_next_word)
|
1331
|
-
else #Search from beginning
|
1332
|
-
position_of_next_word = self.index(@current_word)
|
1333
|
-
set_pos(position_of_next_word) if position_of_next_word != nil
|
1334
|
-
end
|
1335
|
-
center_on_current_line
|
1336
|
-
return true
|
1337
|
-
end
|
1338
|
-
|
1339
|
-
def jump_word(direction, wordpos)
|
1340
|
-
offset = 0
|
1341
|
-
if direction == FORWARD
|
1342
|
-
debug "POS: #{@pos},"
|
1343
|
-
search_str = self[(@pos)..(@pos + 250)]
|
1344
|
-
return if search_str == nil
|
1345
|
-
if wordpos == WORD_START # vim 'w'
|
1346
|
-
wsmarks = scan_indexes(search_str, /(?<=[^\p{Word}])\p{Word}|\Z/) # \Z = end of string, just before last newline.
|
1347
|
-
wsmarks2 = scan_indexes(search_str, /\n[ \t]*\n/) # "empty" lines that have whitespace
|
1348
|
-
wsmarks2 = wsmarks2.collect { |x| x + 1 }
|
1349
|
-
wsmarks = (wsmarks2 + wsmarks).sort.uniq
|
1350
|
-
offset = 0
|
1351
|
-
if wsmarks.any?
|
1352
|
-
next_pos = @pos + wsmarks[0] + offset
|
1353
|
-
set_pos(next_pos)
|
1354
|
-
end
|
1355
|
-
elsif wordpos == WORD_END
|
1356
|
-
search_str = self[(@pos + 1)..(@pos + 150)]
|
1357
|
-
wsmarks = scan_indexes(search_str, /(?<=\p{Word})[^\p{Word}]/)
|
1358
|
-
offset = -1
|
1359
|
-
if wsmarks.any?
|
1360
|
-
next_pos = @pos + 1 + wsmarks[0] + offset
|
1361
|
-
set_pos(next_pos)
|
1362
|
-
end
|
1363
|
-
end
|
1364
|
-
end
|
1365
|
-
if direction == BACKWARD # vim 'b'
|
1366
|
-
start_search = @pos - 150 #TODO 150 length limit
|
1367
|
-
start_search = 0 if start_search < 0
|
1368
|
-
search_str = self[start_search..(@pos - 1)]
|
1369
|
-
return if search_str == nil
|
1370
|
-
wsmarks = scan_indexes(search_str,
|
1371
|
-
#/(^|(\W)\w|\n)/) #TODO 150 length limit
|
1372
|
-
#/^|(?<=[^\p{Word}])\p{Word}|(?<=\n)\n/) #include empty lines?
|
1373
|
-
/\A|(?<=[^\p{Word}])\p{Word}/) # Start of string or nonword,word.
|
1374
|
-
|
1375
|
-
offset = 0
|
1376
|
-
|
1377
|
-
if wsmarks.any?
|
1378
|
-
next_pos = start_search + wsmarks.last + offset
|
1379
|
-
set_pos(next_pos)
|
1380
|
-
end
|
1381
|
-
end
|
1382
|
-
end
|
1383
|
-
|
1384
|
-
def jump_to_mark(mark_char)
|
1385
|
-
p = @marks[mark_char]
|
1386
|
-
set_pos(p) if p
|
1387
|
-
center_on_current_line
|
1388
|
-
return true
|
1389
|
-
end
|
1390
|
-
|
1391
|
-
def jump(target)
|
1392
|
-
if target == START_OF_BUFFER
|
1393
|
-
set_pos(0)
|
1394
|
-
end
|
1395
|
-
if target == END_OF_BUFFER
|
1396
|
-
set_pos(self.size - 1)
|
1397
|
-
end
|
1398
|
-
if target == BEGINNING_OF_LINE
|
1399
|
-
@cpos = 0
|
1400
|
-
calculate_pos_from_cpos_lpos
|
1401
|
-
end
|
1402
|
-
if target == END_OF_LINE
|
1403
|
-
@cpos = line(@lpos).size - 1
|
1404
|
-
calculate_pos_from_cpos_lpos
|
1405
|
-
end
|
1406
|
-
|
1407
|
-
if target == FIRST_NON_WHITESPACE
|
1408
|
-
l = current_line()
|
1409
|
-
debug l.inspect
|
1410
|
-
@cpos = line(@lpos).size - 1
|
1411
|
-
a = scan_indexes(l, /\S/)
|
1412
|
-
debug a.inspect
|
1413
|
-
if a.any?
|
1414
|
-
@cpos = a[0]
|
1415
|
-
else
|
1416
|
-
@cpos = 0
|
1417
|
-
end
|
1418
|
-
calculate_pos_from_cpos_lpos
|
1419
|
-
end
|
1420
|
-
end
|
1421
|
-
|
1422
|
-
def jump_to_line(line_n = 1)
|
1423
|
-
|
1424
|
-
# $method_handles_repeat = true
|
1425
|
-
# if !$next_command_count.nil? and $next_command_count > 0
|
1426
|
-
# line_n = $next_command_count
|
1427
|
-
# debug "jump to line:#{line_n}"
|
1428
|
-
# end
|
1429
|
-
debug "jump to line:#{line_n}"
|
1430
|
-
line_n = get_repeat_num() if line_n == 1
|
1431
|
-
|
1432
|
-
if line_n > @line_ends.size
|
1433
|
-
debug("lpos too large") #TODO
|
1434
|
-
return
|
1435
|
-
end
|
1436
|
-
if line_n == 1
|
1437
|
-
set_pos(0)
|
1438
|
-
else
|
1439
|
-
set_pos(@line_ends[line_n - 2] + 1)
|
1440
|
-
end
|
1441
|
-
end
|
1442
|
-
|
1443
1087
|
def join_lines()
|
1444
1088
|
if @lpos >= @line_ends.size - 1 # Cursor is on last line
|
1445
1089
|
debug("ON LAST LINE")
|
@@ -1453,28 +1097,6 @@ class Buffer < String
|
|
1453
1097
|
end
|
1454
1098
|
end
|
1455
1099
|
|
1456
|
-
def jump_to_next_instance_of_char(char, direction = FORWARD)
|
1457
|
-
|
1458
|
-
#return if at_end_of_line?
|
1459
|
-
if direction == FORWARD
|
1460
|
-
position_of_next_char = self.index(char, @pos + 1)
|
1461
|
-
if position_of_next_char != nil
|
1462
|
-
@pos = position_of_next_char
|
1463
|
-
end
|
1464
|
-
elsif direction == BACKWARD
|
1465
|
-
start_search = @pos - 250
|
1466
|
-
start_search = 0 if start_search < 0
|
1467
|
-
search_substr = self[start_search..(@pos - 1)]
|
1468
|
-
_pos = search_substr.reverse.index(char)
|
1469
|
-
if _pos != nil
|
1470
|
-
@pos -= (_pos + 1)
|
1471
|
-
end
|
1472
|
-
end
|
1473
|
-
m = method("jump_to_next_instance_of_char")
|
1474
|
-
set_last_command({ method: m, params: [char, direction] })
|
1475
|
-
$last_find_command = { char: char, direction: direction }
|
1476
|
-
set_pos(@pos)
|
1477
|
-
end
|
1478
1100
|
|
1479
1101
|
def replace_with_char(char)
|
1480
1102
|
debug "self_pos:'#{self[@pos]}'"
|
@@ -1487,6 +1109,10 @@ class Buffer < String
|
|
1487
1109
|
end
|
1488
1110
|
|
1489
1111
|
def insert_txt_at(c, pos)
|
1112
|
+
if c.nil? or pos.nil?
|
1113
|
+
error("input c=nil || pos=nil")
|
1114
|
+
return
|
1115
|
+
end
|
1490
1116
|
c = c.force_encoding("UTF-8"); #TODO:correct?
|
1491
1117
|
c = "\n" if c == "\r"
|
1492
1118
|
add_delta([pos, INSERT, c.size, c], true)
|
@@ -1596,88 +1222,6 @@ class Buffer < String
|
|
1596
1222
|
@need_redraw = false
|
1597
1223
|
end
|
1598
1224
|
|
1599
|
-
# Create a new line after current line and insert text on that line
|
1600
|
-
def put_to_new_next_line(txt)
|
1601
|
-
l = current_line_range()
|
1602
|
-
insert_txt_at(txt, l.end + 1)
|
1603
|
-
set_pos(l.end + 1)
|
1604
|
-
end
|
1605
|
-
|
1606
|
-
# Start asynchronous read of system clipboard
|
1607
|
-
def paste_start(at, register)
|
1608
|
-
@clipboard_paste_running = true
|
1609
|
-
clipboard = vma.gui.window.display.clipboard
|
1610
|
-
clipboard.read_text_async do |_clipboard, result|
|
1611
|
-
text = clipboard.read_text_finish(result)
|
1612
|
-
paste_finish(text, at, register)
|
1613
|
-
end
|
1614
|
-
end
|
1615
|
-
|
1616
|
-
def paste_finish(text, at, register)
|
1617
|
-
# if text == ""
|
1618
|
-
# return if !$clipboard.any?
|
1619
|
-
# if register == nil
|
1620
|
-
# text = $clipboard[-1]
|
1621
|
-
# else
|
1622
|
-
# text = $register[register]
|
1623
|
-
# end
|
1624
|
-
# end
|
1625
|
-
debug "PASTE: #{text}"
|
1626
|
-
$clipboard << text
|
1627
|
-
|
1628
|
-
return if text == ""
|
1629
|
-
|
1630
|
-
if $paste_lines
|
1631
|
-
debug "PASTE LINES"
|
1632
|
-
put_to_new_next_line(text)
|
1633
|
-
else
|
1634
|
-
if at_end_of_buffer? or at_end_of_line? or at == BEFORE
|
1635
|
-
pos = @pos
|
1636
|
-
else
|
1637
|
-
pos = @pos + 1
|
1638
|
-
end
|
1639
|
-
insert_txt_at(text, pos)
|
1640
|
-
set_pos(pos + text.size)
|
1641
|
-
end
|
1642
|
-
set_pos(@pos)
|
1643
|
-
@clipboard_paste_running = false
|
1644
|
-
end
|
1645
|
-
|
1646
|
-
def paste(at = AFTER, register = nil)
|
1647
|
-
# Macro's don't work with asynchronous call using GTK
|
1648
|
-
# TODO: implement as synchronous?
|
1649
|
-
# Use internal clipboard
|
1650
|
-
if vma.macro.running_macro
|
1651
|
-
text = get_clipboard()
|
1652
|
-
paste_finish(text, at, register)
|
1653
|
-
else
|
1654
|
-
# Get clipboard using GUI
|
1655
|
-
paste_start(at, register)
|
1656
|
-
end
|
1657
|
-
return true
|
1658
|
-
end
|
1659
|
-
|
1660
|
-
def delete_line()
|
1661
|
-
$method_handles_repeat = true
|
1662
|
-
num_lines = 1
|
1663
|
-
if !$next_command_count.nil? and $next_command_count > 0
|
1664
|
-
num_lines = $next_command_count
|
1665
|
-
debug "copy num_lines:#{num_lines}"
|
1666
|
-
end
|
1667
|
-
lrange = line_range(@lpos, num_lines)
|
1668
|
-
s = self[lrange]
|
1669
|
-
add_delta([lrange.begin, DELETE, lrange.end - lrange.begin + 1], true)
|
1670
|
-
set_clipboard(s)
|
1671
|
-
update_pos(lrange.begin)
|
1672
|
-
$paste_lines = true
|
1673
|
-
#recalc_line_ends
|
1674
|
-
end
|
1675
|
-
|
1676
|
-
def update_pos(pos)
|
1677
|
-
@pos = pos
|
1678
|
-
calculate_line_and_column_pos
|
1679
|
-
end
|
1680
|
-
|
1681
1225
|
def start_visual_mode()
|
1682
1226
|
@visual_mode = true
|
1683
1227
|
@selection_start = @pos
|
@@ -1686,17 +1230,17 @@ class Buffer < String
|
|
1686
1230
|
|
1687
1231
|
def copy_active_selection(x = nil)
|
1688
1232
|
debug "!COPY SELECTION"
|
1689
|
-
|
1233
|
+
@paste_lines = false
|
1690
1234
|
return if !@visual_mode
|
1691
1235
|
|
1692
1236
|
debug "COPY SELECTION"
|
1693
1237
|
s = self[get_visual_mode_range]
|
1694
1238
|
if x == :append
|
1695
1239
|
debug "APPEND"
|
1696
|
-
s += "\n" +
|
1240
|
+
s += "\n" + vma.clipboard.get()
|
1697
1241
|
end
|
1698
1242
|
|
1699
|
-
|
1243
|
+
vma.clipboard.set(s)
|
1700
1244
|
end_visual_mode
|
1701
1245
|
return true
|
1702
1246
|
end
|
@@ -1759,33 +1303,34 @@ class Buffer < String
|
|
1759
1303
|
end
|
1760
1304
|
|
1761
1305
|
def copy_line()
|
1762
|
-
|
1306
|
+
vma.kbd.method_handles_repeat = true
|
1763
1307
|
num_lines = 1
|
1764
|
-
if
|
1765
|
-
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
|
1766
1310
|
debug "copy num_lines:#{num_lines}"
|
1767
1311
|
end
|
1768
|
-
|
1769
|
-
|
1312
|
+
vma.clipboard.set(self[line_range(@lpos, num_lines)])
|
1313
|
+
@paste_lines = true
|
1770
1314
|
end
|
1771
1315
|
|
1772
1316
|
def put_file_path_to_clipboard
|
1773
|
-
|
1317
|
+
vma.clipboard.set(self.fname)
|
1774
1318
|
end
|
1775
1319
|
|
1776
1320
|
def put_file_ref_to_clipboard
|
1777
|
-
|
1321
|
+
vma.clipboard.set(self.fname + ":#{@lpos}")
|
1778
1322
|
end
|
1779
1323
|
|
1780
1324
|
def delete_active_selection() #TODO: remove this function
|
1781
1325
|
return if !@visual_mode #TODO: this should not happen
|
1782
1326
|
|
1783
1327
|
_start, _end = get_visual_mode_range
|
1784
|
-
|
1328
|
+
vma.clipboard.set(self[_start, _end])
|
1785
1329
|
end_visual_mode
|
1786
1330
|
end
|
1787
1331
|
|
1788
1332
|
def end_visual_mode()
|
1333
|
+
return if !visual_mode?
|
1789
1334
|
debug "End visual mode"
|
1790
1335
|
#TODO:take previous mode (insert|command) from stack?
|
1791
1336
|
$kbd.set_mode(:command)
|
@@ -1840,7 +1385,7 @@ class Buffer < String
|
|
1840
1385
|
savepath = ""
|
1841
1386
|
|
1842
1387
|
# If current file has fname, save to that fname
|
1843
|
-
# Else search for previously
|
1388
|
+
# Else search for previously opened files and save to the directory of
|
1844
1389
|
# the last viewed file that has a filename
|
1845
1390
|
# selffers[$buffer_history.reverse[1]].fname
|
1846
1391
|
|
@@ -1864,7 +1409,7 @@ class Buffer < String
|
|
1864
1409
|
# Keeping this code from GTK3 in case want to do this manually at some point
|
1865
1410
|
# if !confirmed
|
1866
1411
|
# @unconfirmed_path = fpath
|
1867
|
-
# if File.
|
1412
|
+
# if File.exist?(fpath) and File.file?(fpath)
|
1868
1413
|
# params = {}
|
1869
1414
|
# params["title"] = "The file already exists, overwrite? \r #{fpath}"
|
1870
1415
|
# params["inputs"] = {}
|
@@ -1873,7 +1418,7 @@ class Buffer < String
|
|
1873
1418
|
# params[:callback] = callback
|
1874
1419
|
# PopupFormGenerator.new(params).run
|
1875
1420
|
# return
|
1876
|
-
# elsif File.
|
1421
|
+
# elsif File.exist?(fpath) #and File.directory?(fpath)
|
1877
1422
|
# params = {}
|
1878
1423
|
# params["title"] = "Can't write to the destination.\r #{fpath}"
|
1879
1424
|
# params["inputs"] = {}
|
@@ -1965,44 +1510,6 @@ class Buffer < String
|
|
1965
1510
|
write_contents_to_file(@fname)
|
1966
1511
|
end
|
1967
1512
|
|
1968
|
-
# Indents whole buffer using external program
|
1969
|
-
def indent()
|
1970
|
-
file = Tempfile.new("out")
|
1971
|
-
infile = Tempfile.new("in")
|
1972
|
-
file.write(self.to_s)
|
1973
|
-
file.flush
|
1974
|
-
bufc = "FOO"
|
1975
|
-
|
1976
|
-
tmppos = @pos
|
1977
|
-
|
1978
|
-
message("Auto format #{@fname}")
|
1979
|
-
|
1980
|
-
ftype = get_file_type()
|
1981
|
-
if ["chdr", "c", "cpp", "cpphdr"].include?(ftype)
|
1982
|
-
|
1983
|
-
#C/C++/Java/JavaScript/Objective-C/Protobuf code
|
1984
|
-
system("clang-format -style='{BasedOnStyle: LLVM, ColumnLimit: 100, SortIncludes: false}' #{file.path} > #{infile.path}")
|
1985
|
-
bufc = IO.read(infile.path)
|
1986
|
-
elsif ftype == "Javascript"
|
1987
|
-
cmd = "clang-format #{file.path} > #{infile.path}'"
|
1988
|
-
debug cmd
|
1989
|
-
system(cmd)
|
1990
|
-
bufc = IO.read(infile.path)
|
1991
|
-
elsif ftype == "ruby"
|
1992
|
-
cmd = "rufo #{file.path}"
|
1993
|
-
debug cmd
|
1994
|
-
system(cmd)
|
1995
|
-
bufc = IO.read(file.path)
|
1996
|
-
else
|
1997
|
-
message("No auto-format handler for file of type: #{ftype}")
|
1998
|
-
return
|
1999
|
-
end
|
2000
|
-
self.update_content(bufc)
|
2001
|
-
center_on_current_line #TODO: needed?
|
2002
|
-
file.close; file.unlink
|
2003
|
-
infile.close; infile.unlink
|
2004
|
-
end
|
2005
|
-
|
2006
1513
|
def close()
|
2007
1514
|
idx = vma.buffers.get_buffer_by_id(@id)
|
2008
1515
|
vma.buffers.close_buffer(idx)
|
@@ -2025,7 +1532,7 @@ class Buffer < String
|
|
2025
1532
|
end
|
2026
1533
|
end
|
2027
1534
|
|
2028
|
-
#TODO
|
1535
|
+
#TODO: function not used
|
2029
1536
|
def write_to_file(savepath, s)
|
2030
1537
|
if is_path_writable(savepath)
|
2031
1538
|
IO.write(savepath, self.to_s)
|