vimamsa 0.1.0 → 0.1.5

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.
@@ -0,0 +1,161 @@
1
+
2
+ # Similar feature as Vim EasyMotion https://github.com/easymotion/vim-easymotion
3
+ class EasyJump
4
+ def initialize()
5
+ make_jump_sequence
6
+ end
7
+ end
8
+
9
+ def easy_jump(direction)
10
+ # message "EASY JUMP"
11
+ visible_range = get_visible_area()
12
+ visible_text = $buffer[visible_range[0]..visible_range[1]]
13
+ wsmarks = scan_word_start_marks(visible_text)
14
+ line_starts = scan_indexes(visible_text, /^/)
15
+ lsh = Hash[line_starts.collect { |x| [x, true] }]
16
+ wsmh = Hash[wsmarks.collect { |x| [x, true] }]
17
+
18
+ wsmarks.select! { |x|
19
+ r = true
20
+ r = false if lsh[x] or lsh[x - 1] or lsh[x - 2]
21
+ r
22
+ }
23
+
24
+ linestart_buf = (line_starts).collect { |x| x + visible_range[0] }
25
+ wsmarks_buf = (wsmarks).collect { |x| x + visible_range[0] }
26
+
27
+ # All line starts should be accessible with just two key presses, so put them first in order
28
+ # Other word start positions ordered by distance from current pos
29
+ wsmarks_buf.sort_by! { |x| (x - $buffer.pos).abs }
30
+ $easy_jump_wsmarks = linestart_buf + wsmarks_buf
31
+
32
+ $jump_sequence = make_jump_sequence($easy_jump_wsmarks.size)
33
+
34
+ $input_char_call_func = method(:easy_jump_input_char)
35
+ $kbd.set_mode(:readchar)
36
+ $easy_jump_input = ""
37
+ easy_jump_draw
38
+ end
39
+
40
+ def easy_jump_input_char(c)
41
+ # vma.paint_stack = []
42
+ puts "EASY JUMP: easy_jump_input_char [#{c}]"
43
+ $easy_jump_input << c.upcase
44
+ if $jump_sequence.include?($easy_jump_input)
45
+ jshash = Hash[$jump_sequence.map.with_index.to_a]
46
+ nthword = jshash[$easy_jump_input]
47
+ puts "nthword:#{nthword} #{[$easy_jump_wsmarks[nthword],$jump_sequence[nthword]]}"
48
+ $buffer.set_pos($easy_jump_wsmarks[nthword])
49
+ $kbd.set_mode(:command)
50
+ $input_char_call_func = nil
51
+ $jump_sequence = []
52
+ $vmag.clear_overlay()
53
+ end
54
+ if $easy_jump_input.size > 2
55
+ $kbd.set_mode(:command)
56
+ $input_char_call_func = nil
57
+ $jump_sequence = []
58
+ $vmag.clear_overlay()
59
+ end
60
+ end
61
+
62
+ def easy_jump_draw()
63
+ # puts $jump_sequence.inspect
64
+ # puts $easy_jump_wsmarks.inspect
65
+ $vmag.start_overlay_draw
66
+ for i in 0..($easy_jump_wsmarks.size - 1)
67
+ $vmag.overlay_draw_text($jump_sequence[i], $easy_jump_wsmarks[i])
68
+ end
69
+ $vmag.end_overlay_draw
70
+
71
+ return
72
+ return if $jump_sequence.empty?
73
+ puts "EASY JUMP DRAW"
74
+ screen_cord = cpp_function_wrapper(0, [$easy_jump_wsmarks])
75
+ screen_cord = screen_cord[1..$jump_sequence.size]
76
+ screen_cord.each_with_index { |point, i|
77
+ mark_str = $jump_sequence[i]
78
+ #puts "draw #{point[0]}x#{point[1]}"
79
+ draw_text(mark_str, point[0] + 3, point[1])
80
+ #break if m > $cpos
81
+ }
82
+ end
83
+
84
+ def make_jump_sequence(num_items)
85
+ left_hand = "asdfvgbqwertzxc123".upcase.split("")
86
+ right_hand = "jklhnnmyuiop890".upcase.split("")
87
+
88
+ sequence = []
89
+ left_hand_fast = "asdf".upcase.split("")
90
+ right_hand_fast = "jkl;".upcase.split("")
91
+
92
+ left_hand_slow = "wergc".upcase.split("") # v
93
+ right_hand_slow = "uiophnm,".upcase.split("")
94
+
95
+ left_hand_slow2 = "tzx23".upcase.split("")
96
+ right_hand_slow2 = "yb9'".upcase.split("")
97
+
98
+ # Rmoved characters that can be mixed: O0Q, 8B, I1, VY
99
+
100
+ left_fast_slow = Array.new(left_hand_fast).concat(left_hand_slow)
101
+ right_fast_slow = Array.new(right_hand_fast).concat(right_hand_slow)
102
+
103
+ left_hand_all = Array.new(left_hand_fast).concat(left_hand_slow).concat(left_hand_slow2)
104
+ right_hand_all = Array.new(right_hand_fast).concat(right_hand_slow).concat(right_hand_slow2)
105
+
106
+ left_hand_fast.each { |x|
107
+ left_hand_fast.each { |y|
108
+ sequence << "#{x}#{y}"
109
+ }
110
+ }
111
+
112
+ right_hand_fast.each { |x|
113
+ right_hand_fast.each { |y|
114
+ sequence << "#{x}#{y}"
115
+ }
116
+ }
117
+
118
+ right_hand_fast.each { |x|
119
+ left_hand_fast.each { |y|
120
+ sequence << "#{x}#{y}"
121
+ }
122
+ }
123
+
124
+ left_hand_fast.each { |x|
125
+ right_hand_fast.each { |y|
126
+ sequence << "#{x}#{y}"
127
+ }
128
+ }
129
+
130
+ left_hand_slow.each { |x|
131
+ right_fast_slow.each { |y|
132
+ sequence << "#{x}#{y}"
133
+ }
134
+ }
135
+
136
+ right_hand_slow.each { |x|
137
+ left_fast_slow.each { |y|
138
+ sequence << "#{x}#{y}"
139
+ }
140
+ }
141
+
142
+ left_hand_slow2.each { |x|
143
+ right_hand_all.each { |y|
144
+ left_hand_all.each { |z|
145
+ sequence << "#{x}#{y}#{z}"
146
+ }
147
+ }
148
+ }
149
+
150
+ right_hand_slow2.each { |x|
151
+ left_hand_all.each { |y|
152
+ right_hand_all.each { |z|
153
+ sequence << "#{x}#{y}#{z}"
154
+ }
155
+ }
156
+ }
157
+
158
+ #printf("Size of sequence: %d\n",sequence.size)
159
+ #puts sequence.inspect
160
+ return sequence
161
+ end
@@ -0,0 +1,667 @@
1
+ require "pty"
2
+
3
+ def exec_in_terminal(cmd)
4
+ # puts "CMD:#{cmd}"
5
+
6
+ # global to prevent garbage collect unlink
7
+ $initf = Tempfile.new("bashinit")
8
+ # puts $initf.path
9
+ $initf.write(cmd)
10
+ $initf.write("rm #{$initf.path}\n")
11
+ $initf.write("\nexec bash\n")
12
+ $initf.close
13
+ # PTY.spawn("gnome-terminal", "--tab", "--", "bash", "-i", $initf.path, "-c", "exec bash")
14
+ fork { exec "gnome-terminal", "--tab", "--", "bash", "-i", $initf.path, "-c", "exec bash" }
15
+ end
16
+
17
+ def handle_drag_and_drop(fname)
18
+ debug "EDITOR:handle_drag_and_drop"
19
+ buf.handle_drag_and_drop(fname)
20
+ end
21
+
22
+ class Editor
23
+ attr_reader :file_content_search_paths, :file_name_search_paths
24
+ attr_accessor :converters, :fh, :paint_stack
25
+ #attr_writer :call_func, :update_highlight
26
+
27
+ def initialize()
28
+ # Thread.new{10000.times{|x|sleep(3);10000.times{|y|y+2};puts "FOOTHREAD #{x}"}}
29
+
30
+ # Search for content inside files (e.g. using ack/grep) in:
31
+ @file_content_search_paths = []
32
+
33
+ # Search for files based on filenames in:
34
+ @file_name_search_paths = []
35
+
36
+ #Regexp gsubs or other small modifiers of text
37
+ @converters = {}
38
+ @paint_stack = []
39
+ @_plugins = {}
40
+ end
41
+
42
+ def open_file_listener(added)
43
+ if !added.empty?
44
+ for fp in added
45
+ sleep 0.1
46
+ x = IO.read(fp)
47
+ File.delete(fp)
48
+ for f in x.lines
49
+ f.gsub!("\n", "")
50
+ if File.exist?(f)
51
+ if file_is_text_file(f)
52
+ jump_to_file(f)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ def start
61
+ # $highlight = {}
62
+
63
+ # GLib::Idle.add
64
+ # Ripl.start :binding => binding
65
+ # GLib::Idle.add(proc{ puts "IDLEFUNC"})
66
+ # GLib::Idle.add(proc { idle_func })
67
+
68
+ $hook = Hook.new
69
+ register_plugin(:Hook, $hook)
70
+ $macro = Macro.new
71
+ register_plugin(:Macro, $macro)
72
+ $search = Search.new
73
+ register_plugin(:Search, $search)
74
+
75
+ $buffers = BufferList.new
76
+ $minibuffer = Buffer.new(">", "")
77
+
78
+ require "vimamsa/text_transforms"
79
+
80
+ debug "ARGV: " + ARGV.inspect
81
+ # build_key_bindings_tree
82
+ $kbd = KeyBindingTree.new()
83
+ $kbd.add_mode("C", :command)
84
+ $kbd.add_mode("I", :insert)
85
+ $kbd.add_mode("V", :visual)
86
+ $kbd.add_mode("M", :minibuffer)
87
+ $kbd.add_mode("R", :readchar)
88
+ $kbd.add_mode("B", :browse)
89
+ $kbd.set_default_mode(:command)
90
+ require "vimamsa/default_key_bindings"
91
+ sleep(0.03)
92
+
93
+ FileManager.init
94
+
95
+ dot_dir = File.expand_path("~/.vimamsa")
96
+ Dir.mkdir(dot_dir) unless File.exist?(dot_dir)
97
+ listen_dir = File.expand_path("~/.vimamsa/listen")
98
+ Dir.mkdir(listen_dir) unless File.exist?(dot_dir)
99
+ listener = Listen.to(listen_dir) do |modified, added, removed|
100
+ puts(modified: modified, added: added, removed: removed)
101
+ open_file_listener(added)
102
+ end
103
+ listener.start
104
+
105
+ $cnf[:theme] = "Twilight_edit"
106
+ $cnf[:syntax_highlight] = true
107
+ settings_path = get_dot_path("settings.rb")
108
+ if File.exist?(settings_path)
109
+ $cnf = eval(IO.read(settings_path))
110
+ end
111
+
112
+ # set_qt_style(1)
113
+
114
+ # Limit file search to these extensions:
115
+ $find_extensions = [".txt", ".h", ".c", ".cpp", ".hpp", ".rb"]
116
+
117
+ dotfile = read_file("", "~/.vimamsarc")
118
+ eval(dotfile) if dotfile
119
+
120
+ # build_options
121
+
122
+ fname = nil
123
+ if conf(:startup_file)
124
+ fname_ = File.expand_path(conf(:startup_file))
125
+ if File.exist?(fname_)
126
+ fname = fname_
127
+ end
128
+ end
129
+ fname = ARGV[0] if ARGV.size >= 1 and File.file?(File.expand_path(ARGV[0]))
130
+ # vma.add_content_search_path(Dir.pwd)
131
+ for fn in ARGV
132
+ fn = File.expand_path(fn)
133
+ if File.directory?(fn)
134
+ vma.add_content_search_path(fn)
135
+ $search_dirs << fn
136
+ end
137
+ end
138
+
139
+ if fname
140
+ buffer = Buffer.new(read_file("", fname), fname)
141
+ else
142
+ buffer = Buffer.new("INIT\n")
143
+ end
144
+ $buffers << buffer
145
+
146
+ # load_theme($cnf[:theme])
147
+
148
+ # render_buffer($buffer, 1) #TODO
149
+
150
+ # gui_select_buffer_init #TODO
151
+ # gui_file_finder_init #TODO
152
+
153
+ #Load plugins
154
+ require "vimamsa/file_history.rb"
155
+ @fh = FileHistory.new
156
+ # @_plugins[:FileFinder] = FileFinder.new
157
+ @_plugins[:FileHistory] = @fh
158
+
159
+ register_plugin(:FileHistory, @fh)
160
+ register_plugin(:FileFinder, FileFinder.new)
161
+ # To access via vma.FileFinder
162
+ # self.define_singleton_method(:FileFinder) { @_plugins[:FileFinder] }
163
+
164
+ $hook.call(:after_init)
165
+ end
166
+
167
+ def register_plugin(name, obj)
168
+ @_plugins[name] = obj
169
+ # To access via e.g. vma.FileFinder
170
+ self.define_singleton_method(name) { obj }
171
+ end
172
+
173
+ def buf()
174
+ return $buffer
175
+ end
176
+
177
+ def marshal_save(varname, vardata)
178
+ save_var_to_file(varname, Marshal.dump(vardata))
179
+ end
180
+
181
+ def marshal_load(varname, default_data = nil)
182
+ mdata = load_var_from_file(varname)
183
+ if mdata
184
+ return Marshal.load(mdata)
185
+ else
186
+ return default_data
187
+ end
188
+ end
189
+
190
+ def save_var_to_file(varname, vardata)
191
+ fn = get_dot_path(varname)
192
+ f = File.open(fn, "w")
193
+ File.binwrite(f, vardata)
194
+ f.close
195
+ end
196
+
197
+ def load_var_from_file(varname)
198
+ fn = get_dot_path(varname)
199
+ if File.exist?(fn)
200
+ vardata = IO.binread(fn)
201
+ if vardata
202
+ debug("Successfully red #{varname} from file #{fn}")
203
+ return vardata
204
+ end
205
+ end
206
+ return nil
207
+ end
208
+
209
+ def plug()
210
+ return @_plugins
211
+ end
212
+
213
+ def shutdown()
214
+ $hook.call(:shutdown)
215
+ save_state
216
+ end
217
+
218
+ def save_state
219
+ end
220
+
221
+ def add_content_search_path(pathstr)
222
+ p = File.expand_path(pathstr)
223
+ if !@file_content_search_paths.include?(p)
224
+ @file_content_search_paths << p
225
+ end
226
+ end
227
+
228
+ # Register converter
229
+ def reg_conv(converter, converter_id)
230
+ @converters[converter_id] = converter
231
+ reg_act(converter_id, proc { $buffer.convert_selected_text(converter_id) }, "Converter #{converter_id}", [:selection])
232
+ # reg_act(converter_id, "$buffer.convert_selected_text(:#{converter_id})", "Converter #{converter_id}", [:selection])
233
+ end
234
+
235
+ def apply_conv(converter_id, txt)
236
+ @converters[converter_id].apply(txt)
237
+ end
238
+
239
+ def get_content_search_paths()
240
+ r = @file_content_search_paths.clone
241
+ p = find_project_dir_of_cur_buffer()
242
+
243
+ if p and !@file_content_search_paths.include?(p)
244
+ r.insert(0, p)
245
+ end
246
+ return r
247
+ end
248
+
249
+ def can_open_extension?(filepath)
250
+ exts = $cnf[:extensions_to_open]
251
+ extname = Pathname.new(filepath).extname.downcase
252
+ can_open = exts.include?(extname)
253
+ puts "CAN OPEN?: #{can_open}"
254
+ return can_open
255
+ end
256
+ end
257
+
258
+ def _quit()
259
+ vma.shutdown
260
+ exit
261
+ end
262
+
263
+ def fatal_error(msg)
264
+ puts msg
265
+ exit!
266
+ end
267
+
268
+ def file_saveas(filename)
269
+ $buffer.set_filename(filename)
270
+ $buffer.save()
271
+ end
272
+
273
+ def open_file_dialog()
274
+ path = ""
275
+ path = $buffer.fname if $buffer.fname
276
+ qt_open_file_dialog(File.dirname(path))
277
+ end
278
+
279
+ def system_clipboard_changed(clipboard_contents)
280
+ max_clipboard_items = 100
281
+ if clipboard_contents != $clipboard[-1]
282
+ #TODO: HACK
283
+ $paste_lines = false
284
+ end
285
+ $clipboard << clipboard_contents
286
+ # puts $clipboard[-1]
287
+ $clipboard = $clipboard[-([$clipboard.size, max_clipboard_items].min)..-1]
288
+ end
289
+
290
+ def set_clipboard(s)
291
+ if !(s.class <= String) or s.size == 0
292
+ puts s.inspect
293
+ puts [s, s.class, s.size]
294
+ log_error("s.class != String or s.size == 0")
295
+ Ripl.start :binding => binding
296
+ return
297
+ end
298
+ $clipboard << s
299
+ set_system_clipboard(s)
300
+ $register[$cur_register] = s
301
+ debug "SET CLIPBOARD: [#{s}]"
302
+ debug "REGISTER: #{$cur_register}:#{$register[$cur_register]}"
303
+ end
304
+
305
+ def set_cursor_pos(new_pos)
306
+ buf.set_pos(new_pos)
307
+ #render_buffer($buffer)
308
+ debug "New pos: #{new_pos}lpos:#{$buffer.lpos} cpos:#{$buffer.cpos}"
309
+ end
310
+
311
+ def set_last_command(cmd)
312
+ $command_history << cmd
313
+ end
314
+
315
+ def can_save_to_directory?(dpath)
316
+ return false if !File.exist?(dpath)
317
+ return false if !File.directory?(dpath)
318
+ return false if !File.writable?(dpath)
319
+ return true
320
+ end
321
+
322
+ def repeat_last_action()
323
+ cmd = $command_history.last
324
+ cmd[:method].call *cmd[:params] if cmd != nil
325
+ end
326
+
327
+ def repeat_last_find()
328
+ return if !defined? $last_find_command
329
+ $buffer.jump_to_next_instance_of_char($last_find_command[:char],
330
+ $last_find_command[:direction])
331
+ end
332
+
333
+ def set_next_command_count(num)
334
+ if $next_command_count != nil
335
+ $next_command_count = $next_command_count * 10 + num.to_i
336
+ else
337
+ $next_command_count = num.to_i
338
+ end
339
+ debug("NEXT COMMAND COUNT: #{$next_command_count}")
340
+ end
341
+
342
+ def start_minibuffer_cmd(bufname, bufstr, cmd)
343
+ $kbd.set_mode(:minibuffer)
344
+ $minibuffer = Buffer.new(bufstr, "")
345
+ $minibuffer.call_func = method(cmd)
346
+ end
347
+
348
+ def show_key_bindings()
349
+ kbd_s = "❙Key bindings❙\n"
350
+ kbd_s << "=======================================\n"
351
+ kbd_s << $kbd.to_s
352
+ kbd_s << "\n=======================================\n"
353
+ create_new_file(nil, kbd_s)
354
+ end
355
+
356
+ def diff_buffer()
357
+ bufstr = ""
358
+ orig_path = $buffer.fname
359
+ infile = Tempfile.new("out")
360
+ infile = Tempfile.new("in")
361
+ infile.write($buffer.to_s)
362
+ infile.flush
363
+ cmd = "diff -w '#{orig_path}' #{infile.path}"
364
+ # puts cmd
365
+ bufstr << run_cmd(cmd)
366
+ # puts bufstr
367
+ infile.close; infile.unlink
368
+ create_new_file(nil, bufstr)
369
+ end
370
+
371
+ def invoke_command()
372
+ start_minibuffer_cmd("", "", :execute_command)
373
+ end
374
+
375
+ def execute_command(input_str)
376
+ begin
377
+ out_str = eval(input_str, TOPLEVEL_BINDING) #TODO: Other binding?
378
+ $minibuffer.clear
379
+ $minibuffer << out_str.to_s #TODO: segfaults, why?
380
+ rescue SyntaxError
381
+ debug("SYNTAX ERROR with eval cmd #{action}: " + $!.to_s)
382
+ end
383
+ end
384
+
385
+ def minibuffer_end()
386
+ debug "minibuffer_end"
387
+ $kbd.set_mode(:command)
388
+ minibuffer_input = $minibuffer.to_s[0..-2]
389
+ return $minibuffer.call_func.call(minibuffer_input)
390
+ end
391
+
392
+ def minibuffer_cancel()
393
+ debug "minibuffer_cancel"
394
+ $kbd.set_mode(:command)
395
+ minibuffer_input = $minibuffer.to_s[0..-2]
396
+ # $minibuffer.call_func.call('')
397
+ end
398
+
399
+ def minibuffer_new_char(c)
400
+ if c == "\r"
401
+ raise "Should not come here"
402
+ debug "MINIBUFFER END"
403
+ else
404
+ $minibuffer.insert_txt(c)
405
+ debug "MINIBUFFER: #{c}"
406
+ end
407
+ #$buffer = $minibuffer
408
+ end
409
+
410
+ def readchar_new_char(c)
411
+ $input_char_call_func.call(c)
412
+ end
413
+
414
+ def minibuffer_delete()
415
+ $minibuffer.delete(BACKWARD_CHAR)
416
+ end
417
+
418
+ def message(s)
419
+ s = "[#{DateTime.now().strftime("%H:%M")}] #{s}"
420
+ puts s
421
+
422
+ $vmag.add_to_minibuf(s)
423
+ # $minibuffer = Buffer.new(s, "")
424
+ # $minibuffer[0..-1] = s # TODO
425
+ #render_minibuffer
426
+ end
427
+
428
+ GUESS_ENCODING_ORDER = [
429
+ Encoding::US_ASCII,
430
+ Encoding::UTF_8,
431
+ Encoding::Shift_JIS,
432
+ Encoding::EUC_JP,
433
+ Encoding::EucJP_ms,
434
+ Encoding::Big5,
435
+ Encoding::UTF_16BE,
436
+ Encoding::UTF_16LE,
437
+ Encoding::UTF_32BE,
438
+ Encoding::UTF_32LE,
439
+ Encoding::CP949,
440
+ Encoding::Emacs_Mule,
441
+ Encoding::EUC_KR,
442
+ Encoding::EUC_TW,
443
+ Encoding::GB18030,
444
+ Encoding::GBK,
445
+ Encoding::Stateless_ISO_2022_JP,
446
+ Encoding::CP51932,
447
+ Encoding::EUC_CN,
448
+ Encoding::GB12345,
449
+ Encoding::Windows_31J,
450
+ Encoding::MacJapanese,
451
+ Encoding::UTF8_MAC,
452
+ Encoding::BINARY,
453
+ ]
454
+
455
+ def create_new_file(filename = nil, file_contents = "\n")
456
+ debug "NEW FILE CREATED"
457
+ buffer = Buffer.new(file_contents)
458
+ # qt_set_current_buffer(buffer.id) #TODO: remove?
459
+ $buffers << buffer
460
+ return buffer
461
+ end
462
+
463
+ def filter_buffer(buf)
464
+ i = 0
465
+ while i < buf.size
466
+ if buf[i].ord == 160
467
+ buf[i] = " "
468
+ #TODO: hack. fix properly
469
+ end
470
+ i += 1
471
+ end
472
+ return buf
473
+ end
474
+
475
+ def load_buffer(fname)
476
+ return if !File.exist?(fname)
477
+ existing_buffer = $buffers.get_buffer_by_filename(fname)
478
+ if existing_buffer != nil
479
+ $buffer_history << existing_buffer
480
+ return
481
+ end
482
+ debug("LOAD BUFFER: #{fname}")
483
+ buffer = Buffer.new(read_file("", fname), fname)
484
+ # qt_set_current_buffer(buffer.id)
485
+ buffer.set_active
486
+ debug("DONE LOAD: #{fname}")
487
+ #buf = filter_buffer(buffer)
488
+ # debug("END FILTER: #{fname}")
489
+ $buffers << buffer
490
+ #$buffer_history << $buffers.size - 1
491
+ end
492
+
493
+ def jump_to_file(filename, linenum = 0)
494
+ open_new_file(filename)
495
+ if linenum > 0
496
+ $buffer.jump_to_line(linenum)
497
+ center_on_current_line
498
+ end
499
+ end
500
+
501
+ #TODO: needed?
502
+ def open_existing_file(filename)
503
+ open_new_file(filename)
504
+ end
505
+
506
+ def open_new_file(filename, file_contents = "")
507
+ #TODO: expand path
508
+ filename = File.expand_path(filename)
509
+ b = $buffers.get_buffer_by_filename(filename)
510
+ # File is already opened to existing buffer
511
+ if b != nil
512
+ message "Switching to: #{filename}"
513
+ $buffers.set_current_buffer(b)
514
+ else
515
+ message "New file opened: #{filename}"
516
+ fname = filename
517
+ load_buffer(fname)
518
+ end
519
+ end
520
+
521
+ def scan_word_start_marks(search_str)
522
+ # \Z = end of string, just before last newline.
523
+ wsmarks = scan_indexes(search_str, /(?<=[^\p{Word}])\p{Word}|\Z/)
524
+ return wsmarks
525
+ end
526
+
527
+ def draw_text(str, x, y)
528
+ vma.paint_stack << [4, x, y, str]
529
+ end
530
+
531
+ def center_on_current_line__2del()
532
+ center_where_cursor
533
+ end
534
+
535
+ def hook_draw()
536
+ # TODO: as hook.register
537
+ # easy_jump_draw()
538
+ end
539
+
540
+ def render_buffer(buffer = 0, reset = 0)
541
+ tmpbuf = $buffer.to_s
542
+ debug "pos:#{$buffer.pos} L:#{$buffer.lpos} C:#{$buffer.cpos}"
543
+ pos = $buffer.pos
544
+ selection_start = $buffer.selection_start
545
+
546
+ if $buffer.need_redraw?
547
+ reset = 1
548
+ end
549
+ t1 = Time.now
550
+ hook_draw()
551
+
552
+ render_text(tmpbuf, pos, selection_start, reset) #TODO: remove?
553
+
554
+ if $buffer.need_redraw?
555
+ hpt_scan_images() if $debug #experimental
556
+ end
557
+
558
+ $buffer.highlight
559
+ if Time.now - t1 > 1 / 100.0
560
+ debug "SLOW render"
561
+ debug "Render time: #{Time.now - t1}"
562
+ end
563
+ $buffer.set_redrawed if reset == 1
564
+ end
565
+
566
+ def get_dot_path(sfx)
567
+ dot_dir = File.expand_path("~/.vimamsa")
568
+ Dir.mkdir(dot_dir) unless File.exist?(dot_dir)
569
+ dpath = "#{dot_dir}/#{sfx}"
570
+ return dpath
571
+ end
572
+
573
+ def get_file_line_pointer(s)
574
+ #"/code/vimamsa/lib/vimamsa/buffer_select.rb:31:def"
575
+ # m = s.match(/(~[a-z]*)?\/.*\//)
576
+ m = s.match(/((~[a-z]*)?\/.*\/\S+):(\d+)/)
577
+ if m != nil
578
+ if File.exist?(File.expand_path(m[1]))
579
+ return [m[1], m[3].to_i]
580
+ end
581
+ end
582
+ return nil
583
+ end
584
+
585
+ def open_url(url)
586
+ system("xdg-open", url)
587
+ end
588
+
589
+ def open_with_default_program(url)
590
+ system("xdg-open", url)
591
+ end
592
+
593
+ def run_cmd(cmd)
594
+ tmpf = Tempfile.new("vmarun", "/tmp").path
595
+ cmd = "#{cmd} > #{tmpf}"
596
+ puts "CMD:\n#{cmd}"
597
+ system("bash", "-c", cmd)
598
+ res_str = File.read(tmpf)
599
+ return res_str
600
+ end
601
+
602
+ require "open3"
603
+
604
+ def exec_cmd(bin_name, arg1 = nil, arg2 = nil, arg3 = nil, arg4 = nil, arg5 = nil)
605
+ assert_binary_exists(bin_name)
606
+ if !arg5.nil?
607
+ p = Open3.popen2(bin_name, arg1, arg2, arg3, arg4, arg5)
608
+ elsif !arg4.nil?
609
+ p = Open3.popen2(bin_name, arg1, arg2, arg3, arg4)
610
+ elsif !arg3.nil?
611
+ p = Open3.popen2(bin_name, arg1, arg2, arg3)
612
+ elsif !arg2.nil?
613
+ p = Open3.popen2(bin_name, arg1, arg2)
614
+ elsif !arg1.nil?
615
+ p = Open3.popen2(bin_name, arg1)
616
+ else
617
+ p = Open3.popen2(bin_name)
618
+ end
619
+
620
+ ret_str = p[1].read
621
+ return ret_str
622
+ end
623
+
624
+ def file_is_text_file(fpath)
625
+ puts "file_is_text_file(#{fpath})"
626
+ fpath = File.expand_path(fpath)
627
+ return false if !File.exist?(fpath)
628
+ r = exec_cmd("file", fpath)
629
+ puts "DEBUG:#{r}"
630
+ return true if r.match(/UTF-8.*text/)
631
+ return true if r.match(/ASCII.*text/)
632
+ return false
633
+ end
634
+
635
+ def set_register(char)
636
+ $cur_register = char
637
+ message("Set register #{char}")
638
+ end
639
+
640
+ def paste_register(char)
641
+ $c = $register[char]
642
+ message("Paste: #{$c}")
643
+ end
644
+
645
+ def find_project_dir_of_fn(fn)
646
+ pcomp = Pathname.new(fn).each_filename.to_a
647
+ parent_dirs = (0..(pcomp.size - 2)).collect { |x| "/" + pcomp[0..x].join("/") }.reverse
648
+ projdir = nil
649
+ for pdir in parent_dirs
650
+ candfn = "#{pdir}/.vma_project"
651
+ if File.exist?(candfn)
652
+ projdir = pdir
653
+ break
654
+ end
655
+ end
656
+ return projdir
657
+ end
658
+
659
+ def find_project_dir_of_cur_buffer()
660
+ # Find "project dir" of current file. If currently editing file in path "/foo/bar/baz/fn.txt" and file named "/foo/bar/.vma_project" exists, then dir /foo/bar is treated as project dir and subject to e.g. ack search.
661
+ pdir = nil
662
+ if $buffer.fname
663
+ pdir = find_project_dir_of_fn($buffer.fname)
664
+ end
665
+ # puts "Proj dir of current file: #{pdir}"
666
+ return pdir
667
+ end