Top Level Namespace

Defined Under Namespace

Modules: Differ, Gtk, Gui, Kernel, Vimamsa Classes: Ack, Action, ActionList, Audio, Autocomplete, Buffer, BufferList, BufferManager, Clipboard, Conf, ConfId, Converter, DelayExecutioner, EasyJump, Editor, EditorTests, Encrypt, File, FileContentSearch, FileFinder, FileHistory, FileManager, FileSelector, Grep, HSafe, Hook, HookItem, KeyBindingTree, LangSrv, Macro, OneInputAction, PopupFormGenerator, ResizableImage, Search, SelectUpdateWindow, State, StringIndex, VMAgui, VSourceView

Constant Summary collapse

VOWELS =
%w(a e i o u)
CONSONANTS =
%w(b c d f g h j k l m n p q r s t v w x y z)
LOREM_IPSUM =
"
   Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis sollicitudin mauris. Integer in mauris eu nibh euismod gravida. Duis ac tellus et risus vulputate vehicula. Donec lobortis risus a elit. Etiam tempor. Ut ullamcorper, ligula eu tempor congue, eros est euismod turpis, id tincidunt sapien risus a quam. Maecenas fermentum consequat mi. Donec fermentum. Pellentesque malesuada nulla a mi. Duis sapien sem, aliquet nec, commodo eget, consequat quis, neque. Aliquam faucibus, elit ut dictum aliquet, felis nisl adipiscing sapien, sed malesuada diam lacus eget erat. Cras mollis scelerisque nunc. Nullam arcu. Aliquam consequat. Curabitur augue lorem, dapibus quis, laoreet et, pretium ac, nisi. Aenean magna nisl, mollis quis, molestie eu, feugiat in, orci. In hac habitasse platea dictumst."
JABBERWOCKY =
"
  ’Twas brillig, and the slithy toves
      Did gyre and gimble in the wabe:
All mimsy were the borogoves,
      And the mome raths outgrabe.

“Beware the Jabberwock, my son!
      The jaws that bite, the claws that catch!
Beware the Jubjub bird, and shun
      The frumious Bandersnatch!”

He took his vorpal sword in hand;
      Long time the manxome foe he sought—
So rested he by the Tumtum tree
      And stood awhile in thought.

And, as in uffish thought he stood,
      The Jabberwock, with eyes of flame,
Came whiffling through the tulgey wood,
      And burbled as it came!

One, two! One, two! And through and through
      The vorpal blade went snicker-snack!
He left it dead, and with its head
      He went galumphing back.

“And hast thou slain the Jabberwock?
      Come to my arms, my beamish boy!
O frabjous day! Callooh! Callay!”
      He chortled in his joy.

’Twas brillig, and the slithy toves
      Did gyre and gimble in the wabe:
All mimsy were the borogoves,
      And the mome raths outgrabe.
"
GUESS_ENCODING_ORDER =
[
  Encoding::US_ASCII,
  Encoding::UTF_8,
  Encoding::ISO_8859_1,
  Encoding::Shift_JIS,
  Encoding::EUC_JP,
  Encoding::EucJP_ms,
  Encoding::Big5,
  Encoding::UTF_16BE,
  Encoding::UTF_16LE,
  Encoding::UTF_32BE,
  Encoding::UTF_32LE,
  Encoding::CP949,
  Encoding::Emacs_Mule,
  Encoding::EUC_KR,
  Encoding::EUC_TW,
  Encoding::GB18030,
  Encoding::GBK,
  Encoding::Stateless_ISO_2022_JP,
  Encoding::CP51932,
  Encoding::EUC_CN,
  Encoding::GB12345,
  Encoding::Windows_31J,
  Encoding::MacJapanese,
  Encoding::UTF8_MAC,
  Encoding::BINARY,
]
NEXT_MARK =
1001
PREVIOUS_MARK =
1002
BACKWARD =
1003
FORWARD =
1004
BEFORE =
1005
AFTER =
1006
SELECTION =
1007
FORWARD_CHAR =
2001
BACKWARD_CHAR =
2002
FORWARD_LINE =
2003
BACKWARD_LINE =
2004
CURRENT_CHAR_FORWARD =
2005
CURRENT_CHAR_BACKWARD =
2006
START_OF_BUFFER =
2007
END_OF_BUFFER =
2008
END_OF_LINE =
2011
BEGINNING_OF_LINE =
2012
WORD_START =
2013
WORD_END =
2014
FIRST_NON_WHITESPACE =
2014
INSERT =
2
DELETE =
3001
REPLACE =
3002
KEY_PRESS =
6
KEY_RELEASE =

QEvent::KeyRelease

7
LSP =
LanguageServer::Protocol

Instance Method Summary collapse

Instance Method Details

#_insert_move(op) ⇒ Object



24
25
26
27
28
29
30
31
32
# File 'lib/vimamsa/key_bindings_vimlike.rb', line 24

def _insert_move(op)
  if op == :pagedown
    vma.gui.page_down
  elsif op == :pageup
    vma.gui.page_up
  else
    buf.move(op)
  end
end

#_quitObject



285
286
287
# File 'lib/vimamsa/editor.rb', line 285

def _quit()
  vma.shutdown
end

#add_keys(keywords, to_add) ⇒ Object



695
696
697
698
699
# File 'lib/vimamsa/key_binding_tree.rb', line 695

def add_keys(keywords, to_add)
  to_add.each { |key, value|
    bindkey(key, value, keywords: keywords)
  }
end

#assert_binary_exists(bin) ⇒ Object



288
289
290
291
292
# File 'lib/vimamsa/util.rb', line 288

def assert_binary_exists(bin)
  if which(bin).nil?
    raise "Binary #{bin} doesn't exist"
  end
end

#backup_all_buffersObject



1620
1621
1622
1623
1624
1625
# File 'lib/vimamsa/buffer.rb', line 1620

def backup_all_buffers()
  for b in bufs
    b.backup
  end
  message("Backup all buffers")
end

#bindkey(key, action, keywords: "") ⇒ Object



691
692
693
# File 'lib/vimamsa/key_binding_tree.rb', line 691

def bindkey(key, action, keywords: "")
  vma.kbd.bindkey(key, action, keywords: keywords)
end

#bufObject

Return currently active buffer



31
32
33
# File 'lib/vimamsa/main.rb', line 31

def buf()
  return vma.buf
end

#buf_replace(search_str, replace_str) ⇒ Object



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/vimamsa/search_replace.rb', line 204

def buf_replace(search_str, replace_str)
  if vma.buf.visual_mode?
    r = vma.buf.get_visual_mode_range
    txt = vma.buf[r]
    txt.gsub!(search_str, replace_str)
    vma.buf.replace_range(r, txt)
    vma.buf.end_visual_mode
  else
    repbuf = vma.buf.to_s.clone
    repbuf.gsub!(search_str, replace_str)
    tmppos = vma.buf.pos
    if repbuf == vma.buf.to_s.clone
      message("NO CHANGE. Replacing #{search_str} with #{replace_str}.")
    else
      vma.buf.set_content(repbuf)
      vma.buf.set_pos(tmppos)
      message("Replacing #{search_str} with #{replace_str}.")
    end
  end
end

#buf_replace_string(instr) ⇒ Object

Requires instr in form “FROM/TO” Replaces all occurences of FROM with TO



227
228
229
230
231
232
233
234
235
# File 'lib/vimamsa/search_replace.rb', line 227

def buf_replace_string(instr)
  # puts "buf_replace_string(instr=#{instr})"

  a = instr.split("/")
  if a.size != 2
    return
  end
  buf_replace(a[0], a[1])
end

#buflistObject



43
44
45
# File 'lib/vimamsa/main.rb', line 43

def buflist()
  return vma.buffers
end

#bufsObject



39
40
41
# File 'lib/vimamsa/main.rb', line 39

def bufs()
  return vma.buffers
end

#call_action(id) ⇒ Object

TODO: remove?



32
33
34
# File 'lib/vimamsa/actions.rb', line 32

def call_action(id)
  vma.actions.call(id)
end

#can_save_to_directory?(dpath) ⇒ Boolean

Returns:

  • (Boolean)


338
339
340
341
342
343
# File 'lib/vimamsa/editor.rb', line 338

def can_save_to_directory?(dpath)
  return false if !File.exist?(dpath)
  return false if !File.directory?(dpath)
  return false if !File.writable?(dpath)
  return true
end

#center_on_current_lineObject



94
95
96
97
98
99
100
101
102
# File 'lib/vimamsa/gui.rb', line 94

def center_on_current_line()
  b = $view.buffer
  iter = b.get_iter_at(:offset => b.cursor_position)
  within_margin = 0.0 #margin as a [0.0,0.5) fraction of screen size
  use_align = true
  xalign = 0.0 #0.0=top 1.0=bottom, 0.5=center
  yalign = 0.5
  $view.scroll_to_iter(iter, within_margin, use_align, xalign, yalign)
end

#cnfObject



102
103
104
# File 'lib/vimamsa/conf.rb', line 102

def cnf()
  return $vimamsa_conf
end

#command_to_bufObject



31
32
33
34
# File 'lib/vimamsa/terminal.rb', line 31

def command_to_buf
  callback = method("command_to_buf_callback")
  gui_one_input_action("Execute command in shell, output to buffer", "Command:", "Execute", callback)
end

#command_to_buf_callback(cmd) ⇒ Object



23
24
25
26
27
# File 'lib/vimamsa/terminal.rb', line 23

def command_to_buf_callback(cmd)
  require "open3"
  stdout, stderr, status = Open3.capture3(cmd)
  b = create_new_buffer(stdout, cmd)
end

#crash(message, e = nil) ⇒ Object



49
50
51
52
53
54
# File 'lib/vimamsa/debug.rb', line 49

def crash(message, e = nil)
  puts "FATAL ERROR:#{message}"
  puts caller().join("\n")
  # savedebug(message, e)
  _quit()
end

#create_new_buffer(file_contents = "\n", prefix = "buf", setcurrent = true) ⇒ Object



492
493
494
495
496
497
498
499
500
# File 'lib/vimamsa/editor.rb', line 492

def create_new_buffer(file_contents = "\n", prefix = "buf", setcurrent = true)
  debug "NEW BUFFER CREATED"
  buffer = Buffer.new(file_contents, nil, prefix)
  vma.buffers.add(buffer)
  vma.buffers.set_current_buffer_by_id(buffer.id) if setcurrent
  buffer.set_content(file_contents)

  return buffer
end

#create_new_file(filename = nil, file_contents = "\n") ⇒ Object



477
478
479
480
481
482
483
484
485
486
487
488
489
490
# File 'lib/vimamsa/editor.rb', line 477

def create_new_file(filename = nil, file_contents = "\n")
  buffer = Buffer.new(file_contents, filename)

  debug "NEW FILE CREATED: #{buffer.id}"
  vma.buffers.add(buffer)
  vma.kbd.set_mode_to_default
  vma.buffers.set_current_buffer_by_id(buffer.id)

  # Do set_content twice (once in Buffer.new) to force redraw and work around a bug
  # The bug: if switching a child of scrolledWindow to a textview with a file smaller than the window, it won't get drawn properly if in previous (larger) file the ScrolledWindow was scrolled down.
  buffer.set_content(file_contents)

  return buffer
end

#debug(message, severity = 1) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
# File 'lib/vimamsa/debug.rb', line 3

def debug(message, severity = 1)
  if cnf.debug?
    if severity > 1
      # Add red colour and bold for attention
      # https://en.wikipedia.org/wiki/ANSI_escape_code
      message = "\033[1;31m!!! \033[0m#{message}"
    end
    puts "[#{DateTime.now().strftime("%H:%M:%S")}] #{message}"
    $stdout.flush
  end
end

#debug_dump_clipboardObject



20
21
22
# File 'lib/vimamsa/debug.rb', line 20

def debug_dump_clipboard()
  puts vma.clipboard.inspect
end

#debug_dump_deltasObject



24
25
26
# File 'lib/vimamsa/debug.rb', line 24

def debug_dump_deltas()
  puts buf.edit_history.inspect
end

#debug_print_buffer(c) ⇒ Object



15
16
17
18
# File 'lib/vimamsa/debug.rb', line 15

def debug_print_buffer(c)
  puts buf.inspect
  puts buf
end

#decrypt_dialog(filename:, wrong_pass: false) ⇒ Object



3
4
5
6
7
8
# File 'lib/vimamsa/encrypt.rb', line 3

def decrypt_dialog(filename:, wrong_pass: false)
  callback = proc { |x| Encrypt.open(filename, x) }
  msg = ""
  msg = "\nWRONG PASSWORD!\n" if wrong_pass
  gui_one_input_action("Decrypt file \n #{filename}\n#{msg}", "Password:", "Decrypt", callback, { :hide => true })
end

#diff_bufferObject



372
373
374
375
376
377
378
379
380
381
382
383
384
385
# File 'lib/vimamsa/editor.rb', line 372

def diff_buffer()
  bufstr = ""
  orig_path = vma.buf.fname
  infile = Tempfile.new("out")
  infile = Tempfile.new("in")
  infile.write(vma.buf.to_s)
  infile.flush
  cmd = "diff -w '#{orig_path}' #{infile.path}"
  # debug cmd
  bufstr << run_cmd(cmd)
  # debug bufstr
  infile.close; infile.unlink
  create_new_file(nil, bufstr)
end

#draw_cursor_bug_workaroundObject



6
7
8
# File 'lib/vimamsa/util.rb', line 6

def draw_cursor_bug_workaround()
  DelayExecutioner.exec(id: :bug_workaround_draw_cursor, wait: 1.0, callable: proc { vma.gui.view.draw_cursor(); debug ":bug_workaround_draw_cursor"; false })
end

#e_move_backward_charObject



5
6
7
# File 'lib/vimamsa/key_actions.rb', line 5

def e_move_backward_char
  buf.move(BACKWARD_CHAR)
end

#e_move_forward_charObject



1
2
3
# File 'lib/vimamsa/key_actions.rb', line 1

def e_move_forward_char
  buf.move(FORWARD_CHAR)
end

#encrypt_cur_bufferObject



72
73
74
75
# File 'lib/vimamsa/encrypt.rb', line 72

def encrypt_cur_buffer()
  callback = proc { |x| encrypt_cur_buffer_callback(x) }
  gui_one_input_action("Encrypt", "Password:", "Encrypt", callback, { :hide => true })
end

#encrypt_cur_buffer_callback(password, b = nil) ⇒ Object



77
78
79
# File 'lib/vimamsa/encrypt.rb', line 77

def encrypt_cur_buffer_callback(password, b = nil)
  vma.buf.set_encrypted(password)
end

#end_profilerObject



16
17
18
19
20
# File 'lib/vimamsa/gui.rb', line 16

def end_profiler
  result = RubyProf.stop
  printer = RubyProf::FlatPrinter.new(result)
  printer.print(STDOUT)
end

#error(str) ⇒ Object



434
435
436
437
# File 'lib/vimamsa/editor.rb', line 434

def error(str)
  show_caller
  debug "#{caller[0]} ERROR: #{str}", 2
end

#exec_action(action) ⇒ Object



701
702
703
704
705
706
707
708
709
710
711
# File 'lib/vimamsa/key_binding_tree.rb', line 701

def exec_action(action)
  vma.kbd.last_action = vma.kbd.cur_action
  vma.kbd.cur_action = action
  if action.class == Symbol
    return call_action(action)
  elsif action.class == Proc
    return action.call
  else
    return eval(action)
  end
end

#exec_cmd(bin_name, arg1 = nil, arg2 = nil, arg3 = nil, arg4 = nil, arg5 = nil) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/vimamsa/util.rb', line 128

def exec_cmd(bin_name, arg1 = nil, arg2 = nil, arg3 = nil, arg4 = nil, arg5 = nil)
  assert_binary_exists(bin_name)
  if !arg5.nil?
    p = Open3.popen2(bin_name, arg1, arg2, arg3, arg4, arg5)
  elsif !arg4.nil?
    p = Open3.popen2(bin_name, arg1, arg2, arg3, arg4)
  elsif !arg3.nil?
    p = Open3.popen2(bin_name, arg1, arg2, arg3)
  elsif !arg2.nil?
    p = Open3.popen2(bin_name, arg1, arg2)
  elsif !arg1.nil?
    p = Open3.popen2(bin_name, arg1)
  else
    p = Open3.popen2(bin_name)
  end

  ret_str = p[1].read
  return ret_str
end

#exec_in_terminal(cmd, autoclose = false) ⇒ Object



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/vimamsa/terminal.rb', line 2

def exec_in_terminal(cmd, autoclose = false)
  # debug "CMD:#{cmd}"

  # global to prevent garbage collect unlink
  $initf = Tempfile.new("bashinit")
  # debug $initf.path
  $initf.write(cmd)
  if autoclose
    $initf.write("\nsleep 10; exit;\n")
    $initf.write("rm #{$initf.path}\n")
  else
    $initf.write("rm #{$initf.path}\n")
    $initf.write("\nexec bash\n")
  end
  $initf.close
  # PTY.spawn("gnome-terminal", "--tab", "--", "bash", "-i", $initf.path, "-c", "exec bash")
  # fork { exec "gnome-terminal", "--tab", "--", "bash", "-i", $initf.path, "-c", "exec bash" }
  # Just another execution
  fork { exec "gnome-terminal", "--tab", "--", "bash", "-i", $initf.path, "-c", "exec bash" }
end

#execute_command(input_str) ⇒ Object



391
392
393
394
395
396
397
398
399
# File 'lib/vimamsa/editor.rb', line 391

def execute_command(input_str)
  begin
    out_str = eval(input_str, TOPLEVEL_BINDING) #TODO: Other binding?
    $minibuffer.clear
    $minibuffer << out_str.to_s #TODO: segfaults, why?
  rescue SyntaxError
    debug("SYNTAX ERROR with eval cmd #{action}: " + $!.to_s)
  end
end

#execute_search(input_str) ⇒ Object



2
3
4
5
6
7
# File 'lib/vimamsa/search.rb', line 2

def execute_search(input_str)
  $search = Search.new
  eval_str="execute_search(#{input_str.dump})"
  vma.macro.overwrite_current_action(eval_str)
  return $search.set(input_str, "simple", vma.buf)
end

#expand_if_existing(fpath) ⇒ Object



337
338
339
340
341
342
# File 'lib/vimamsa/util.rb', line 337

def expand_if_existing(fpath)
  return nil if fpath.class != String
  fpath = File.expand_path(fpath)
  fpath = nil if !File.exist?(fpath)
  return fpath
end

#fatal_error(msg) ⇒ Object



289
290
291
292
# File 'lib/vimamsa/editor.rb', line 289

def fatal_error(msg)
  debug msg
  exit!
end

#file_is_text_file(fpath) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/vimamsa/util.rb', line 78

def file_is_text_file(fpath)
  debug "file_is_text_file(#{fpath})"
  fpath = File.expand_path(fpath)
  return false if !File.exist?(fpath)
  return false if !File.file?(fpath)

  if File.size(fpath) < 1000e3 #smaler than 1MB
    str = IO.read(fpath)
    str.force_encoding("UTF-8")
    debug "Small file with valid utf-8"
    return true if str.valid_encoding?
  end

  #TODO: not sure if needed
  r = exec_cmd("file", fpath)
  return true if r.match(/UTF-8.*text/)
  return true if r.match(/ASCII.*text/)
  return false
end

#file_mime_type(fpath) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/vimamsa/util.rb', line 63

def file_mime_type(fpath)
  fpath = File.expand_path(fpath)
  return nil if !File.readable?(fpath)
  r = exec_cmd("file", "--mime-type", "--mime-encoding", fpath)
  return nil if r.class != String
  return nil if r.size < 2
  m = r.match(".*:\s*(.*)")
  b = m[1].match(/(.*);/)
  c = m[1].match(/charset=(.*)/)
  return nil if b.nil? or c.nil?
  mimetype = b[1]
  charset = c[1]
  return [mimetype, charset]
end

#file_saveas(filename) ⇒ Object



294
295
296
# File 'lib/vimamsa/editor.rb', line 294

def file_saveas(filename)
  buf.save_as_callback(filename)
end

#filter_buffer(buf) ⇒ Object



502
503
504
505
506
507
508
509
510
511
512
# File 'lib/vimamsa/editor.rb', line 502

def filter_buffer(buf)
  i = 0
  while i < buf.size
    if buf[i].ord == 160
      buf[i] = " "
      #TODO: hack. fix properly
    end
    i += 1
  end
  return buf
end

#find_project_dir_of_cur_bufferObject



641
642
643
644
645
646
647
648
649
# File 'lib/vimamsa/editor.rb', line 641

def find_project_dir_of_cur_buffer()
  # 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.
  pdir = nil
  if vma.buf.fname
    pdir = find_project_dir_of_fn(vma.buf.fname)
  end
  # debug "Proj dir of current file: #{pdir}"
  return pdir
end

#find_project_dir_of_fn(fn) ⇒ Object



622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
# File 'lib/vimamsa/editor.rb', line 622

def find_project_dir_of_fn(fn)
  pcomp = Pathname.new(fn).each_filename.to_a
  parent_dirs = (0..(pcomp.size - 2)).collect { |x| "/" + pcomp[0..x].join("/") }.reverse
  projdir = nil
  for pdir in parent_dirs
    candfns = []
    candfns << "#{pdir}/.vma_project"
    candfns << "#{pdir}/.git"
    for candfn in candfns
      if File.exist?(candfn)
        projdir = pdir
        break
      end
    end
    return projdir if !projdir.nil?
  end
  return projdir
end

#fuzzy_filter(search_str, list, maxfinds) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/vimamsa/file_history.rb', line 61

def fuzzy_filter(search_str, list, maxfinds)
  h = {}
  scores = Parallel.map(list, in_threads: 8) do |l|
    [l, srn_dst(search_str, l)]
  end
  for s in scores
    h[s[0]] = s[1] if s[1] > 0
  end
  h = h.sort_by { |k, v| -v }
  h = h[0..maxfinds]
  # h.map do |i, d|
  # puts "D:#{d} #{i}"
  # end
  return h
end

#generate_password(length) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/vimamsa/util.rb', line 35

def generate_password(length)
  password = ""
  while password.size < length
    i = password.size + 1
    if i.even?
      char = CONSONANTS.sample
    else
      char = VOWELS.sample
    end
    char.upcase! if rand < 0.2
    password << char
    password << (1..10).to_a.sample.to_s if rand < 0.25
  end
  password
end

#generate_password_to_buf(length) ⇒ Object



51
52
53
54
# File 'lib/vimamsa/util.rb', line 51

def generate_password_to_buf(length)
  passw = generate_password(length)
  vma.buf.insert_txt(passw)
end

#get(id) ⇒ Object



24
25
26
27
28
29
30
31
32
33
# File 'lib/vimamsa/conf.rb', line 24

def get(id)
  id = id.to_a
  a = $confh
  for x in id
    return nil if a[x].nil?
    return nil if a.empty?
    a = a[x]
  end
  return a
end

#get_dot_path(sfx) ⇒ Object



603
604
605
606
607
608
# File 'lib/vimamsa/editor.rb', line 603

def get_dot_path(sfx)
  dot_dir = File.expand_path("~/.config/vimamsa")
  Dir.mkdir(dot_dir) unless File.exist?(dot_dir)
  dpath = "#{dot_dir}/#{sfx}"
  return dpath
end

#get_file_line_pointer(s) ⇒ Object



610
611
612
613
614
615
616
617
618
619
620
# File 'lib/vimamsa/editor.rb', line 610

def get_file_line_pointer(s)
  #"/code/vimamsa/lib/vimamsa/buffer_select.rb:31:def"
  #    m = s.match(/(~[a-z]*)?\/.*\//)
  m = s.match(/((~[a-z]*)?\/.*\/\S+):(c?)(\d+)/)
  if m != nil
    if File.exist?(File.expand_path(m[1]))
      return [m[1], m[4].to_i, m[3]]
    end
  end
  return nil
end

#get_visible_areaObject



104
105
106
107
108
109
110
# File 'lib/vimamsa/gui.rb', line 104

def get_visible_area()
  view = $view
  vr = view.visible_rect
  startpos = view.get_iter_at_position_raw(vr.x, vr.y)[1].offset
  endpos = view.get_iter_at_position_raw(vr.x + vr.width, vr.y + vr.height)[1].offset
  return [startpos, endpos]
end

#group_by_folder(list) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/vimamsa/ack.rb', line 98

def group_by_folder(list)
  bh = {}
  for b in list
    fpath = b[:fpath]
    if !fpath.nil?
      bname = File.basename(b[:fpath])
      dname = File.dirname(b[:fpath])
    else
      #TODO
    end
    bh[dname] ||= {}
    bh[dname][:files] ||= []
    bh[dname][:files] << { bname: bname, nfo: b }
  end
  arr = []

  for k in bh.keys.sort
    tp = tilde_path(k)
    arr << { type: :dir, path: tp }
    for f in bh[k][:files].sort_by { |x| x[:bname] }
      arr << { type: :file, bname: f[:bname], nfo: f[:nfo] }
    end
  end
  return arr
end

#gui_ackObject



84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/vimamsa/ack.rb', line 84

def gui_ack()
  search_paths = vma.get_content_search_paths.join("<br/>")

  nfo = "<span size='x-large'>Search contents of all files using ack</span>
Will search the following directories:
#{search_paths}
  
<span>Note: Directory determined automatically as the first parent directory of a last accessed file which includes file/dir named .git or .vma_project. Or, if not found, the last accessed directory.
</span>"

  callback = proc { |x| Ack.new.ack_buffer(x) }
  gui_one_input_action(nfo, "Search:", "search", callback)
end

#gui_add_image(imgpath, pos) ⇒ Object



162
163
# File 'lib/vimamsa/gui.rb', line 162

def gui_add_image(imgpath, pos)
end

#gui_create_buffer(id, bufo) ⇒ Object

def page_down $view.signal_emit(“move-cursor”, Gtk::MovementStep.new(:PAGES), 1, false) return true end



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/vimamsa/gui.rb', line 122

def gui_create_buffer(id, bufo)
  debug "gui_create_buffer(#{id})"
  buf1 = GtkSource::Buffer.new()
  view = VSourceView.new(nil, bufo)

  view.register_signals()

  ssm = GtkSource::StyleSchemeManager.new
  ssm.set_search_path(ssm.search_path << ppath("styles/"))
  sty = ssm.get_scheme("molokai_edit")

  buf1.highlight_matching_brackets = true
  buf1.style_scheme = sty

  view.set_highlight_current_line(true)
  view.set_show_line_numbers(true)
  view.set_buffer(buf1)

  provider = Gtk::CssProvider.new

  provider.load(data: "textview { font-family: #{cnf.font.family!}; font-size: #{cnf.font.size!}pt; }")
  view.style_context.add_provider(provider)
  view.wrap_mode = :char

  view.set_tab_width(cnf.tab.width!)

  $vmag.buffers[id] = view
end

#gui_file_history_select_callback(search_str, idx) ⇒ Object



92
93
94
95
96
97
98
# File 'lib/vimamsa/file_history.rb', line 92

def gui_file_history_select_callback(search_str, idx)
  selected_file = $search_list[idx][0]

  debug "FILE HISTORY SELECT CALLBACK: s=#{search_str},i=#{idx}: #{selected_file}"
  gui_select_window_close(0)
  open_new_file(selected_file)
end

#gui_file_history_update_callback(search_str = "") ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/vimamsa/file_history.rb', line 77

def gui_file_history_update_callback(search_str = "")
  debug "gui_file_history_update_callback: #{search_str}"
  return [] if vma.fh.history.empty?
  $search_list = []
  files = vma.fh.history.keys.sort.collect { |x| [x, 0] }

  if (search_str.size > 1)
    files = fuzzy_filter(search_str, vma.fh.history.keys, 40)
  end

  $search_list = files
  ret = files.collect{|x|[x[0]]}
  return ret
end

#gui_file_saveas(dirpath) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/vimamsa/gui.rb', line 77

def gui_file_saveas(dirpath)
  dialog = Gtk::FileChooserDialog.new(:title => "Save as",
                                      :action => :save,
                                      :buttons => [["Save", :accept],
                                                   ["Cancel", :cancel]])
  dialog.set_current_folder(Gio::File.new_for_path(dirpath))
  dialog.signal_connect("response") do |dialog, response_id|
    if response_id == Gtk::ResponseType::ACCEPT
      file_saveas(dialog.file.parse_name)
    end
    dialog.destroy
  end

  dialog.modal = true
  dialog.show
end

#gui_find_macro_select_callback(search_str, idx) ⇒ Object



15
16
17
18
19
20
21
22
23
# File 'lib/vimamsa/macro.rb', line 15

def gui_find_macro_select_callback(search_str, idx)
  debug "gui_find_macro_select_callback"
  selected = $macro_search_list[idx]
  m = vma.macro.named_macros[selected[0]].clone
  debug "SELECTED MACRO:#{selected}, #{m}"
  id = vma.macro.last_macro
  vma.macro.recorded_macros[id] = m
  vma.macro.run_macro(id)
end

#gui_find_macro_update_callback(search_str = "") ⇒ Object



1
2
3
4
5
6
7
8
9
10
11
12
13
# File 'lib/vimamsa/macro.rb', line 1

def gui_find_macro_update_callback(search_str = "")
  debug "gui_find_macro_update_callback: #{search_str}"
  heystack = vma.macro.named_macros
  return [] if heystack.empty?
  $macro_search_list = []
  files = heystack.keys.sort.collect { |x| [x, 0] }

  if (search_str.size > 1)
    files = fuzzy_filter(search_str, heystack.keys, 40)
  end
  $macro_search_list = files
  return files
end

#gui_one_input_action(title, field_label, button_title, callback, opt = {}) ⇒ Object



172
173
174
175
176
# File 'lib/vimamsa/search_replace.rb', line 172

def gui_one_input_action(title, field_label, button_title, callback, opt = {})
  a = OneInputAction.new(nil, title, field_label, button_title, callback, opt)
  a.run
  return
end

#gui_open_file_dialog(dirpath) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/vimamsa/gui.rb', line 59

def gui_open_file_dialog(dirpath)
  dialog = Gtk::FileChooserDialog.new(:title => "Open file",
                                      :action => :open,
                                      :buttons => [["Open", :accept],
                                                   ["Cancel", :cancel]])
  dialog.set_current_folder(Gio::File.new_for_path(dirpath))

  dialog.signal_connect("response") do |dialog, response_id|
    if response_id == Gtk::ResponseType::ACCEPT
      open_new_file(dialog.file.parse_name)
    end
    dialog.destroy
  end

  dialog.modal = true
  dialog.show
end

#gui_remove_controllers(widget) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/vimamsa/gui.rb', line 41

def gui_remove_controllers(widget)
  clist = widget.observe_controllers
  to_remove = []
  (0..(clist.n_items - 1)).each { |x|
    ctr = clist.get_item(x)
    to_remove << ctr
  }
  if to_remove.size > 0
    # debug "Removing controllers:"
    # pp to_remove
    to_remove.each { |x|
      # To avoid GC. https://github.com/ruby-gnome/ruby-gnome/issues/15790
      $removed_controllers << x
      widget.remove_controller(x)
    }
  end
end

#gui_replace_callback(vals) ⇒ Object

def gui_replace_callback(search_str, replace_str)



179
180
181
182
183
184
185
# File 'lib/vimamsa/search_replace.rb', line 179

def gui_replace_callback(vals)
  search_str = vals["search"]
  replace_str = vals["replace"]
  debug "gui_replace_callback: #{search_str} => #{replace_str}"
  gui_select_window_close(0)
  buf_replace(search_str, replace_str)
end

#gui_search_replaceObject

Search and replace text via GUI interface



188
189
190
191
192
193
194
195
196
197
198
# File 'lib/vimamsa/search_replace.rb', line 188

def gui_search_replace()
  params = {}
  params["inputs"] = {}
  params["inputs"]["search"] = { :label => "Search", :type => :entry }
  params["inputs"]["replace"] = { :label => "Replace", :type => :entry }
  params["inputs"]["btn1"] = { :label => "Replace all", :type => :button }
  callback = proc { |x| gui_replace_callback(x) }

  params[:callback] = callback
  PopupFormGenerator.new(params).run
end

#gui_select_update_window(item_list, jump_keys, select_callback, update_callback, opt = {}) ⇒ Object



1
2
3
4
5
6
7
# File 'lib/vimamsa/gui_select_window.rb', line 1

def gui_select_update_window(item_list, jump_keys, select_callback, update_callback, opt = {})
  $selup = SelectUpdateWindow.new(nil, item_list, jump_keys, select_callback, update_callback, opt)
  $selup.run
  # opt fields:
  # :title
  # :desc
end

#gui_select_window_close(arg = nil) ⇒ Object

TODO:?



166
167
# File 'lib/vimamsa/gui.rb', line 166

def gui_select_window_close(arg = nil)
end

#gui_set_buffer_contents(id, txt) ⇒ Object



169
170
171
172
173
# File 'lib/vimamsa/gui.rb', line 169

def gui_set_buffer_contents(id, txt)
  debug "gui_set_buffer_contents(#{id}, txt)"
  # vma.gui.buffers[id].buffer.set_text(txt)
  vma.gui.buffers[id].set_content(txt)
end

#gui_set_current_buffer(id) ⇒ Object



180
181
182
183
# File 'lib/vimamsa/gui.rb', line 180

def gui_set_current_buffer(id)
  vma.gui.set_current_buffer(id)
  return
end

#gui_set_cursor_pos(id, pos) ⇒ Object

TODO: remove



176
177
178
# File 'lib/vimamsa/gui.rb', line 176

def gui_set_cursor_pos(id, pos)
  vma.buf.view.set_cursor_pos(pos)
end

#gui_set_file_lang(id, lname) ⇒ Object



151
152
153
154
155
156
157
158
159
160
# File 'lib/vimamsa/gui.rb', line 151

def gui_set_file_lang(id, lname)
  view = $vmag.buffers[id]
  lm = GtkSource::LanguageManager.new
  lang = nil
  lm.set_search_path(lm.search_path << ppath("lang/"))
  lang = lm.get_language(lname)

  view.buffer.language = lang
  view.buffer.highlight_syntax = true
end

#gui_set_window_title(wtitle, subtitle = "") ⇒ Object



185
186
187
188
189
190
# File 'lib/vimamsa/gui.rb', line 185

def gui_set_window_title(wtitle, subtitle = "")
  $vmag.window.title = wtitle
  # $vmag.subtitle.markup = "<span weight='ultrabold'>#{subtitle}</span>"
  $vmag.subtitle.markup = "<span weight='light' size='small'>#{subtitle}</span>"
  #  $vmag.window.titlebar.subtitle = subtitle #TODO:gtk4
end

#gui_sleep(t2) ⇒ Object

TODO: remove?



106
107
108
109
110
111
# File 'lib/vimamsa/debug.rb', line 106

def gui_sleep(t2)
  t1 = Time.now()
  while Time.now < t1 + t2
    sleep(0.02)
  end
end

#history_switch_backwardsObject



9
10
11
# File 'lib/vimamsa/key_actions.rb', line 9

def history_switch_backwards
  bufs.history_switch_backwards
end

#history_switch_forwardsObject



13
14
15
# File 'lib/vimamsa/key_actions.rb', line 13

def history_switch_forwards
  bufs.history_switch_forwards
end

#hookObject



35
36
37
# File 'lib/vimamsa/main.rb', line 35

def hook
  return vma.hook
end

#hook_drawObject



598
599
600
601
# File 'lib/vimamsa/editor.rb', line 598

def hook_draw()
  # TODO: as hook.register
  # easy_jump_draw()
end

#hpt_check_cur_word(w) ⇒ Object



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/vimamsa/hyper_plain_text.rb', line 1

def hpt_check_cur_word(w)
  debug "check_cur_word(w)"
  m = w.match(/⟦((audio|img):)?(.*)⟧/)
  if m
    fpfx = m[3]
    if vma.buf.fname
      dn = File.dirname(vma.buf.fname)

      fcands = []
      if fpfx[0] != "/" and fpfx[0] != "~"
        fcands << "#{dn}/#{fpfx}"
        fcands << "#{dn}/#{fpfx}.txt"
      end
      fcands << File.expand_path("#{fpfx}")
      fcands << File.expand_path("#{fpfx}.txt")

      fn = nil

      for fc in fcands
        if File.exist?(fc)
          fn = fc
          break
        end
      end

      if fn
        if m[2] == "audio"
          # Thread.new { Audio.play(fn) }
          Audio.play(fn) if cnf.audio.enabled?
        else
          if !file_is_text_file(fn)
            message "Not text file #{fn}"
            return nil
          end
          message "HPT opening file #{fn}"
          return fn
        end
        # open_existing_file(fn)
        # return true
      else
        message "File not found: #{fpfx}"
        newfn = fcands[0]
        if File.extname(newfn) == ""
          newfn = fcands[1]
        end
         Gui.confirm("File does not exist. Create a new file? \r #{newfn}",
                    proc{hpt_create_new_file(newfn)})
                   
      end
    end
  end
  return nil
end

#hpt_create_new_file(fn) ⇒ Object



56
57
58
# File 'lib/vimamsa/hyper_plain_text.rb', line 56

def hpt_create_new_file(fn)
  create_new_file(fn)
end

#hpt_scan_audio(bf = nil) ⇒ Object

Scan audio files inserted with ⟦audio:filepath⟧ syntax TODO: merge code with hpt_scan_images



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/vimamsa/hyper_plain_text.rb', line 78

def hpt_scan_audio(bf = nil)
  bf = buf() if bf.nil?
  return if bf.nil?
  return if !bf.fname
  return if !bf.fname.match(/.*txt$/)
  imgpos = scan_indexes(bf, /⟦audio:.+?⟧/)
  imgtags = bf.scan(/(⟦audio:(.+?)⟧)/)
  c = 0
  imgpos.each.with_index { |x, i|
    a = imgpos[i]
    t = imgtags[i]
    insert_pos = a + t[0].size + c
    fn = t[1]
    imgfn = translate_path(fn, bf)
    next if !File.exist?(imgfn)
    # Show as image in gui, handle as empty space in txt file

    if bf[insert_pos..(insert_pos + 2)] != "\n \n"
      bf.insert_txt_at("\n \n", insert_pos)
      bf.view.handle_deltas
      c += 3
    end
    bf.add_audio(imgfn, insert_pos + 1)
  }
  # vma.gui.delex.run #TODO:gtk4
end

#hpt_scan_images(bf = nil) ⇒ Object

Scan images inserted with ⟦img:filepath⟧ syntax



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/vimamsa/hyper_plain_text.rb', line 106

def hpt_scan_images(bf = nil)
  bf = buf() if bf.nil?
  return if bf.nil?
  return if !bf.fname
  return if !bf.fname.match(/.*txt$/)
  imgpos = scan_indexes(bf, /⟦img:.+?⟧/)
  imgtags = bf.scan(/(⟦img:(.+?)⟧)/)
  c = 0
  imgpos.each.with_index { |x, i|
    a = imgpos[i]
    t = imgtags[i]
    insert_pos = a + t[0].size + c
    fn = t[1]
    imgfn = translate_path(fn, bf)
    next if !File.exist?(imgfn)
    # Show as image in gui, handle as empty space in txt file

    if bf[insert_pos..(insert_pos + 2)] != "\n \n"
      bf.insert_txt_at("\n \n", insert_pos)
      bf.view.handle_deltas
      c += 3
    end
    bf.add_image(imgfn, insert_pos + 1)
  }

  # Need to scale after buffer loaded
  run_as_idle proc { vma.gui.scale_all_images }

  # vma.gui.delex.run #TODO:gtk4
end

#insert_move(op) ⇒ Object



39
40
41
42
# File 'lib/vimamsa/key_bindings_vimlike.rb', line 39

def insert_move(op)
  buf.end_selection
  _insert_move(op)
end

#insert_select_move(op) ⇒ Object



34
35
36
37
# File 'lib/vimamsa/key_bindings_vimlike.rb', line 34

def insert_select_move(op)
  buf.continue_selection
  _insert_move(op)
end

#invoke_commandObject



387
388
389
# File 'lib/vimamsa/editor.rb', line 387

def invoke_command()
  start_minibuffer_cmd("", "", :execute_command)
end

#invoke_replaceObject



200
201
202
# File 'lib/vimamsa/search_replace.rb', line 200

def invoke_replace()
  start_minibuffer_cmd("", "", :buf_replace_string)
end

#invoke_searchObject



9
10
11
12
13
14
# File 'lib/vimamsa/search.rb', line 9

def invoke_search()
  nfo = ""
  
  callback = proc{|x| execute_search(x)}
  gui_one_input_action(nfo, "Search:", "search", callback)
end

#is_command_modeObject



21
22
23
24
# File 'lib/vimamsa/key_actions.rb', line 21

def is_command_mode()
  return true if vma.kbd.mode_root_state.to_s() == "C"
  return false
end

#is_existing_file(s) ⇒ Object



352
353
354
355
356
357
358
# File 'lib/vimamsa/util.rb', line 352

def is_existing_file(s)
  return false if !s
  if is_path(s) and File.exist?(File.expand_path(s))
    return true
  end
  return false
end

#is_image_file(fpath) ⇒ Object



371
372
373
374
375
376
377
378
379
380
381
# File 'lib/vimamsa/util.rb', line 371

def is_image_file(fpath)
  return false if !File.exist?(fpath)
  # return false if !fpath.match(/.(jpg|jpeg|png)$/i)
  mime = file_mime_type(fpath)
  if !mime.nil?
    if mime[0].match(/image\//)
      return true
    end
  end
  return false
end

#is_path(s) ⇒ Object

def is_text_file(fpath) return false if !File.exist?(fpath) return false if !fpath.match(/.(txt|cpp|h|rb|c|php|java|py)$/i) #TODO: check contents of file return true end



390
391
392
393
394
395
396
# File 'lib/vimamsa/util.rb', line 390

def is_path(s)
  m = s.match(/(~[a-z]*)?\/.*\//)
  if m != nil
    return true
  end
  return false
end

#is_path_writable(fpath) ⇒ Object



1612
1613
1614
1615
1616
1617
1618
# File 'lib/vimamsa/buffer.rb', line 1612

def is_path_writable(fpath)
  r = false
  if fpath.class == String
    r = true if File.writable?(Pathname.new(fpath).dirname)
  end
  return r
end

#is_url(s) ⇒ Object



333
334
335
# File 'lib/vimamsa/util.rb', line 333

def is_url(s)
  return s.match(/(https?|file):\/\/.*/) != nil
end

#is_visual_modeObject



26
27
28
29
# File 'lib/vimamsa/key_actions.rb', line 26

def is_visual_mode()
  return 1 if vma.kbd.mode_root_state.to_s() == "V"
  return 0
end

#iterate_gui_main_loopObject



7
8
9
# File 'lib/vimamsa/gui.rb', line 7

def iterate_gui_main_loop
  GLib::MainContext.default.iteration(true)
end

#jump_to_file(filename, tnum = nil, charn = nil) ⇒ Object



534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
# File 'lib/vimamsa/editor.rb', line 534

def jump_to_file(filename, tnum = nil, charn = nil)
  b = open_new_file(filename)
  return if b.nil?
  # debug "open_new_file #{filename}, #{tnum} = nil, #{charn}",2

  # Link to character position
  if !charn.nil?
    if charn == "c"
      b.jump_to_pos(tnum) # tnum=character position
      center_on_current_line
      return
    end
  end

  # Link to line
  if !tnum.nil?
    b.jump_to_line(tnum) # tnum=line position
    center_on_current_line
    return
  end
end

#jump_to_next_editObject



17
18
19
# File 'lib/vimamsa/key_actions.rb', line 17

def jump_to_next_edit
  buf.jump_to_next_edit
end

#load_buffer(fname) ⇒ Object



514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
# File 'lib/vimamsa/editor.rb', line 514

def load_buffer(fname)
  # If file already open in existing buffer
  existing_buffer = vma.buffers.get_buffer_by_filename(fname)
  if existing_buffer != nil
    vma.buffers.add_buf_to_history(existing_buffer)
    return
  end
  return if !File.exist?(fname)
  debug("LOAD BUFFER: #{fname}")
  buffer = Buffer.new(read_file("", fname), fname)
  # gui_set_current_buffer(buffer.id)
  buffer.set_active
  debug("DONE LOAD: #{fname}")
  #buf = filter_buffer(buffer)
  #    debug("END FILTER: #{fname}")
  vma.buffers << buffer
  #$buffer_history << vma.buffers.size - 1
  return buffer
end

#load_buffer_listObject



10
11
12
13
14
15
16
17
18
19
20
# File 'lib/vimamsa/buffer_list.rb', line 10

def load_buffer_list()
  message("Load buffer list")
  buffn = get_dot_path("buffers.txt")
  return if !File.exist?(buffn)
  bufstr = IO.read(buffn)
  bufl = eval(bufstr)
  debug bufl
  for b in bufl
    load_buffer(b) if b != nil and File.file?(b)
  end
end

#log_error(message) ⇒ Object



35
36
37
38
39
40
41
42
# File 'lib/vimamsa/debug.rb', line 35

def log_error(message)
  puts "====== ERROR ====="
  puts caller[0]
  puts message
  puts "=================="
  $errors << [message, caller]
  #TODO
end

#log_message(message, vlevel = 1) ⇒ Object



30
31
32
33
# File 'lib/vimamsa/debug.rb', line 30

def log_message(message, vlevel = 1)
  puts message if conf("log.verbose") >= vlevel
  $log_messages << message
end

#macro_test(macro, correct_hex, runmacro = true) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/vimamsa/tests.rb', line 129

def macro_test(macro, correct_hex, runmacro = true)
  b = create_new_buffer(file_contents = "\n", prefix = "buf", setcurrent = true)
  b.insert_txt(JABBERWOCKY)
  b.insert_txt(LOREM_IPSUM)
  b.insert_txt(LOREM_IPSUM)

  macro_r = true
  if runmacro
    macro_r = vma.macro.run_actions(macro)
  end

  hex = Digest::SHA2.hexdigest b.to_s
  conds = [hex == correct_hex,
           macro_r == true]
  # debug conds
  debug hex

  if conds.include?(false)
    return false
  else
    return true
  end
end

#message(s) ⇒ Object



439
440
441
442
443
444
445
446
447
# File 'lib/vimamsa/editor.rb', line 439

def message(s)
  s = "[#{DateTime.now().strftime("%H:%M")}] #{s}"
  debug s

  $vmag.add_to_minibuf(s)
  # $minibuffer = Buffer.new(s, "")
  # $minibuffer[0..-1] = s # TODO
  #render_minibuffer
end

#minibuffer_cancelObject



408
409
410
411
412
413
# File 'lib/vimamsa/editor.rb', line 408

def minibuffer_cancel()
  debug "minibuffer_cancel"
  vma.kbd.set_mode(:command)
  minibuffer_input = $minibuffer.to_s[0..-2]
  # $minibuffer.call_func.call('')
end

#minibuffer_deleteObject

def readchar_new_char© $input_char_call_func.call© end



430
431
432
# File 'lib/vimamsa/editor.rb', line 430

def minibuffer_delete()
  $minibuffer.delete(BACKWARD_CHAR)
end

#minibuffer_endObject



401
402
403
404
405
406
# File 'lib/vimamsa/editor.rb', line 401

def minibuffer_end()
  debug "minibuffer_end"
  vma.kbd.set_mode(:command)
  minibuffer_input = $minibuffer.to_s[0..-2]
  return $minibuffer.call_func.call(minibuffer_input)
end

#minibuffer_new_char(c) ⇒ Object



415
416
417
418
419
420
421
422
423
424
# File 'lib/vimamsa/editor.rb', line 415

def minibuffer_new_char(c)
  if c == "\r"
    raise "Should not come here"
    debug "MINIBUFFER END"
  else
    $minibuffer.insert_txt(c)
    debug "MINIBUFFER: #{c}"
  end
  #vma.buf = $minibuffer
end

#missing_callfuncObject



27
28
29
# File 'lib/vimamsa/actions.rb', line 27

def missing_callfunc
  debug "missing_callfunc"
end

#mkdir_if_not_exists(_dirpath) ⇒ Object



166
167
168
169
# File 'lib/vimamsa/util.rb', line 166

def mkdir_if_not_exists(_dirpath)
  dirpath = File.expand_path(_dirpath)
  Dir.mkdir(dirpath) unless File.exist?(dirpath)
end

#open_existing_file(filename) ⇒ Object

TODO: needed?



557
558
559
# File 'lib/vimamsa/editor.rb', line 557

def open_existing_file(filename)
  open_new_file(filename)
end

#open_file_dialogObject



298
299
300
301
302
# File 'lib/vimamsa/editor.rb', line 298

def open_file_dialog()
  path = ""
  path = vma.buf.fname if vma.buf.fname
  gui_open_file_dialog(File.dirname(path))
end

#open_new_file(filename, file_contents = "") ⇒ Object



561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
# File 'lib/vimamsa/editor.rb', line 561

def open_new_file(filename, file_contents = "")
  #TODO: expand path
  filename = File.expand_path(filename)
  b = vma.buffers.get_buffer_by_filename(filename)
  # File is already opened to existing buffer
  if b != nil
    message "Switching to: #{filename}"
    bu = vma.buffers.set_current_buffer(b)
  else
    if !is_path_writable(filename)
      message("Path #{filename} cannot be written to")
      return false
    elsif !File.exist?(filename)
      message("File #{filename} does not exist")
      return false
    elsif !file_is_text_file(filename)
      message("File #{filename} does not contain text")
      return false
    end
    if Encrypt.is_encrypted?(filename)
      decrypt_dialog(filename: filename)
      return nil
    end
    message "New file opened: #{filename}"
    fname = filename
    bu = load_buffer(fname)
    vma.buffers.set_current_buffer_by_id(bu.id)
  end
  return bu
end

#open_url(url) ⇒ Object



111
112
113
# File 'lib/vimamsa/util.rb', line 111

def open_url(url)
  system("xdg-open", url)
end

#open_with_default_program(url) ⇒ Object



115
116
117
# File 'lib/vimamsa/util.rb', line 115

def open_with_default_program(url)
  system("xdg-open", url)
end

#pipe_to_external(program, text) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/vimamsa/util.rb', line 148

def pipe_to_external(program, text)
  # Open a pipe to the external program
  IO.popen(program, "r+") do |pipe|
    # Send the text to the program
    pipe.write(text)
    pipe.close_write # Close the write end to signal EOF to the program
    # Read and return the output from the program
    output = pipe.read
    return output
  end
rescue Errno::ENOENT
  puts "Error: The program '#{program}' was not found."
  nil
rescue => e
  puts "An error occurred: #{e.message}"
  nil
end

#ppath(s) ⇒ Object



344
345
346
347
348
349
350
# File 'lib/vimamsa/util.rb', line 344

def ppath(s)
  selfpath = __FILE__
  selfpath = File.readlink(selfpath) if File.lstat(selfpath).symlink?
  scriptdir = File.expand_path(File.dirname(selfpath))
  p = "#{scriptdir}/../../#{s}"
  return File.expand_path(p)
end

#read_file(text, path) ⇒ Object



294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
# File 'lib/vimamsa/util.rb', line 294

def read_file(text, path)
  path = Pathname(path.to_s).expand_path
  FileUtils.touch(path) unless File.exist?(path)
  if !File.exist?(path)
    #TODO: fail gracefully
    return
  end

  encoding = text.encoding
  content = path.open("r:#{encoding.name}") { |io| io.read }

  debug("GUESS ENCODING")
  unless content.valid_encoding? # take a guess
    GUESS_ENCODING_ORDER.find { |enc|
      content.force_encoding(enc)
      content.valid_encoding?
    }
    content.encode!(Encoding::UTF_8)
  end
  debug("END GUESS ENCODING")

  #TODO: Should put these as option:
  content.gsub!(/\r\n/, "\n")
  # content.gsub!(/\t/, "    ")
  content.gsub!(/\b/, "")

  #    content = filter_buffer(content)
  debug("END FILTER")
  return content
end

#reg_act(id, callfunc, name = "", opt = {}) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/vimamsa/actions.rb', line 13

def reg_act(id, callfunc, name = "", opt = {})
  if callfunc.class == Proc
    a = Action.new(id, name, callfunc, opt)
  else
    begin
      m = method(callfunc)
    rescue NameError
      m = method("missing_callfunc")
    end
    a = Action.new(id, name, m, opt)
  end
  return a
end

#repeat_last_actionObject



345
346
347
348
# File 'lib/vimamsa/editor.rb', line 345

def repeat_last_action()
  cmd = $command_history.last
  cmd[:method].call *cmd[:params] if cmd != nil
end

#repeat_last_findObject



350
351
352
353
354
# File 'lib/vimamsa/editor.rb', line 350

def repeat_last_find()
  return if !defined? $last_find_command
  vma.buf.jump_to_next_instance_of_char($last_find_command[:char],
                                        $last_find_command[:direction])
end

#run_as_idle(p, delay: 0.0) ⇒ Object

Run idle proc once (return false) Delay execution of proc until Gtk has fully processed the last calls.



102
103
104
105
106
107
108
109
# File 'lib/vimamsa/util.rb', line 102

def run_as_idle(p, delay: 0.0)
  if p.class == Proc
    Thread.new {
      sleep delay
      GLib::Idle.add(proc { p.call; false })
    }
  end
end

#run_cmd(cmd) ⇒ Object



119
120
121
122
123
124
125
126
# File 'lib/vimamsa/util.rb', line 119

def run_cmd(cmd)
  tmpf = Tempfile.new("vmarun", "/tmp").path
  cmd = "#{cmd} > #{tmpf}"
  debug "CMD:\n#{cmd}"
  system("bash", "-c", cmd)
  res_str = File.read(tmpf)
  return res_str
end

#run_edit_testsObject



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/vimamsa/tests.rb', line 31

def run_edit_tests()
  edt = EditorTests.new
  tests = edt.methods.select { |x| x.match(/test_.*/) }.collect { |x| { :method => edt.method(x), :name => x } }
  for t in tests
    b = create_new_buffer(file_contents = "\n", prefix = "buf", setcurrent = true)

    edits = t[:method].call
    # next if t[:name] != :test_create_close_buf
    errors = 0
    edits.each_with_index do |x, i|
      if x.class == Array
        (act, target) = x
        
        vma.macro.run_actions(act)
        # bufc = b.to_s
        bufc = vma.buf.to_s
        if bufc != target
          puts "ERROR[#{t[:name]}:#{i}] act=#{act.inspect} content=#{bufc.inspect} != #{target.inspect}"
          errors += 1
        end
      else
        vma.macro.run_actions(x)
      end
    end
    if errors == 0
      puts "TEST #{t[:name]} passed"
    else
    end
  end
end

#run_random_jump_test__tmpl(test_time = 60 * 60 * 10) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/vimamsa/debug.rb', line 113

def run_random_jump_test__tmpl(test_time = 60 * 60 * 10)
  open_new_file("TODO"); gui_sleep(0.1)

  ttstart = Time.now
  Kernel.srand(1231)
  step = 0
  while Time.now < ttstart + test_time
    debug "step=#{step}"
    buf.jump_to_random_pos
    buf.insert_txt("Z") if rand() > 0.25
    buf.reset_highlight() if rand() > 0.1
    gui_trigger_event

    # puts "========line:========="
    # puts buf.current_line()
    # puts "======================"

    render_buffer(vma.buf)

    gui_sleep(rand() / 2)
    if rand() < (1 / 40.0)
      buf.revert
    end

    gui_trigger_event
    buf.insert_txt("X") if rand() > 0.25
    render_buffer(vma.buf)

    vma.buffers.set_current_buffer(rand(vma.buffers.size)) if rand > 0.25
    step += 1
  end
end

#run_test(test_id) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/vimamsa/debug.rb', line 88

def run_test(test_id)
  target_results = read_file("", "tests/test_#{test_id}_output.txt")
  old_buffer = vma.buf
  vma.buf = Buffer.new("", "")
  load "tests/test_#{test_id}.rb"
  test_ok = vma.buf.to_s.strip == target_results.strip
  puts "##################"
  puts target_results
  puts "##################"
  puts vma.buf.to_s
  puts "##################"
  puts "TEST OK" if test_ok
  puts "TEST FAILED" if !test_ok
  puts "##################"
  vma.buf = old_buffer
end

#run_testsObject



3
4
5
6
7
8
9
10
11
12
13
# File 'lib/vimamsa/tests.rb', line 3

def run_tests()
  # DelayExecutioner.exec(id: :run_tests, wait: 0.7, callable: proc { run_tests_0 })

  # Reload class
  # if Object.constants.include?(:EditorTests)
  # Object.send(:remove_const, :EditorTests)
  # end
  load __FILE__

  run_edit_tests
end

#run_tests_0Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/vimamsa/tests.rb', line 15

def run_tests_0()
  tests = ["test_write_0"]
  stats = []
  for t in tests
    r = eval(t)
    if r == true
      stats << "test #{t} OK"
    else
      stats << "test #{t} FAILED"
    end
  end
  debug "TEST RESULTS:", 2
  puts stats.join("\n")
  puts "===================="
end

#running_wayland?Boolean

Returns:

  • (Boolean)


10
11
12
13
14
15
16
17
18
19
20
# File 'lib/vimamsa/util.rb', line 10

def running_wayland?
  sess = ENV["DESKTOP_SESSION"]
  sess ||= ENV["XDG_SESSION_DESKTOP"]
  sess ||= ENV["GDMSESSION"]
  sess ||= ""
  if sess.match(/wayland/)
    return true
  else
    return false
  end
end

#sanitize_input(str) ⇒ Object



325
326
327
328
329
330
331
# File 'lib/vimamsa/util.rb', line 325

def sanitize_input(str)
  if str.encoding != Encoding::UTF_8
    str = text.encode(Encoding::UTF_8)
  end
  str.gsub!(/\r\n/, "\n")
  return str
end

#save_buffer_listObject



1
2
3
4
5
6
7
8
# File 'lib/vimamsa/buffer_list.rb', line 1

def save_buffer_list()
  message("Save buffer list")
  buffn = get_dot_path("buffers.txt")
  f = File.open(buffn, "w")
  bufstr = vma.buffers.list.collect { |buf| buf.fname }.inspect
  f.write(bufstr)
  f.close()
end

#savedebug(message, e) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/vimamsa/debug.rb', line 56

def savedebug(message, e)
  FileUtils.mkdir_p("debug")
  puts "savedebug()"
  dbginfo = {}
  dbginfo["message"] = message
  dbginfo["debuginfo"] = $debuginfo
  dbginfo["trace"] = caller()
  dbginfo["trace"] = e.backtrace() if e
  dbginfo["trace_str"] = dbginfo["trace"].join("\n")
  dbginfo["edit_history"] = buf.edit_history
  dbginfo["cnf"] = $vimamsa_conf
  dbginfo["register"] = vma.register
  dbginfo["clipboard"] = vma.clipboard
  # dbginfo["last_event"] = $last_event
  dbginfo["buffer"] = {}
  dbginfo["buffer"]["str"] = buf.to_s
  dbginfo["buffer"]["lpos"] = buf.lpos
  dbginfo["buffer"]["cpos"] = buf.cpos
  dbginfo["buffer"]["pos"] = buf.pos

  pfxs = DateTime.now().strftime("%d%m%Y_%H%M%S")
  save_fn_dump = sprintf("debug/crash_%s.marshal", pfxs)
  save_fn_json = sprintf("debug/crash_%s.json", pfxs)
  mdump = Marshal.dump(dbginfo)
  IO.binwrite(save_fn_dump, mdump)
  IO.write(save_fn_json, dbginfo.to_json)
  puts "SAVED CRASH INFO TO:"
  puts save_fn_dump
  puts save_fn_json
end

#scan_indexes(txt, regex) ⇒ Object

Get all indexes for start of matching regexp



57
58
59
60
61
# File 'lib/vimamsa/util.rb', line 57

def scan_indexes(txt, regex)
  # indexes = txt.enum_for(:scan, regex).map { Regexp.last_match.begin(0) + 1 }
  indexes = txt.enum_for(:scan, regex).map { Regexp.last_match.begin(0) }
  return indexes
end

#scan_word_start_marks(search_str) ⇒ Object



592
593
594
595
596
# File 'lib/vimamsa/editor.rb', line 592

def scan_word_start_marks(search_str)
  # \Z = end of string, just before last newline.
  wsmarks = scan_indexes(search_str, /(?<=[^\p{Word}])\p{Word}|\Z/)
  return wsmarks
end

#set(_id, val) ⇒ Object

> $confh = :foo=>{:bar=>{:baz=>3}}



14
15
16
17
18
19
20
21
22
# File 'lib/vimamsa/conf.rb', line 14

def set(_id, val)
  a = $confh
  id = _id.to_a
  last = id.pop
  for x in id
    a = a[x]
  end
  a[last] = val
end

#set_cursor_pos(new_pos) ⇒ Object



328
329
330
331
332
# File 'lib/vimamsa/editor.rb', line 328

def set_cursor_pos(new_pos)
  buf.set_pos(new_pos)
  #render_buffer(vma.buf)
  debug "New pos: #{new_pos}lpos:#{vma.buf.lpos} cpos:#{vma.buf.cpos}"
end

#set_last_command(cmd) ⇒ Object



334
335
336
# File 'lib/vimamsa/editor.rb', line 334

def set_last_command(cmd)
  $command_history << cmd
end

#set_margin_all(widget, m) ⇒ Object



32
33
34
35
36
37
# File 'lib/vimamsa/gui_dialog.rb', line 32

def set_margin_all(widget, m)
  widget.margin_bottom = m
  widget.margin_top = m
  widget.margin_end = m
  widget.margin_start = m
end

#set_next_command_count(num) ⇒ Object



356
357
358
359
360
361
362
363
# File 'lib/vimamsa/editor.rb', line 356

def set_next_command_count(num)
  if $next_command_count != nil
    $next_command_count = $next_command_count * 10 + num.to_i
  else
    $next_command_count = num.to_i
  end
  debug("NEXT COMMAND COUNT: #{$next_command_count}")
end

#set_system_clipboard(arg) ⇒ Object



33
34
35
36
# File 'lib/vimamsa/clipboard.rb', line 33

def set_system_clipboard(arg)
  debug arg,2
  vma.gui.window.display.clipboard.set(arg)
end

#show_callerObject



44
45
46
# File 'lib/vimamsa/debug.rb', line 44

def show_caller
  puts caller().join("\n")
end

#show_key_bindingsObject



713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
# File 'lib/vimamsa/key_binding_tree.rb', line 713

def show_key_bindings()
  kbd_s = "❙Key bindings❙\n"
  kbd_s << "\n⦁[Mode] <keys> : <action>⦁\n"
  done = []

  kbd_s << "[B]=Browse, [C]=Command, [I]=Insert, [V]=Visual\n"
  kbd_s << "<key>!: Press <key> once, release before pressing any other keys\n"
  kbd_s << "===============================================\n"
  kbd_s << "◼ Basic\n"
  kbd_s << "◼◼ Command mode\n"

  x = vma.kbd.get_by_keywords(modes: ["C"], keywords: ["intro"])
  done.concat(x.lines); kbd_s << x

  kbd_s << "\n"
  kbd_s << "◼◼ Insert mode\n"
  x = vma.kbd.get_by_keywords(modes: ["I"], keywords: ["intro"])
  done.concat(x.lines); kbd_s << x
  kbd_s << "\n"
  kbd_s << "◼◼ Visual mode\n"
  x = vma.kbd.get_by_keywords(modes: ["V"], keywords: ["intro"])
  done.concat(x.lines); kbd_s << x
  kbd_s << "\n"

  kbd_s << "◼ Core\n"
  x = vma.kbd.get_by_keywords(modes: [], keywords: ["core"])
  x << vma.kbd.get_by_keywords(modes: ["X"], keywords: ["intro"])

  done.concat(x.lines); kbd_s << x
  kbd_s << "\n"

  kbd_s << "◼ Debug / Experimental\n"
  x = vma.kbd.get_by_keywords(modes: [], keywords: ["experimental"])
  done.concat(x.lines); kbd_s << x
  kbd_s << "\n"

  kbd_s << "◼ Others\n"
  # x = vma.kbd.get_by_keywords(modes: [], keywords:["experimental"])
  # x = vma.kbd.to_s
  x = vma.kbd.get_by_keywords(modes: [], keywords: [])
  done << x.lines - done
  kbd_s << (x.lines - done).join
  kbd_s << "\n"

  kbd_s << "===============================================\n"
  # x = vma.kbd.to_s
  # # require "pry"; binding.pry
  # done << x.lines - done
  # kbd_s << (x.lines - done).join
  # kbd_s << "\n"
  # kbd_s << "===============================================\n"
  b = create_new_buffer(kbd_s, "key-bindings")
  gui_set_file_lang(b.id, "hyperplaintext")
  #
end

#start_minibuffer_cmd(bufname, bufstr, cmd) ⇒ Object



365
366
367
368
369
# File 'lib/vimamsa/editor.rb', line 365

def start_minibuffer_cmd(bufname, bufstr, cmd)
  vma.kbd.set_mode(:minibuffer)
  $minibuffer = Buffer.new(bufstr, "")
  $minibuffer.call_func = method(cmd)
end

#start_profilerObject



11
12
13
14
# File 'lib/vimamsa/gui.rb', line 11

def start_profiler
  require "ruby-prof"
  RubyProf.start
end

#start_riplObject



146
147
148
# File 'lib/vimamsa/debug.rb', line 146

def start_ripl
  Ripl.start :binding => binding
end

#test_delete_0Object



153
154
155
156
# File 'lib/vimamsa/tests.rb', line 153

def test_delete_0
  macro = ["buf.jump(START_OF_BUFFER)", "buf.jump_word(FORWARD,WORD_START)", "buf.jump_word(FORWARD,WORD_START)", "buf.jump_word(FORWARD,WORD_START)", "buf.jump_word(FORWARD,WORD_START)", "buf.jump_word(FORWARD,WORD_START)", :e_move_backward_char, "buf.delete(BACKWARD_CHAR)", "buf.delete(BACKWARD_CHAR)", "buf.delete(BACKWARD_CHAR)", "buf.delete(BACKWARD_CHAR)", "buf.delete(BACKWARD_CHAR)", "buf.delete(BACKWARD_CHAR)", :forward_line, :e_move_backward_char, "buf.delete(CURRENT_CHAR_FORWARD)", "buf.delete(CURRENT_CHAR_FORWARD)", "buf.delete(CURRENT_CHAR_FORWARD)", "buf.delete(CURRENT_CHAR_FORWARD)", "buf.delete(CURRENT_CHAR_FORWARD)", "buf.delete(CURRENT_CHAR_FORWARD)", "buf.delete(CURRENT_CHAR_FORWARD)", "buf.delete(CURRENT_CHAR_FORWARD)", "buf.delete(CURRENT_CHAR_FORWARD)", "buf.delete(CURRENT_CHAR_FORWARD)", :forward_line, :forward_line, :forward_line, :forward_line, :forward_line, :delete_line, :forward_line, :delete_line, :forward_line, :forward_line, :delete_line, :delete_line, :forward_line, :forward_line, "vma.kbd.set_mode(:audio)", :forward_line, :forward_line, :forward_line, :forward_line, "buf.delete2(:to_mark,'a')", :backward_line, :forward_line, :forward_line, "vma.kbd.set_mode(:audio)", "buf.jump_word(FORWARD,WORD_START)", "buf.jump_word(FORWARD,WORD_START)", "buf.jump_word(FORWARD,WORD_START)", "buf.jump_word(FORWARD,WORD_START)", "buf.delete2(:to_mark,'a')", "buf.mark_current_position('b')", :forward_line, :forward_line, :forward_line, :forward_line, :forward_line, :forward_line, :forward_line, :forward_line, :forward_line, :forward_line, "buf.delete2(:to_mark,'a')", "vma.kbd.set_mode(:audio)", :forward_line, :forward_line, :forward_line, "buf.jump_to_mark('a')", "buf.jump_to_mark('a')", :backward_line, :backward_line, :backward_line, :backward_line, "buf.jump_to_mark('a')", "buf.jump_to_mark('a')", "buf.jump_to_mark('a')", "buf.jump_to_mark('a')"]
  return macro_test(macro, "71bc0421b47549267b327b69216ad8e042379625f99de1ba4faaa30d5042c22d")
end

#test_paste_0(runmacro = true) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/vimamsa/tests.rb', line 100

def test_paste_0(runmacro = true)
  return
  #TODO: update macro
  b = create_new_buffer(file_contents = "\n", prefix = "buf", setcurrent = true)

  b.insert_txt(JABBERWOCKY)
  b.insert_txt(LOREM_IPSUM)
  b.insert_txt(LOREM_IPSUM)

  macro = ["buf.jump(START_OF_BUFFER)", "buf.copy_line", :forward_line, :paste_after, :backward_line, :backward_line, "buf.paste(BEFORE)", :forward_line, :forward_line, :forward_line, :forward_line, "buf.jump_word(FORWARD,WORD_START)", "buf.start_visual_mode", "buf.jump_word(FORWARD,WORD_END)", "buf.copy_active_selection()", "buf.move(FORWARD_CHAR)", "buf.paste(BEFORE)", "buf.jump_word(FORWARD,WORD_END)", :paste_after, :forward_line, "buf.jump(BEGINNING_OF_LINE)", "buf.copy_line", :forward_line, :forward_line, :paste_after, :paste_after, :forward_line, "buf.jump_word(FORWARD,WORD_START)", "buf.start_visual_mode", "buf.jump_word(FORWARD,WORD_END)", "buf.jump_word(FORWARD,WORD_END)", "buf.jump_word(FORWARD,WORD_END)", "buf.jump_word(FORWARD,WORD_END)", "buf.jump(END_OF_LINE)", :e_move_backward_char, "buf.copy_active_selection()", :forward_line, "buf.paste(BEFORE)", "buf.paste(BEFORE)", "buf.paste(BEFORE)", "buf.paste(BEFORE)", "buf.jump(END_OF_BUFFER)", "buf.jump(BEGINNING_OF_LINE)", "buf.jump_word(FORWARD,WORD_START)", "buf.jump_word(FORWARD,WORD_START)", "buf.start_visual_mode", "buf.jump_word(FORWARD,WORD_END)", "buf.jump_word(FORWARD,WORD_END)", "buf.jump_word(FORWARD,WORD_END)", "buf.jump_word(FORWARD,WORD_END)", "buf.copy_active_selection()", "buf.jump(BEGINNING_OF_LINE)", "buf.paste(BEFORE)", "buf.paste(BEFORE)"]

  macro_r = true
  if runmacro
    macro_r = vma.macro.run_actions(macro)
  end

  hex = Digest::SHA2.hexdigest b.to_s
  conds = [hex == "705061f7bc6370b501b6d09615547530a103e2a659e20fb6915d17ae65f564fa",
           macro_r == true]
  # debug conds
  debug hex

  if conds.include?(false)
    return false
  else
    return true
  end
end

#tilde_path(abspath) ⇒ Object



22
23
24
25
# File 'lib/vimamsa/util.rb', line 22

def tilde_path(abspath)
  userhome = File.expand_path("~/")
  abspath.sub(/^#{Regexp.escape(userhome)}\//, "~/")
end

#to_camel_case(str) ⇒ Object



27
28
29
30
31
32
33
# File 'lib/vimamsa/util.rb', line 27

def to_camel_case(str)
  words = str.split(/\W+/) # Split the input string into words
  camel_case_words = words.map.with_index do |word, index|
    index == 0 ? word.downcase : word.capitalize
  end
  camel_case_words.join
end

#translate_path(fn, bf) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/vimamsa/hyper_plain_text.rb', line 60

def translate_path(fn, bf)
  if File.exist?(fn)
    outfn = fn
  elsif fn[0] == "$"
    outfn = ppath(fn[1..-1]) # Path to source location
  elsif fn[0] == "~"
    outfn = File.expand_path(fn)
  elsif !bf.fname.nil?
    pd = File.dirname(bf.fname)
    outfn = "#{pd}/#{fn}"
  else
    outfn = File.expand_path(fn)
  end
  return outfn
end

#unimplementedObject

load “vendor/ver/config/detect.rb”



61
62
63
# File 'lib/vimamsa/rbvma.rb', line 61

def unimplemented
  debug "unimplemented"
end

#uri_to_path(uri) ⇒ Object



360
361
362
363
364
365
366
367
368
369
# File 'lib/vimamsa/util.rb', line 360

def uri_to_path(uri)
  fp = nil
  begin
    x = URI::DEFAULT_PARSER.unescape(URI(uri).path)
  rescue URI::InvalidURIError
  else
    fp = x # only if no exception
  end
  return fp
end

#vmaObject



50
51
52
# File 'lib/vimamsa/main.rb', line 50

def vma()
  return $vma
end

#wait_for_resize(window, tries = 200) ⇒ Object

Wait for window resize to take effect GTk3 had a resize notify event which got removed in gtk4 discourse.gnome.org/t/gtk4-any-way-to-connect-to-a-window-resize-signal/14869/3



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/vimamsa/gui.rb', line 25

def wait_for_resize(window, tries = 200)
  i = 0
  widthold = @window.width
  heightold = @window.height
  while true
    iterate_gui_main_loop
    break if widthold != window.width
    break if heightold != window.height
    if i >= tries
      debug "i >= tries", 2
      break
    end
    i += 1
  end
end

#which(cmd) ⇒ Object



277
278
279
280
281
282
283
284
285
286
# File 'lib/vimamsa/util.rb', line 277

def which(cmd)
  exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [""]
  ENV["PATH"].split(File::PATH_SEPARATOR).each do |path|
    exts.each do |ext|
      exe = File.join(path, "#{cmd}#{ext}")
      return exe if File.executable?(exe) && !File.directory?(exe)
    end
  end
  nil
end

#write_to_file(savepath, s) ⇒ Object

TODO: function not used



1604
1605
1606
1607
1608
1609
1610
# File 'lib/vimamsa/buffer.rb', line 1604

def write_to_file(savepath, s)
  if is_path_writable(savepath)
    IO.write(savepath, self.to_s)
  else
    message("PATH NOT WRITABLE: #{savepath}")
  end
end