vimamsa 0.1.10 → 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 +20 -3
- data/custom_example.rb +11 -1
- data/demo.txt +2 -2
- data/exe/vimamsa +1 -1
- data/lib/vimamsa/ack.rb +57 -9
- data/lib/vimamsa/actions.rb +1 -1
- data/lib/vimamsa/buffer.rb +272 -44
- data/lib/vimamsa/buffer_list.rb +57 -16
- data/lib/vimamsa/buffer_manager.rb +19 -3
- data/lib/vimamsa/conf.rb +10 -1
- data/lib/vimamsa/debug.rb +7 -3
- data/lib/vimamsa/easy_jump.rb +9 -5
- data/lib/vimamsa/editor.rb +55 -41
- data/lib/vimamsa/file_finder.rb +70 -72
- 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 +467 -120
- 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 +171 -78
- 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 +54 -25
- 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 +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 +24 -22
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
|
@@ -402,9 +497,23 @@ class Buffer < String
|
|
402
497
|
def run_delta(delta, auto_update_cpos = false)
|
403
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.
|
404
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
|
405
506
|
if $experimental
|
406
507
|
@bt.handle_delta(Delta.new(delta[0], delta[1], delta[2], delta[3]))
|
407
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
|
408
517
|
pos = delta[0]
|
409
518
|
if @edit_pos_history.any? and (@edit_pos_history.last - pos).abs <= 2
|
410
519
|
@edit_pos_history.pop
|
@@ -441,7 +550,7 @@ class Buffer < String
|
|
441
550
|
@update_hl_endpos = pos + delta[2]
|
442
551
|
add_hl_update(@update_hl_startpos, @update_hl_endpos)
|
443
552
|
end
|
444
|
-
debug
|
553
|
+
debug("DELTA=#{delta.inspect}", 2)
|
445
554
|
# sanity_check_line_ends #TODO: enable with debug mode
|
446
555
|
#highlight_c()
|
447
556
|
|
@@ -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
|
@@ -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)
|
@@ -1470,22 +1606,27 @@ class Buffer < String
|
|
1470
1606
|
set_pos(l.end + 1)
|
1471
1607
|
end
|
1472
1608
|
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
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)
|
1478
1616
|
end
|
1617
|
+
end
|
1479
1618
|
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
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
|
1488
1628
|
debug "PASTE: #{text}"
|
1629
|
+
$clipboard << text
|
1489
1630
|
|
1490
1631
|
return if text == ""
|
1491
1632
|
|
@@ -1502,9 +1643,21 @@ class Buffer < String
|
|
1502
1643
|
set_pos(pos + text.size)
|
1503
1644
|
end
|
1504
1645
|
set_pos(@pos)
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
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
|
1508
1661
|
end
|
1509
1662
|
|
1510
1663
|
def delete_line()
|
@@ -1623,6 +1776,10 @@ class Buffer < String
|
|
1623
1776
|
set_clipboard(self.fname)
|
1624
1777
|
end
|
1625
1778
|
|
1779
|
+
def put_file_ref_to_clipboard
|
1780
|
+
set_clipboard(self.fname + ":#{@lpos}")
|
1781
|
+
end
|
1782
|
+
|
1626
1783
|
def delete_active_selection() #TODO: remove this function
|
1627
1784
|
return if !@visual_mode #TODO: this should not happen
|
1628
1785
|
|
@@ -1641,6 +1798,10 @@ class Buffer < String
|
|
1641
1798
|
|
1642
1799
|
def get_visual_mode_range2()
|
1643
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
|
1644
1805
|
return [r.begin, r.end]
|
1645
1806
|
end
|
1646
1807
|
|
@@ -1659,9 +1820,9 @@ class Buffer < String
|
|
1659
1820
|
_end = @pos
|
1660
1821
|
|
1661
1822
|
_start, _end = _end, _start if _start > _end
|
1662
|
-
_end = _end + 1 if _start < _end
|
1663
|
-
|
1664
|
-
return _start..(_end
|
1823
|
+
# _end = _end + 1 if _start < _end #TODO:verify if correct
|
1824
|
+
# return _start..(_end - 1)
|
1825
|
+
return _start..(_end)
|
1665
1826
|
end
|
1666
1827
|
|
1667
1828
|
def selection_start()
|
@@ -1695,7 +1856,36 @@ class Buffer < String
|
|
1695
1856
|
# calls back to file_saveas
|
1696
1857
|
end
|
1697
1858
|
|
1698
|
-
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
|
+
|
1699
1889
|
set_filename(fpath)
|
1700
1890
|
save()
|
1701
1891
|
gui_set_window_title(@title, @subtitle) #TODO: if not active buffer?
|
@@ -1729,11 +1919,47 @@ class Buffer < String
|
|
1729
1919
|
message("File #{fpath} not writeable")
|
1730
1920
|
#TODO: show message box
|
1731
1921
|
end
|
1922
|
+
@last_save = Time.now
|
1923
|
+
puts "file saved on #{@last_save}"
|
1732
1924
|
sleep 3
|
1733
1925
|
}
|
1734
1926
|
end
|
1735
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
|
+
|
1736
1961
|
def save()
|
1962
|
+
check_if_modified_outside
|
1737
1963
|
if !@fname
|
1738
1964
|
save_as()
|
1739
1965
|
return
|
@@ -1754,22 +1980,24 @@ class Buffer < String
|
|
1754
1980
|
|
1755
1981
|
message("Auto format #{@fname}")
|
1756
1982
|
|
1757
|
-
|
1983
|
+
ftype = get_file_type()
|
1984
|
+
if ["chdr", "c", "cpp", "cpphdr"].include?(ftype)
|
1758
1985
|
|
1759
1986
|
#C/C++/Java/JavaScript/Objective-C/Protobuf code
|
1760
1987
|
system("clang-format -style='{BasedOnStyle: LLVM, ColumnLimit: 100, SortIncludes: false}' #{file.path} > #{infile.path}")
|
1761
1988
|
bufc = IO.read(infile.path)
|
1762
|
-
elsif
|
1989
|
+
elsif ftype == "Javascript"
|
1763
1990
|
cmd = "clang-format #{file.path} > #{infile.path}'"
|
1764
1991
|
debug cmd
|
1765
1992
|
system(cmd)
|
1766
1993
|
bufc = IO.read(infile.path)
|
1767
|
-
elsif
|
1994
|
+
elsif ftype == "ruby"
|
1768
1995
|
cmd = "rufo #{file.path}"
|
1769
1996
|
debug cmd
|
1770
1997
|
system(cmd)
|
1771
1998
|
bufc = IO.read(file.path)
|
1772
1999
|
else
|
2000
|
+
message("No auto-format handler for file of type: #{ftype}")
|
1773
2001
|
return
|
1774
2002
|
end
|
1775
2003
|
self.update_content(bufc)
|
@@ -1818,8 +2046,8 @@ def is_path_writable(fpath)
|
|
1818
2046
|
end
|
1819
2047
|
|
1820
2048
|
def backup_all_buffers()
|
1821
|
-
for
|
1822
|
-
|
2049
|
+
for b in bufs
|
2050
|
+
b.backup
|
1823
2051
|
end
|
1824
2052
|
message("Backup all buffers")
|
1825
2053
|
end
|