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
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)
|