vimamsa 0.1.9 → 0.1.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +29 -7
- data/custom_example.rb +12 -2
- data/demo.txt +2 -2
- data/exe/vimamsa +1 -1
- data/lib/vimamsa/ack.rb +57 -46
- data/lib/vimamsa/actions.rb +1 -1
- data/lib/vimamsa/buffer.rb +287 -55
- data/lib/vimamsa/buffer_list.rb +83 -48
- data/lib/vimamsa/buffer_manager.rb +19 -3
- data/lib/vimamsa/conf.rb +10 -1
- data/lib/vimamsa/debug.rb +15 -11
- data/lib/vimamsa/easy_jump.rb +9 -5
- data/lib/vimamsa/editor.rb +73 -54
- data/lib/vimamsa/encrypt.rb +2 -2
- data/lib/vimamsa/file_finder.rb +70 -72
- data/lib/vimamsa/file_history.rb +2 -3
- data/lib/vimamsa/file_manager.rb +10 -8
- data/lib/vimamsa/form_generator.rb +122 -0
- data/lib/vimamsa/gui.rb +469 -118
- data/lib/vimamsa/gui_image.rb +12 -6
- data/lib/vimamsa/gui_menu.rb +26 -21
- data/lib/vimamsa/gui_select_window.rb +40 -21
- data/lib/vimamsa/gui_sourceview.rb +173 -79
- data/lib/vimamsa/hyper_plain_text.rb +36 -3
- data/lib/vimamsa/key_actions.rb +13 -1
- data/lib/vimamsa/key_binding_tree.rb +32 -20
- data/lib/vimamsa/key_bindings_vimlike.rb +54 -25
- data/lib/vimamsa/langservp.rb +172 -0
- data/lib/vimamsa/macro.rb +9 -8
- data/lib/vimamsa/main.rb +3 -4
- data/lib/vimamsa/rbvma.rb +7 -4
- data/lib/vimamsa/search.rb +3 -2
- data/lib/vimamsa/search_replace.rb +50 -120
- data/lib/vimamsa/text_transforms.rb +1 -1
- data/lib/vimamsa/util.rb +47 -1
- data/lib/vimamsa/version.rb +1 -1
- data/lib/vimamsa.rb +1 -6
- data/styles/molokai_edit.xml +3 -0
- data/vimamsa.gemspec +10 -10
- metadata +22 -20
data/lib/vimamsa/buffer.rb
CHANGED
@@ -6,7 +6,7 @@ require "openssl"
|
|
6
6
|
require "ripl/multi_line"
|
7
7
|
|
8
8
|
$paste_lines = false
|
9
|
-
$buffer_history = [
|
9
|
+
$buffer_history = []
|
10
10
|
|
11
11
|
$update_highlight = false
|
12
12
|
|
@@ -14,27 +14,29 @@ $ifuncon = false
|
|
14
14
|
|
15
15
|
class Buffer < String
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
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
|
17
|
+
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
|
20
18
|
attr_writer :call_func, :update_highlight
|
21
19
|
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
|
22
20
|
|
23
21
|
@@num_buffers = 0
|
24
22
|
|
25
|
-
def initialize(str = "\n", fname = nil)
|
23
|
+
def initialize(str = "\n", fname = nil, prefix = "buf")
|
26
24
|
debug "Buffer.rb: def initialize"
|
27
25
|
super(str)
|
28
26
|
|
29
27
|
@images = []
|
28
|
+
@audiofiles = []
|
30
29
|
@lang = nil
|
31
30
|
@id = @@num_buffers
|
32
31
|
@@num_buffers += 1
|
32
|
+
@version = 0
|
33
33
|
gui_create_buffer(@id, self)
|
34
34
|
debug "NEW BUFFER fn=#{fname} ID:#{@id}"
|
35
35
|
|
36
36
|
@module = nil
|
37
37
|
|
38
|
+
@last_save = @last_asked_from_user = @file_last_cheked = Time.now
|
39
|
+
|
38
40
|
@crypt = nil
|
39
41
|
@update_highlight = true
|
40
42
|
@syntax_detect_failed = false
|
@@ -51,19 +53,18 @@ class Buffer < String
|
|
51
53
|
@line_action_handler = nil
|
52
54
|
|
53
55
|
@dirname = nil
|
54
|
-
@title = "
|
56
|
+
@title = "*#{prefix}-#{@id}*"
|
55
57
|
@subtitle = ""
|
56
58
|
|
57
59
|
if @fname
|
58
60
|
@title = File.basename(@fname)
|
59
61
|
@dirname = File.dirname(@fname)
|
60
62
|
userhome = File.expand_path("~")
|
61
|
-
@subtitle = @dirname.gsub(/^#{userhome}/, "~")
|
63
|
+
# @subtitle = @dirname.gsub(/^#{userhome}/, "~")
|
64
|
+
@subtitle = @fname.gsub(/^#{userhome}/, "~")
|
62
65
|
end
|
63
66
|
|
64
67
|
t1 = Time.now
|
65
|
-
gui_set_current_buffer(@id)
|
66
|
-
gui_set_window_title(@title, @subtitle)
|
67
68
|
|
68
69
|
set_content(str)
|
69
70
|
debug "init time:#{Time.now - t1}"
|
@@ -72,6 +73,10 @@ class Buffer < String
|
|
72
73
|
self << "\n" if self[-1] != "\n"
|
73
74
|
@current_word = nil
|
74
75
|
@active_kbd_mode = nil
|
76
|
+
if conf(:enable_lsp)
|
77
|
+
init_lsp
|
78
|
+
end
|
79
|
+
return self
|
75
80
|
end
|
76
81
|
|
77
82
|
def list_str()
|
@@ -99,6 +104,36 @@ class Buffer < String
|
|
99
104
|
end
|
100
105
|
end
|
101
106
|
|
107
|
+
def lsp_get_def()
|
108
|
+
if !@lsp.nil?
|
109
|
+
fpuri = URI.join("file:///", @fname).to_s
|
110
|
+
@lsp.get_definition(fpuri, @lpos, @cpos)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def lsp_jump_to_def()
|
115
|
+
if !@lsp.nil?
|
116
|
+
fpuri = URI.join("file:///", @fname).to_s
|
117
|
+
r = @lsp.get_definition(fpuri, @lpos, @cpos)
|
118
|
+
if !r.nil?
|
119
|
+
jump_to_file(r[0], r[1])
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def init_lsp()
|
125
|
+
if conf(:enable_lsp) and !@lang.nil?
|
126
|
+
@lsp = LangSrv.get(@lang.to_sym)
|
127
|
+
if @lang == "php"
|
128
|
+
# Ripl.start :binding => binding
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
if !@lsp.nil?
|
133
|
+
@lsp.open_file(@fname, self.to_s)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
102
137
|
def detect_file_language
|
103
138
|
@lang = nil
|
104
139
|
@lang = "c" if @fname.match(/\.(c|h|cpp)$/)
|
@@ -106,6 +141,7 @@ class Buffer < String
|
|
106
141
|
@lang = "ruby" if @fname.match(/\.(rb)$/)
|
107
142
|
@lang = "hyperplaintext" if @fname.match(/\.(txt)$/)
|
108
143
|
@lang = "php" if @fname.match(/\.(php)$/)
|
144
|
+
@lsp = nil
|
109
145
|
|
110
146
|
lm = GtkSource::LanguageManager.new
|
111
147
|
|
@@ -119,10 +155,12 @@ class Buffer < String
|
|
119
155
|
debug "Guessed LANG: #{lang.id}"
|
120
156
|
@lang = lang.id
|
121
157
|
end
|
158
|
+
puts @lang.inspect
|
122
159
|
|
123
160
|
if @lang
|
124
161
|
gui_set_file_lang(@id, @lang)
|
125
162
|
end
|
163
|
+
return @lang
|
126
164
|
end
|
127
165
|
|
128
166
|
def view()
|
@@ -130,6 +168,61 @@ class Buffer < String
|
|
130
168
|
return vma.gui.buffers[@id]
|
131
169
|
end
|
132
170
|
|
171
|
+
# Replace char at pos with audio widget for
|
172
|
+
def add_audio(afpath, pos)
|
173
|
+
return if !is_legal_pos(pos)
|
174
|
+
afpath = File.expand_path(afpath)
|
175
|
+
return if !File.exist?(afpath)
|
176
|
+
|
177
|
+
vbuf = view.buffer
|
178
|
+
itr = vbuf.get_iter_at(:offset => pos)
|
179
|
+
itr2 = vbuf.get_iter_at(:offset => pos + 1)
|
180
|
+
vbuf.delete(itr, itr2)
|
181
|
+
anchor = vbuf.create_child_anchor(itr)
|
182
|
+
|
183
|
+
mf = Gtk::MediaFile.new(afpath)
|
184
|
+
mc = Gtk::MediaControls.new(mf)
|
185
|
+
# mc = Gtk::MediaControls.new(Gtk::MediaFile.new)
|
186
|
+
# Thread.new{mf.play;sleep 0.01; mf.pause}
|
187
|
+
@audiofiles << mc
|
188
|
+
|
189
|
+
view.add_child_at_anchor(mc, anchor)
|
190
|
+
mc.set_size_request(500, 20)
|
191
|
+
mc.set_margin_start(view.gutter_width + 10)
|
192
|
+
|
193
|
+
provider = Gtk::CssProvider.new
|
194
|
+
mc.add_css_class("medctr")
|
195
|
+
|
196
|
+
provider.load(data: ".medctr { background-color:#353535; }")
|
197
|
+
mc.style_context.add_provider(provider)
|
198
|
+
|
199
|
+
pp mf.set_prepared(true)
|
200
|
+
# pp mf.pause
|
201
|
+
pp mf.duration
|
202
|
+
pp mf.has_audio?
|
203
|
+
|
204
|
+
# >> Gtk::MediaControls.signals
|
205
|
+
# => ["direction-changed", "destroy", "show", "hide", "map", "unmap", "realize", "unrealize", "state-flags-changed", "mnemonic-activate", "move-focus", "keynav-failed", "query-tooltip", "notify"]
|
206
|
+
|
207
|
+
# If this is done too early, the gutter is not yet drawn which
|
208
|
+
# will result in wrong position
|
209
|
+
if @audiofiles.size == 1
|
210
|
+
Thread.new {
|
211
|
+
GLib::Idle.add(proc { self.reset_audio_widget_positions })
|
212
|
+
}
|
213
|
+
end
|
214
|
+
$audiof = mf
|
215
|
+
end
|
216
|
+
|
217
|
+
def reset_audio_widget_positions
|
218
|
+
debug "reset_audio_widget_positions", 2
|
219
|
+
for mc in @audiofiles
|
220
|
+
mc.set_size_request(500, 20)
|
221
|
+
mc.set_margin_start(view.gutter_width + 10)
|
222
|
+
end
|
223
|
+
return false
|
224
|
+
end
|
225
|
+
|
133
226
|
def add_image(imgpath, pos)
|
134
227
|
return if !is_legal_pos(pos)
|
135
228
|
|
@@ -141,16 +234,17 @@ class Buffer < String
|
|
141
234
|
|
142
235
|
da = ResizableImage.new(imgpath, view)
|
143
236
|
view.add_child_at_anchor(da, anchor)
|
144
|
-
|
237
|
+
|
238
|
+
da.set_draw_func do |widget, cr|
|
145
239
|
da.do_draw(widget, cr)
|
146
240
|
end
|
147
241
|
|
148
242
|
da.scale_image
|
149
243
|
|
150
|
-
vma.gui.handle_image_resize
|
244
|
+
# vma.gui.handle_image_resize #TODO:gtk4
|
151
245
|
@images << { :path => imgpath, :obj => da }
|
152
246
|
|
153
|
-
gui_set_current_buffer(@id)
|
247
|
+
gui_set_current_buffer(@id) #TODO: needed?
|
154
248
|
end
|
155
249
|
|
156
250
|
def is_legal_pos(pos, op = :read)
|
@@ -307,6 +401,7 @@ class Buffer < String
|
|
307
401
|
gui_set_buffer_contents(@id, self.to_s)
|
308
402
|
@images = [] #TODO: if reload
|
309
403
|
hpt_scan_images(self)
|
404
|
+
hpt_scan_audio(self)
|
310
405
|
|
311
406
|
# add_hl_update(@update_hl_startpos, @update_hl_endpos)
|
312
407
|
end
|
@@ -320,6 +415,7 @@ class Buffer < String
|
|
320
415
|
@dirname = File.dirname(@fname)
|
321
416
|
userhome = File.expand_path("~")
|
322
417
|
@subtitle = @dirname.gsub(/^#{userhome}/, "~")
|
418
|
+
vma.buffers.last_dir = @dirname
|
323
419
|
|
324
420
|
detect_file_language
|
325
421
|
end
|
@@ -401,9 +497,23 @@ class Buffer < String
|
|
401
497
|
def run_delta(delta, auto_update_cpos = false)
|
402
498
|
# auto_update_cpos: In some cases position of cursor should be updated automatically based on change to buffer (delta). In other cases this is handled by the action that creates the delta.
|
403
499
|
|
500
|
+
# delta[0]: char position
|
501
|
+
# delta[1]: INSERT or DELETE
|
502
|
+
# delta[2]: number of chars affected
|
503
|
+
# delta[3]: text to add in case of insert
|
504
|
+
|
505
|
+
@version += 1
|
404
506
|
if $experimental
|
405
507
|
@bt.handle_delta(Delta.new(delta[0], delta[1], delta[2], delta[3]))
|
406
508
|
end
|
509
|
+
|
510
|
+
if !@lsp.nil?
|
511
|
+
dc = delta.clone
|
512
|
+
dc[3] = "" if dc[3].nil?
|
513
|
+
dc[4] = get_line_and_col_pos(delta[0])
|
514
|
+
dc[5] = get_line_and_col_pos(delta[0] + delta[2])
|
515
|
+
@lsp.handle_delta(dc, @fname, @version)
|
516
|
+
end
|
407
517
|
pos = delta[0]
|
408
518
|
if @edit_pos_history.any? and (@edit_pos_history.last - pos).abs <= 2
|
409
519
|
@edit_pos_history.pop
|
@@ -440,7 +550,7 @@ class Buffer < String
|
|
440
550
|
@update_hl_endpos = pos + delta[2]
|
441
551
|
add_hl_update(@update_hl_startpos, @update_hl_endpos)
|
442
552
|
end
|
443
|
-
debug
|
553
|
+
debug("DELTA=#{delta.inspect}", 2)
|
444
554
|
# sanity_check_line_ends #TODO: enable with debug mode
|
445
555
|
#highlight_c()
|
446
556
|
|
@@ -574,8 +684,7 @@ class Buffer < String
|
|
574
684
|
|
575
685
|
def comment_linerange(r)
|
576
686
|
com_str = get_com_str()
|
577
|
-
|
578
|
-
lines = $buffer[r].lines
|
687
|
+
lines = self[r].lines
|
579
688
|
mod = ""
|
580
689
|
lines.each { |line|
|
581
690
|
m = line.match(/^(\s*)(\S.*)/)
|
@@ -637,14 +746,14 @@ class Buffer < String
|
|
637
746
|
elsif op == :uncomment
|
638
747
|
uncomment_linerange(first..last)
|
639
748
|
end
|
640
|
-
|
749
|
+
self.end_visual_mode
|
641
750
|
end
|
642
751
|
end
|
643
752
|
|
644
753
|
def uncomment_linerange(r)
|
645
754
|
com_str = get_com_str()
|
646
|
-
#r
|
647
|
-
lines =
|
755
|
+
#r=self.line_range(self.lpos, 2)
|
756
|
+
lines = self[r].split(/(\n)/).each_slice(2).map { |x| x[0] }
|
648
757
|
mod = lines.collect { |x| x.sub(/^(\s*)(#{com_str}\s?)/, '\1') + "\n" }.join()
|
649
758
|
replace_range(r, mod)
|
650
759
|
end
|
@@ -804,6 +913,8 @@ class Buffer < String
|
|
804
913
|
end
|
805
914
|
gui_set_cursor_pos(@id, @pos)
|
806
915
|
calculate_line_and_column_pos
|
916
|
+
|
917
|
+
check_if_modified_outside
|
807
918
|
end
|
808
919
|
|
809
920
|
# Get the line number of character position
|
@@ -871,12 +982,12 @@ class Buffer < String
|
|
871
982
|
set_pos(pos)
|
872
983
|
end
|
873
984
|
|
874
|
-
def delete(op)
|
985
|
+
def delete(op, x = nil)
|
875
986
|
$paste_lines = false
|
876
987
|
# Delete selection
|
877
988
|
if op == SELECTION && visual_mode?
|
878
989
|
(startpos, endpos) = get_visual_mode_range2
|
879
|
-
delete_range(startpos, endpos)
|
990
|
+
delete_range(startpos, endpos, x)
|
880
991
|
@pos = [@pos, @selection_start].min
|
881
992
|
end_visual_mode
|
882
993
|
#return
|
@@ -904,21 +1015,39 @@ class Buffer < String
|
|
904
1015
|
#need_redraw!
|
905
1016
|
end
|
906
1017
|
|
907
|
-
def delete_range(startpos, endpos)
|
908
|
-
|
909
|
-
|
1018
|
+
def delete_range(startpos, endpos, x = nil)
|
1019
|
+
s = self[startpos..endpos]
|
1020
|
+
if startpos == endpos or s == ""
|
1021
|
+
return
|
1022
|
+
end
|
1023
|
+
if x == :append
|
1024
|
+
debug "APPEND"
|
1025
|
+
s += "\n" + get_clipboard()
|
1026
|
+
end
|
1027
|
+
set_clipboard(s)
|
910
1028
|
add_delta([startpos, DELETE, (endpos - startpos + 1)], true)
|
911
1029
|
#recalc_line_ends
|
912
1030
|
calculate_line_and_column_pos
|
913
1031
|
end
|
914
1032
|
|
1033
|
+
# Ranges to use in delete or copy operations
|
915
1034
|
def get_range(range_id)
|
916
1035
|
range = nil
|
917
1036
|
if range_id == :to_word_end
|
1037
|
+
# TODO: better way to make the search than + 150 from current position
|
918
1038
|
wmarks = get_word_end_marks(@pos, @pos + 150)
|
919
1039
|
if wmarks.any?
|
920
1040
|
range = @pos..wmarks[0]
|
921
1041
|
end
|
1042
|
+
elsif range_id == :to_next_word # start of
|
1043
|
+
wmarks = get_word_start_marks(@pos, @pos + 150)
|
1044
|
+
if !wmarks[0].nil?
|
1045
|
+
range = @pos..(wmarks[0] - 1)
|
1046
|
+
debug range, 2
|
1047
|
+
else
|
1048
|
+
range = get_range(:to_word_end)
|
1049
|
+
end
|
1050
|
+
# Ripl.start :binding => binding
|
922
1051
|
elsif range_id == :to_line_end
|
923
1052
|
debug "TO LINE END"
|
924
1053
|
range = @pos..(@line_ends[@lpos] - 1)
|
@@ -1150,7 +1279,8 @@ class Buffer < String
|
|
1150
1279
|
wtype = :url
|
1151
1280
|
elsif is_existing_file(path)
|
1152
1281
|
message("PATH:'#{word}'")
|
1153
|
-
if vma.can_open_extension?(path)
|
1282
|
+
# if vma.can_open_extension?(path)
|
1283
|
+
if file_is_text_file(path)
|
1154
1284
|
wtype = :textfile
|
1155
1285
|
else
|
1156
1286
|
wtype = :file
|
@@ -1356,7 +1486,7 @@ class Buffer < String
|
|
1356
1486
|
d2 = [@pos, INSERT, 1, char]
|
1357
1487
|
add_delta(d1, true)
|
1358
1488
|
add_delta(d2, true)
|
1359
|
-
debug "DELTAS:#{
|
1489
|
+
debug "DELTAS:#{self.deltas.inspect} "
|
1360
1490
|
end
|
1361
1491
|
|
1362
1492
|
def insert_txt_at(c, pos)
|
@@ -1366,6 +1496,12 @@ class Buffer < String
|
|
1366
1496
|
calculate_line_and_column_pos
|
1367
1497
|
end
|
1368
1498
|
|
1499
|
+
def append(c)
|
1500
|
+
pos = self.size - 1
|
1501
|
+
add_delta([pos, INSERT, c.size, c], true)
|
1502
|
+
calculate_line_and_column_pos
|
1503
|
+
end
|
1504
|
+
|
1369
1505
|
def execute_current_line_in_terminal(autoclose = false)
|
1370
1506
|
s = get_current_line
|
1371
1507
|
exec_in_terminal(s, autoclose)
|
@@ -1449,7 +1585,6 @@ class Buffer < String
|
|
1449
1585
|
for d in deltas
|
1450
1586
|
add_delta(d, true, true)
|
1451
1587
|
end
|
1452
|
-
# $buffer.update_content(IO.read('test.txt'))
|
1453
1588
|
end
|
1454
1589
|
|
1455
1590
|
def need_redraw!
|
@@ -1471,22 +1606,27 @@ class Buffer < String
|
|
1471
1606
|
set_pos(l.end + 1)
|
1472
1607
|
end
|
1473
1608
|
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1609
|
+
# Start asynchronous read of system clipboard
|
1610
|
+
def paste_start(at, register)
|
1611
|
+
@clipboard_paste_running = true
|
1612
|
+
clipboard = vma.gui.window.display.clipboard
|
1613
|
+
clipboard.read_text_async do |_clipboard, result|
|
1614
|
+
text = clipboard.read_text_finish(result)
|
1615
|
+
paste_finish(text, at, register)
|
1479
1616
|
end
|
1617
|
+
end
|
1480
1618
|
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
end
|
1619
|
+
def paste_finish(text, at, register)
|
1620
|
+
# if text == ""
|
1621
|
+
# return if !$clipboard.any?
|
1622
|
+
# if register == nil
|
1623
|
+
# text = $clipboard[-1]
|
1624
|
+
# else
|
1625
|
+
# text = $register[register]
|
1626
|
+
# end
|
1627
|
+
# end
|
1489
1628
|
debug "PASTE: #{text}"
|
1629
|
+
$clipboard << text
|
1490
1630
|
|
1491
1631
|
return if text == ""
|
1492
1632
|
|
@@ -1503,9 +1643,21 @@ class Buffer < String
|
|
1503
1643
|
set_pos(pos + text.size)
|
1504
1644
|
end
|
1505
1645
|
set_pos(@pos)
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1646
|
+
@clipboard_paste_running = false
|
1647
|
+
end
|
1648
|
+
|
1649
|
+
def paste(at = AFTER, register = nil)
|
1650
|
+
# Macro's don't work with asynchronous call using GTK
|
1651
|
+
# TODO: implement as synchronous?
|
1652
|
+
# Use internal clipboard
|
1653
|
+
if vma.macro.running_macro
|
1654
|
+
text = get_clipboard()
|
1655
|
+
paste_finish(text, at, register)
|
1656
|
+
else
|
1657
|
+
# Get clipboard using GUI
|
1658
|
+
paste_start(at, register)
|
1659
|
+
end
|
1660
|
+
return true
|
1509
1661
|
end
|
1510
1662
|
|
1511
1663
|
def delete_line()
|
@@ -1624,6 +1776,10 @@ class Buffer < String
|
|
1624
1776
|
set_clipboard(self.fname)
|
1625
1777
|
end
|
1626
1778
|
|
1779
|
+
def put_file_ref_to_clipboard
|
1780
|
+
set_clipboard(self.fname + ":#{@lpos}")
|
1781
|
+
end
|
1782
|
+
|
1627
1783
|
def delete_active_selection() #TODO: remove this function
|
1628
1784
|
return if !@visual_mode #TODO: this should not happen
|
1629
1785
|
|
@@ -1642,6 +1798,10 @@ class Buffer < String
|
|
1642
1798
|
|
1643
1799
|
def get_visual_mode_range2()
|
1644
1800
|
r = get_visual_mode_range
|
1801
|
+
if r.begin > r.end
|
1802
|
+
debug "r.begin > r.end"
|
1803
|
+
Ripl.start :binding => binding
|
1804
|
+
end
|
1645
1805
|
return [r.begin, r.end]
|
1646
1806
|
end
|
1647
1807
|
|
@@ -1660,9 +1820,9 @@ class Buffer < String
|
|
1660
1820
|
_end = @pos
|
1661
1821
|
|
1662
1822
|
_start, _end = _end, _start if _start > _end
|
1663
|
-
_end = _end + 1 if _start < _end
|
1664
|
-
|
1665
|
-
return _start..(_end
|
1823
|
+
# _end = _end + 1 if _start < _end #TODO:verify if correct
|
1824
|
+
# return _start..(_end - 1)
|
1825
|
+
return _start..(_end)
|
1666
1826
|
end
|
1667
1827
|
|
1668
1828
|
def selection_start()
|
@@ -1685,7 +1845,7 @@ class Buffer < String
|
|
1685
1845
|
# If current file has fname, save to that fname
|
1686
1846
|
# Else search for previously open files and save to the directory of
|
1687
1847
|
# the last viewed file that has a filename
|
1688
|
-
#
|
1848
|
+
# selffers[$buffer_history.reverse[1]].fname
|
1689
1849
|
|
1690
1850
|
if @fname
|
1691
1851
|
savepath = File.dirname(@fname)
|
@@ -1696,7 +1856,36 @@ class Buffer < String
|
|
1696
1856
|
# calls back to file_saveas
|
1697
1857
|
end
|
1698
1858
|
|
1699
|
-
def
|
1859
|
+
def save_as_check_callback(vals)
|
1860
|
+
if vals["yes_btn"] == "submit"
|
1861
|
+
save_as_callback(@unconfirmed_path, true)
|
1862
|
+
end
|
1863
|
+
end
|
1864
|
+
|
1865
|
+
def save_as_callback(fpath, confirmed = false)
|
1866
|
+
# The check if file exists is handled by Gtk::FileChooserDialog in GTK4
|
1867
|
+
# Keeping this code from GTK3 in case want to do this manually at some point
|
1868
|
+
# if !confirmed
|
1869
|
+
# @unconfirmed_path = fpath
|
1870
|
+
# if File.exists?(fpath) and File.file?(fpath)
|
1871
|
+
# params = {}
|
1872
|
+
# params["title"] = "The file already exists, overwrite? \r #{fpath}"
|
1873
|
+
# params["inputs"] = {}
|
1874
|
+
# params["inputs"]["yes_btn"] = { :label => "Yes", :type => :button, :default_focus => true }
|
1875
|
+
# callback = proc { |x| save_as_check_callback(x) }
|
1876
|
+
# params[:callback] = callback
|
1877
|
+
# PopupFormGenerator.new(params).run
|
1878
|
+
# return
|
1879
|
+
# elsif File.exists?(fpath) #and File.directory?(fpath)
|
1880
|
+
# params = {}
|
1881
|
+
# params["title"] = "Can't write to the destination.\r #{fpath}"
|
1882
|
+
# params["inputs"] = {}
|
1883
|
+
# params["inputs"]["ok_btn"] = { :label => "Ok", :type => :button, :default_focus => true }
|
1884
|
+
# PopupFormGenerator.new(params).run
|
1885
|
+
# return
|
1886
|
+
# end
|
1887
|
+
# end
|
1888
|
+
|
1700
1889
|
set_filename(fpath)
|
1701
1890
|
save()
|
1702
1891
|
gui_set_window_title(@title, @subtitle) #TODO: if not active buffer?
|
@@ -1730,11 +1919,47 @@ class Buffer < String
|
|
1730
1919
|
message("File #{fpath} not writeable")
|
1731
1920
|
#TODO: show message box
|
1732
1921
|
end
|
1922
|
+
@last_save = Time.now
|
1923
|
+
puts "file saved on #{@last_save}"
|
1733
1924
|
sleep 3
|
1734
1925
|
}
|
1735
1926
|
end
|
1736
1927
|
|
1928
|
+
def check_if_modified_outside_callback(x)
|
1929
|
+
debug "check_if_modified_outside_callback"
|
1930
|
+
if x["yes_btn"] == "submit"
|
1931
|
+
revert()
|
1932
|
+
end
|
1933
|
+
end
|
1934
|
+
|
1935
|
+
def check_if_modified_outside
|
1936
|
+
# Don't check if less than 8 seconds since last checked
|
1937
|
+
return false if @fname.nil?
|
1938
|
+
return false if Time.now - 8 < @file_last_cheked
|
1939
|
+
@file_last_cheked = Time.now
|
1940
|
+
return false if !File.exist?(@fname)
|
1941
|
+
|
1942
|
+
file_stat = File.stat(@fname)
|
1943
|
+
modification_time = file_stat.mtime
|
1944
|
+
|
1945
|
+
if modification_time > @last_save and @last_asked_from_user < modification_time
|
1946
|
+
@last_asked_from_user = Time.now
|
1947
|
+
debug "File modified outside this program."
|
1948
|
+
params = {}
|
1949
|
+
params["title"] = "The file has been modified outside this program. Reload from disk? \r #{@fname}"
|
1950
|
+
params["inputs"] = {}
|
1951
|
+
params["inputs"]["yes_btn"] = { :label => "Yes", :type => :button, :default_focus => true }
|
1952
|
+
callback = proc { |x| check_if_modified_outside_callback(x) }
|
1953
|
+
params[:callback] = callback
|
1954
|
+
PopupFormGenerator.new(params).run
|
1955
|
+
return true
|
1956
|
+
end
|
1957
|
+
|
1958
|
+
return false
|
1959
|
+
end
|
1960
|
+
|
1737
1961
|
def save()
|
1962
|
+
check_if_modified_outside
|
1738
1963
|
if !@fname
|
1739
1964
|
save_as()
|
1740
1965
|
return
|
@@ -1747,7 +1972,7 @@ class Buffer < String
|
|
1747
1972
|
def indent()
|
1748
1973
|
file = Tempfile.new("out")
|
1749
1974
|
infile = Tempfile.new("in")
|
1750
|
-
file.write(
|
1975
|
+
file.write(self.to_s)
|
1751
1976
|
file.flush
|
1752
1977
|
bufc = "FOO"
|
1753
1978
|
|
@@ -1755,30 +1980,37 @@ class Buffer < String
|
|
1755
1980
|
|
1756
1981
|
message("Auto format #{@fname}")
|
1757
1982
|
|
1758
|
-
|
1983
|
+
ftype = get_file_type()
|
1984
|
+
if ["chdr", "c", "cpp", "cpphdr"].include?(ftype)
|
1759
1985
|
|
1760
1986
|
#C/C++/Java/JavaScript/Objective-C/Protobuf code
|
1761
1987
|
system("clang-format -style='{BasedOnStyle: LLVM, ColumnLimit: 100, SortIncludes: false}' #{file.path} > #{infile.path}")
|
1762
1988
|
bufc = IO.read(infile.path)
|
1763
|
-
elsif
|
1989
|
+
elsif ftype == "Javascript"
|
1764
1990
|
cmd = "clang-format #{file.path} > #{infile.path}'"
|
1765
1991
|
debug cmd
|
1766
1992
|
system(cmd)
|
1767
1993
|
bufc = IO.read(infile.path)
|
1768
|
-
elsif
|
1994
|
+
elsif ftype == "ruby"
|
1769
1995
|
cmd = "rufo #{file.path}"
|
1770
1996
|
debug cmd
|
1771
1997
|
system(cmd)
|
1772
1998
|
bufc = IO.read(file.path)
|
1773
1999
|
else
|
2000
|
+
message("No auto-format handler for file of type: #{ftype}")
|
1774
2001
|
return
|
1775
2002
|
end
|
1776
|
-
|
2003
|
+
self.update_content(bufc)
|
1777
2004
|
center_on_current_line #TODO: needed?
|
1778
2005
|
file.close; file.unlink
|
1779
2006
|
infile.close; infile.unlink
|
1780
2007
|
end
|
1781
2008
|
|
2009
|
+
def close()
|
2010
|
+
idx = vma.buffers.get_buffer_by_id(@id)
|
2011
|
+
vma.buffers.close_buffer(idx)
|
2012
|
+
end
|
2013
|
+
|
1782
2014
|
def backup()
|
1783
2015
|
fname = @fname
|
1784
2016
|
return if !@fname
|
@@ -1799,7 +2031,7 @@ end
|
|
1799
2031
|
#TODO
|
1800
2032
|
def write_to_file(savepath, s)
|
1801
2033
|
if is_path_writable(savepath)
|
1802
|
-
IO.write(savepath,
|
2034
|
+
IO.write(savepath, self.to_s)
|
1803
2035
|
else
|
1804
2036
|
message("PATH NOT WRITABLE: #{savepath}")
|
1805
2037
|
end
|
@@ -1814,8 +2046,8 @@ def is_path_writable(fpath)
|
|
1814
2046
|
end
|
1815
2047
|
|
1816
2048
|
def backup_all_buffers()
|
1817
|
-
for
|
1818
|
-
|
2049
|
+
for b in bufs
|
2050
|
+
b.backup
|
1819
2051
|
end
|
1820
2052
|
message("Backup all buffers")
|
1821
2053
|
end
|