vimamsa 0.1.10 → 0.1.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +20 -3
- data/custom_example.rb +11 -1
- data/demo.txt +2 -2
- data/exe/vimamsa +1 -4
- data/lib/vimamsa/ack.rb +57 -9
- data/lib/vimamsa/actions.rb +1 -1
- data/lib/vimamsa/buffer.rb +270 -45
- data/lib/vimamsa/buffer_list.rb +57 -16
- data/lib/vimamsa/buffer_manager.rb +21 -4
- data/lib/vimamsa/conf.rb +10 -1
- data/lib/vimamsa/debug.rb +7 -3
- data/lib/vimamsa/easy_jump.rb +10 -6
- data/lib/vimamsa/editor.rb +57 -43
- data/lib/vimamsa/file_finder.rb +69 -71
- data/lib/vimamsa/file_history.rb +2 -3
- data/lib/vimamsa/file_manager.rb +1 -1
- data/lib/vimamsa/form_generator.rb +122 -0
- data/lib/vimamsa/gui.rb +518 -180
- data/lib/vimamsa/gui_image.rb +12 -6
- data/lib/vimamsa/gui_menu.rb +29 -20
- data/lib/vimamsa/gui_select_window.rb +40 -21
- data/lib/vimamsa/gui_sourceview.rb +264 -86
- data/lib/vimamsa/hyper_plain_text.rb +34 -1
- data/lib/vimamsa/key_actions.rb +13 -1
- data/lib/vimamsa/key_binding_tree.rb +26 -14
- data/lib/vimamsa/key_bindings_vimlike.rb +56 -26
- data/lib/vimamsa/langservp.rb +172 -0
- data/lib/vimamsa/macro.rb +9 -8
- data/lib/vimamsa/main.rb +0 -1
- data/lib/vimamsa/rbvma.rb +7 -4
- data/lib/vimamsa/search.rb +2 -1
- data/lib/vimamsa/search_replace.rb +36 -106
- data/lib/vimamsa/util.rb +55 -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 +24 -22
data/lib/vimamsa/buffer.rb
CHANGED
@@ -6,35 +6,36 @@ 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
|
|
13
13
|
$ifuncon = false
|
14
14
|
|
15
15
|
class Buffer < String
|
16
|
-
|
17
|
-
#attr_reader (:pos, :cpos, :lpos)
|
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
|
16
|
+
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
17
|
attr_writer :call_func, :update_highlight
|
21
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
|
22
19
|
|
23
20
|
@@num_buffers = 0
|
24
21
|
|
25
|
-
def initialize(str = "\n", fname = nil)
|
22
|
+
def initialize(str = "\n", fname = nil, prefix = "buf")
|
26
23
|
debug "Buffer.rb: def initialize"
|
27
24
|
super(str)
|
28
25
|
|
29
26
|
@images = []
|
27
|
+
@audiofiles = []
|
30
28
|
@lang = nil
|
31
29
|
@id = @@num_buffers
|
32
30
|
@@num_buffers += 1
|
31
|
+
@version = 0
|
33
32
|
gui_create_buffer(@id, self)
|
34
33
|
debug "NEW BUFFER fn=#{fname} ID:#{@id}"
|
35
34
|
|
36
35
|
@module = nil
|
37
36
|
|
37
|
+
@last_save = @last_asked_from_user = @file_last_cheked = Time.now
|
38
|
+
|
38
39
|
@crypt = nil
|
39
40
|
@update_highlight = true
|
40
41
|
@syntax_detect_failed = false
|
@@ -51,19 +52,18 @@ class Buffer < String
|
|
51
52
|
@line_action_handler = nil
|
52
53
|
|
53
54
|
@dirname = nil
|
54
|
-
@title = "
|
55
|
+
@title = "*#{prefix}-#{@id}*"
|
55
56
|
@subtitle = ""
|
56
57
|
|
57
58
|
if @fname
|
58
59
|
@title = File.basename(@fname)
|
59
60
|
@dirname = File.dirname(@fname)
|
60
61
|
userhome = File.expand_path("~")
|
61
|
-
@subtitle = @dirname.gsub(/^#{userhome}/, "~")
|
62
|
+
# @subtitle = @dirname.gsub(/^#{userhome}/, "~")
|
63
|
+
@subtitle = @fname.gsub(/^#{userhome}/, "~")
|
62
64
|
end
|
63
65
|
|
64
66
|
t1 = Time.now
|
65
|
-
gui_set_current_buffer(@id)
|
66
|
-
gui_set_window_title(@title, @subtitle)
|
67
67
|
|
68
68
|
set_content(str)
|
69
69
|
debug "init time:#{Time.now - t1}"
|
@@ -72,6 +72,10 @@ class Buffer < String
|
|
72
72
|
self << "\n" if self[-1] != "\n"
|
73
73
|
@current_word = nil
|
74
74
|
@active_kbd_mode = nil
|
75
|
+
if conf(:enable_lsp)
|
76
|
+
init_lsp
|
77
|
+
end
|
78
|
+
return self
|
75
79
|
end
|
76
80
|
|
77
81
|
def list_str()
|
@@ -99,6 +103,36 @@ class Buffer < String
|
|
99
103
|
end
|
100
104
|
end
|
101
105
|
|
106
|
+
def lsp_get_def()
|
107
|
+
if !@lsp.nil?
|
108
|
+
fpuri = URI.join("file:///", @fname).to_s
|
109
|
+
@lsp.get_definition(fpuri, @lpos, @cpos)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def lsp_jump_to_def()
|
114
|
+
if !@lsp.nil?
|
115
|
+
fpuri = URI.join("file:///", @fname).to_s
|
116
|
+
r = @lsp.get_definition(fpuri, @lpos, @cpos)
|
117
|
+
if !r.nil?
|
118
|
+
jump_to_file(r[0], r[1])
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def init_lsp()
|
124
|
+
if conf(:enable_lsp) and !@lang.nil?
|
125
|
+
@lsp = LangSrv.get(@lang.to_sym)
|
126
|
+
if @lang == "php"
|
127
|
+
# Ripl.start :binding => binding
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
if !@lsp.nil?
|
132
|
+
@lsp.open_file(@fname, self.to_s)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
102
136
|
def detect_file_language
|
103
137
|
@lang = nil
|
104
138
|
@lang = "c" if @fname.match(/\.(c|h|cpp)$/)
|
@@ -106,6 +140,7 @@ class Buffer < String
|
|
106
140
|
@lang = "ruby" if @fname.match(/\.(rb)$/)
|
107
141
|
@lang = "hyperplaintext" if @fname.match(/\.(txt)$/)
|
108
142
|
@lang = "php" if @fname.match(/\.(php)$/)
|
143
|
+
@lsp = nil
|
109
144
|
|
110
145
|
lm = GtkSource::LanguageManager.new
|
111
146
|
|
@@ -119,10 +154,12 @@ class Buffer < String
|
|
119
154
|
debug "Guessed LANG: #{lang.id}"
|
120
155
|
@lang = lang.id
|
121
156
|
end
|
157
|
+
puts @lang.inspect
|
122
158
|
|
123
159
|
if @lang
|
124
160
|
gui_set_file_lang(@id, @lang)
|
125
161
|
end
|
162
|
+
return @lang
|
126
163
|
end
|
127
164
|
|
128
165
|
def view()
|
@@ -130,6 +167,59 @@ class Buffer < String
|
|
130
167
|
return vma.gui.buffers[@id]
|
131
168
|
end
|
132
169
|
|
170
|
+
# Replace char at pos with audio widget for
|
171
|
+
def add_audio(afpath, pos)
|
172
|
+
return if !is_legal_pos(pos)
|
173
|
+
afpath = File.expand_path(afpath)
|
174
|
+
return if !File.exist?(afpath)
|
175
|
+
|
176
|
+
vbuf = view.buffer
|
177
|
+
itr = vbuf.get_iter_at(:offset => pos)
|
178
|
+
itr2 = vbuf.get_iter_at(:offset => pos + 1)
|
179
|
+
vbuf.delete(itr, itr2)
|
180
|
+
anchor = vbuf.create_child_anchor(itr)
|
181
|
+
|
182
|
+
mf = Gtk::MediaFile.new(afpath)
|
183
|
+
mc = Gtk::MediaControls.new(mf)
|
184
|
+
# mc = Gtk::MediaControls.new(Gtk::MediaFile.new)
|
185
|
+
# Thread.new{mf.play;sleep 0.01; mf.pause}
|
186
|
+
@audiofiles << mc
|
187
|
+
|
188
|
+
view.add_child_at_anchor(mc, anchor)
|
189
|
+
mc.set_size_request(500, 20)
|
190
|
+
mc.set_margin_start(view.gutter_width + 10)
|
191
|
+
|
192
|
+
provider = Gtk::CssProvider.new
|
193
|
+
mc.add_css_class("medctr")
|
194
|
+
|
195
|
+
provider.load(data: ".medctr { background-color:#353535; }")
|
196
|
+
mc.style_context.add_provider(provider)
|
197
|
+
|
198
|
+
pp mf.set_prepared(true)
|
199
|
+
# pp mf.pause
|
200
|
+
pp mf.duration
|
201
|
+
pp mf.has_audio?
|
202
|
+
|
203
|
+
# >> Gtk::MediaControls.signals
|
204
|
+
# => ["direction-changed", "destroy", "show", "hide", "map", "unmap", "realize", "unrealize", "state-flags-changed", "mnemonic-activate", "move-focus", "keynav-failed", "query-tooltip", "notify"]
|
205
|
+
|
206
|
+
# If this is done too early, the gutter is not yet drawn which
|
207
|
+
# will result in wrong position
|
208
|
+
if @audiofiles.size == 1
|
209
|
+
run_as_idle proc { self.reset_audio_widget_positions }
|
210
|
+
end
|
211
|
+
$audiof = mf
|
212
|
+
end
|
213
|
+
|
214
|
+
def reset_audio_widget_positions
|
215
|
+
debug "reset_audio_widget_positions", 2
|
216
|
+
for mc in @audiofiles
|
217
|
+
mc.set_size_request(500, 20)
|
218
|
+
mc.set_margin_start(view.gutter_width + 10)
|
219
|
+
end
|
220
|
+
return false
|
221
|
+
end
|
222
|
+
|
133
223
|
def add_image(imgpath, pos)
|
134
224
|
return if !is_legal_pos(pos)
|
135
225
|
|
@@ -141,16 +231,17 @@ class Buffer < String
|
|
141
231
|
|
142
232
|
da = ResizableImage.new(imgpath, view)
|
143
233
|
view.add_child_at_anchor(da, anchor)
|
144
|
-
|
234
|
+
|
235
|
+
da.set_draw_func do |widget, cr|
|
145
236
|
da.do_draw(widget, cr)
|
146
237
|
end
|
147
238
|
|
148
239
|
da.scale_image
|
149
240
|
|
150
|
-
vma.gui.handle_image_resize
|
241
|
+
# vma.gui.handle_image_resize #TODO:gtk4
|
151
242
|
@images << { :path => imgpath, :obj => da }
|
152
243
|
|
153
|
-
gui_set_current_buffer(@id)
|
244
|
+
gui_set_current_buffer(@id) #TODO: needed?
|
154
245
|
end
|
155
246
|
|
156
247
|
def is_legal_pos(pos, op = :read)
|
@@ -307,6 +398,7 @@ class Buffer < String
|
|
307
398
|
gui_set_buffer_contents(@id, self.to_s)
|
308
399
|
@images = [] #TODO: if reload
|
309
400
|
hpt_scan_images(self)
|
401
|
+
hpt_scan_audio(self)
|
310
402
|
|
311
403
|
# add_hl_update(@update_hl_startpos, @update_hl_endpos)
|
312
404
|
end
|
@@ -402,9 +494,23 @@ class Buffer < String
|
|
402
494
|
def run_delta(delta, auto_update_cpos = false)
|
403
495
|
# 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.
|
404
496
|
|
497
|
+
# delta[0]: char position
|
498
|
+
# delta[1]: INSERT or DELETE
|
499
|
+
# delta[2]: number of chars affected
|
500
|
+
# delta[3]: text to add in case of insert
|
501
|
+
|
502
|
+
@version += 1
|
405
503
|
if $experimental
|
406
504
|
@bt.handle_delta(Delta.new(delta[0], delta[1], delta[2], delta[3]))
|
407
505
|
end
|
506
|
+
|
507
|
+
if !@lsp.nil?
|
508
|
+
dc = delta.clone
|
509
|
+
dc[3] = "" if dc[3].nil?
|
510
|
+
dc[4] = get_line_and_col_pos(delta[0])
|
511
|
+
dc[5] = get_line_and_col_pos(delta[0] + delta[2])
|
512
|
+
@lsp.handle_delta(dc, @fname, @version)
|
513
|
+
end
|
408
514
|
pos = delta[0]
|
409
515
|
if @edit_pos_history.any? and (@edit_pos_history.last - pos).abs <= 2
|
410
516
|
@edit_pos_history.pop
|
@@ -441,7 +547,7 @@ class Buffer < String
|
|
441
547
|
@update_hl_endpos = pos + delta[2]
|
442
548
|
add_hl_update(@update_hl_startpos, @update_hl_endpos)
|
443
549
|
end
|
444
|
-
debug
|
550
|
+
debug("DELTA=#{delta.inspect}", 2)
|
445
551
|
# sanity_check_line_ends #TODO: enable with debug mode
|
446
552
|
#highlight_c()
|
447
553
|
|
@@ -804,6 +910,8 @@ class Buffer < String
|
|
804
910
|
end
|
805
911
|
gui_set_cursor_pos(@id, @pos)
|
806
912
|
calculate_line_and_column_pos
|
913
|
+
|
914
|
+
check_if_modified_outside
|
807
915
|
end
|
808
916
|
|
809
917
|
# Get the line number of character position
|
@@ -871,12 +979,12 @@ class Buffer < String
|
|
871
979
|
set_pos(pos)
|
872
980
|
end
|
873
981
|
|
874
|
-
def delete(op)
|
982
|
+
def delete(op, x = nil)
|
875
983
|
$paste_lines = false
|
876
984
|
# Delete selection
|
877
985
|
if op == SELECTION && visual_mode?
|
878
986
|
(startpos, endpos) = get_visual_mode_range2
|
879
|
-
delete_range(startpos, endpos)
|
987
|
+
delete_range(startpos, endpos, x)
|
880
988
|
@pos = [@pos, @selection_start].min
|
881
989
|
end_visual_mode
|
882
990
|
#return
|
@@ -904,21 +1012,39 @@ class Buffer < String
|
|
904
1012
|
#need_redraw!
|
905
1013
|
end
|
906
1014
|
|
907
|
-
def delete_range(startpos, endpos)
|
908
|
-
|
909
|
-
|
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)
|
910
1025
|
add_delta([startpos, DELETE, (endpos - startpos + 1)], true)
|
911
1026
|
#recalc_line_ends
|
912
1027
|
calculate_line_and_column_pos
|
913
1028
|
end
|
914
1029
|
|
1030
|
+
# Ranges to use in delete or copy operations
|
915
1031
|
def get_range(range_id)
|
916
1032
|
range = nil
|
917
1033
|
if range_id == :to_word_end
|
1034
|
+
# TODO: better way to make the search than + 150 from current position
|
918
1035
|
wmarks = get_word_end_marks(@pos, @pos + 150)
|
919
1036
|
if wmarks.any?
|
920
1037
|
range = @pos..wmarks[0]
|
921
1038
|
end
|
1039
|
+
elsif range_id == :to_next_word # start of
|
1040
|
+
wmarks = get_word_start_marks(@pos, @pos + 150)
|
1041
|
+
if !wmarks[0].nil?
|
1042
|
+
range = @pos..(wmarks[0] - 1)
|
1043
|
+
debug range, 2
|
1044
|
+
else
|
1045
|
+
range = get_range(:to_word_end)
|
1046
|
+
end
|
1047
|
+
# Ripl.start :binding => binding
|
922
1048
|
elsif range_id == :to_line_end
|
923
1049
|
debug "TO LINE END"
|
924
1050
|
range = @pos..(@line_ends[@lpos] - 1)
|
@@ -1150,7 +1276,8 @@ class Buffer < String
|
|
1150
1276
|
wtype = :url
|
1151
1277
|
elsif is_existing_file(path)
|
1152
1278
|
message("PATH:'#{word}'")
|
1153
|
-
if vma.can_open_extension?(path)
|
1279
|
+
# if vma.can_open_extension?(path)
|
1280
|
+
if file_is_text_file(path)
|
1154
1281
|
wtype = :textfile
|
1155
1282
|
else
|
1156
1283
|
wtype = :file
|
@@ -1366,6 +1493,12 @@ class Buffer < String
|
|
1366
1493
|
calculate_line_and_column_pos
|
1367
1494
|
end
|
1368
1495
|
|
1496
|
+
def append(c)
|
1497
|
+
pos = self.size - 1
|
1498
|
+
add_delta([pos, INSERT, c.size, c], true)
|
1499
|
+
calculate_line_and_column_pos
|
1500
|
+
end
|
1501
|
+
|
1369
1502
|
def execute_current_line_in_terminal(autoclose = false)
|
1370
1503
|
s = get_current_line
|
1371
1504
|
exec_in_terminal(s, autoclose)
|
@@ -1470,22 +1603,27 @@ class Buffer < String
|
|
1470
1603
|
set_pos(l.end + 1)
|
1471
1604
|
end
|
1472
1605
|
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
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)
|
1478
1613
|
end
|
1614
|
+
end
|
1479
1615
|
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
end
|
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
|
1488
1625
|
debug "PASTE: #{text}"
|
1626
|
+
$clipboard << text
|
1489
1627
|
|
1490
1628
|
return if text == ""
|
1491
1629
|
|
@@ -1502,9 +1640,21 @@ class Buffer < String
|
|
1502
1640
|
set_pos(pos + text.size)
|
1503
1641
|
end
|
1504
1642
|
set_pos(@pos)
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
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
|
1508
1658
|
end
|
1509
1659
|
|
1510
1660
|
def delete_line()
|
@@ -1623,6 +1773,10 @@ class Buffer < String
|
|
1623
1773
|
set_clipboard(self.fname)
|
1624
1774
|
end
|
1625
1775
|
|
1776
|
+
def put_file_ref_to_clipboard
|
1777
|
+
set_clipboard(self.fname + ":#{@lpos}")
|
1778
|
+
end
|
1779
|
+
|
1626
1780
|
def delete_active_selection() #TODO: remove this function
|
1627
1781
|
return if !@visual_mode #TODO: this should not happen
|
1628
1782
|
|
@@ -1641,6 +1795,10 @@ class Buffer < String
|
|
1641
1795
|
|
1642
1796
|
def get_visual_mode_range2()
|
1643
1797
|
r = get_visual_mode_range
|
1798
|
+
if r.begin > r.end
|
1799
|
+
debug "r.begin > r.end"
|
1800
|
+
Ripl.start :binding => binding
|
1801
|
+
end
|
1644
1802
|
return [r.begin, r.end]
|
1645
1803
|
end
|
1646
1804
|
|
@@ -1659,9 +1817,9 @@ class Buffer < String
|
|
1659
1817
|
_end = @pos
|
1660
1818
|
|
1661
1819
|
_start, _end = _end, _start if _start > _end
|
1662
|
-
_end = _end + 1 if _start < _end
|
1663
|
-
|
1664
|
-
return _start..(_end
|
1820
|
+
# _end = _end + 1 if _start < _end #TODO:verify if correct
|
1821
|
+
# return _start..(_end - 1)
|
1822
|
+
return _start..(_end)
|
1665
1823
|
end
|
1666
1824
|
|
1667
1825
|
def selection_start()
|
@@ -1695,7 +1853,36 @@ class Buffer < String
|
|
1695
1853
|
# calls back to file_saveas
|
1696
1854
|
end
|
1697
1855
|
|
1698
|
-
def
|
1856
|
+
def save_as_check_callback(vals)
|
1857
|
+
if vals["yes_btn"] == "submit"
|
1858
|
+
save_as_callback(@unconfirmed_path, true)
|
1859
|
+
end
|
1860
|
+
end
|
1861
|
+
|
1862
|
+
def save_as_callback(fpath, confirmed = false)
|
1863
|
+
# The check if file exists is handled by Gtk::FileChooserDialog in GTK4
|
1864
|
+
# Keeping this code from GTK3 in case want to do this manually at some point
|
1865
|
+
# if !confirmed
|
1866
|
+
# @unconfirmed_path = fpath
|
1867
|
+
# if File.exists?(fpath) and File.file?(fpath)
|
1868
|
+
# params = {}
|
1869
|
+
# params["title"] = "The file already exists, overwrite? \r #{fpath}"
|
1870
|
+
# params["inputs"] = {}
|
1871
|
+
# params["inputs"]["yes_btn"] = { :label => "Yes", :type => :button, :default_focus => true }
|
1872
|
+
# callback = proc { |x| save_as_check_callback(x) }
|
1873
|
+
# params[:callback] = callback
|
1874
|
+
# PopupFormGenerator.new(params).run
|
1875
|
+
# return
|
1876
|
+
# elsif File.exists?(fpath) #and File.directory?(fpath)
|
1877
|
+
# params = {}
|
1878
|
+
# params["title"] = "Can't write to the destination.\r #{fpath}"
|
1879
|
+
# params["inputs"] = {}
|
1880
|
+
# params["inputs"]["ok_btn"] = { :label => "Ok", :type => :button, :default_focus => true }
|
1881
|
+
# PopupFormGenerator.new(params).run
|
1882
|
+
# return
|
1883
|
+
# end
|
1884
|
+
# end
|
1885
|
+
|
1699
1886
|
set_filename(fpath)
|
1700
1887
|
save()
|
1701
1888
|
gui_set_window_title(@title, @subtitle) #TODO: if not active buffer?
|
@@ -1729,11 +1916,47 @@ class Buffer < String
|
|
1729
1916
|
message("File #{fpath} not writeable")
|
1730
1917
|
#TODO: show message box
|
1731
1918
|
end
|
1919
|
+
@last_save = Time.now
|
1920
|
+
puts "file saved on #{@last_save}"
|
1732
1921
|
sleep 3
|
1733
1922
|
}
|
1734
1923
|
end
|
1735
1924
|
|
1925
|
+
def check_if_modified_outside_callback(x)
|
1926
|
+
debug "check_if_modified_outside_callback"
|
1927
|
+
if x["yes_btn"] == "submit"
|
1928
|
+
revert()
|
1929
|
+
end
|
1930
|
+
end
|
1931
|
+
|
1932
|
+
def check_if_modified_outside
|
1933
|
+
# Don't check if less than 8 seconds since last checked
|
1934
|
+
return false if @fname.nil?
|
1935
|
+
return false if Time.now - 8 < @file_last_cheked
|
1936
|
+
@file_last_cheked = Time.now
|
1937
|
+
return false if !File.exist?(@fname)
|
1938
|
+
|
1939
|
+
file_stat = File.stat(@fname)
|
1940
|
+
modification_time = file_stat.mtime
|
1941
|
+
|
1942
|
+
if modification_time > @last_save and @last_asked_from_user < modification_time
|
1943
|
+
@last_asked_from_user = Time.now
|
1944
|
+
debug "File modified outside this program."
|
1945
|
+
params = {}
|
1946
|
+
params["title"] = "The file has been modified outside this program. Reload from disk? \r #{@fname}"
|
1947
|
+
params["inputs"] = {}
|
1948
|
+
params["inputs"]["yes_btn"] = { :label => "Yes", :type => :button, :default_focus => true }
|
1949
|
+
callback = proc { |x| check_if_modified_outside_callback(x) }
|
1950
|
+
params[:callback] = callback
|
1951
|
+
PopupFormGenerator.new(params).run
|
1952
|
+
return true
|
1953
|
+
end
|
1954
|
+
|
1955
|
+
return false
|
1956
|
+
end
|
1957
|
+
|
1736
1958
|
def save()
|
1959
|
+
check_if_modified_outside
|
1737
1960
|
if !@fname
|
1738
1961
|
save_as()
|
1739
1962
|
return
|
@@ -1754,22 +1977,24 @@ class Buffer < String
|
|
1754
1977
|
|
1755
1978
|
message("Auto format #{@fname}")
|
1756
1979
|
|
1757
|
-
|
1980
|
+
ftype = get_file_type()
|
1981
|
+
if ["chdr", "c", "cpp", "cpphdr"].include?(ftype)
|
1758
1982
|
|
1759
1983
|
#C/C++/Java/JavaScript/Objective-C/Protobuf code
|
1760
1984
|
system("clang-format -style='{BasedOnStyle: LLVM, ColumnLimit: 100, SortIncludes: false}' #{file.path} > #{infile.path}")
|
1761
1985
|
bufc = IO.read(infile.path)
|
1762
|
-
elsif
|
1986
|
+
elsif ftype == "Javascript"
|
1763
1987
|
cmd = "clang-format #{file.path} > #{infile.path}'"
|
1764
1988
|
debug cmd
|
1765
1989
|
system(cmd)
|
1766
1990
|
bufc = IO.read(infile.path)
|
1767
|
-
elsif
|
1991
|
+
elsif ftype == "ruby"
|
1768
1992
|
cmd = "rufo #{file.path}"
|
1769
1993
|
debug cmd
|
1770
1994
|
system(cmd)
|
1771
1995
|
bufc = IO.read(file.path)
|
1772
1996
|
else
|
1997
|
+
message("No auto-format handler for file of type: #{ftype}")
|
1773
1998
|
return
|
1774
1999
|
end
|
1775
2000
|
self.update_content(bufc)
|
@@ -1818,8 +2043,8 @@ def is_path_writable(fpath)
|
|
1818
2043
|
end
|
1819
2044
|
|
1820
2045
|
def backup_all_buffers()
|
1821
|
-
for
|
1822
|
-
|
2046
|
+
for b in bufs
|
2047
|
+
b.backup
|
1823
2048
|
end
|
1824
2049
|
message("Backup all buffers")
|
1825
2050
|
end
|