vimamsa 0.1.9 → 0.1.11
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/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
|