vimamsa 0.1.10 → 0.1.12
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 +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
|