Top Level Namespace

Defined Under Namespace

Modules: Differ, Gtk, Kernel, Vimamsa Classes: Action, Audio, Buffer, BufferList, BufferManager, Converter, DelayExecutioner, EasyJump, Editor, Encrypt, FileContentSearch, FileFinder, FileHistory, FileManager, FileSelector, Grep, HSafe, Hook, HookItem, KeyBindingTree, LangSrv, Macro, OneInputAction, PopupFormGenerator, ResizableImage, Search, SelectUpdateWindow, State, VMAgui, VSourceView

Constant Summary collapse

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 =
2009
FORWARD =
2010
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
ALTMODIFIER =

An Alt key on the keyboard is pressed.

0x08000000
NOMODIFIER =

No modifier key is pressed.

0x00000000
SHIFTMODIFIER =

A Shift key on the keyboard is pressed.

0x02000000
CONTROLMODIFIER =

A Ctrl key on the keyboard is pressed.

0x04000000
METAMODIFIER =

A Meta key on the keyboard is pressed.

0x10000000
KEYPADMODIFIER =

A keypad button is pressed.

0x20000000
LSP =
LanguageServer::Protocol

Instance Method Summary collapse

Instance Method Details

#_quitObject



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

def _quit()
  vma.shutdown
  # Gtk.main_quit
end

#ack_buffer(_instr, b = nil) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/vimamsa/ack.rb', line 114

def ack_buffer(_instr, b = nil)
  instr = Shellwords.escape(_instr)
  bufstr = ""
  for path in vma.get_content_search_paths
    bufstr += run_cmd("ack -Q --type-add=gd=.gd -ki --nohtml --nojs --nojson #{instr} #{path}")
  end
  if bufstr.size > 5
  b = create_new_buffer(bufstr,"ack")
  highlight_match(b, _instr, color: "#10bd8e")
  else
    message("No results for input:#{instr}")
  end
end

#assert_binary_exists(bin) ⇒ Object



150
151
152
153
154
# File 'lib/vimamsa/util.rb', line 150

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

#backup_all_buffersObject



2075
2076
2077
2078
2079
2080
# File 'lib/vimamsa/buffer.rb', line 2075

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

#bindkey(key, action) ⇒ Object



530
531
532
# File 'lib/vimamsa/key_binding_tree.rb', line 530

def bindkey(key, action)
  $kbd.bindkey(key, action)
end

#bufObject

Return currently active buffer



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

def buf()
  return vma.buf
end

#buf_replace(search_str, replace_str) ⇒ Object



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/vimamsa/search_replace.rb', line 155

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



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

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



46
47
48
# File 'lib/vimamsa/main.rb', line 46

def buflist()
  return vma.buffers
end

#bufsObject



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

def bufs()
  return vma.buffers
end

#call_action(id) ⇒ Object



41
42
43
44
45
46
47
48
49
# File 'lib/vimamsa/actions.rb', line 41

def call_action(id)
  $acth << id
  a = $actions[id]
  if a
    a.method.call()
  else
    message("Unknown action: " + id.inspect)
  end
end

#can_save_to_directory?(dpath) ⇒ Boolean

Returns:

  • (Boolean)


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

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



65
66
67
68
69
70
71
72
73
# File 'lib/vimamsa/gui.rb', line 65

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

#conf(id) ⇒ Object

TODO



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

def conf(id)
  return $cnf[id]
end

#crash(message, e = nil) ⇒ Object



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

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



519
520
521
522
523
524
525
526
527
# File 'lib/vimamsa/editor.rb', line 519

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



504
505
506
507
508
509
510
511
512
513
514
515
516
517
# File 'lib/vimamsa/editor.rb', line 504

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

  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 $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 $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_cur_buffer(password, b = nil) ⇒ Object



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

def decrypt_cur_buffer(password, b = nil)
  vma.buf.decrypt(password)
end

#diff_bufferObject



399
400
401
402
403
404
405
406
407
408
409
410
411
412
# File 'lib/vimamsa/editor.rb', line 399

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

#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



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

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



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

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

#error(str) ⇒ Object



461
462
463
464
# File 'lib/vimamsa/editor.rb', line 461

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

#exec_action(action) ⇒ Object



536
537
538
539
540
541
542
543
544
545
546
# File 'lib/vimamsa/key_binding_tree.rb', line 536

def exec_action(action)
  $kbd.last_action = $kbd.cur_action
  $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



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

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



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

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



418
419
420
421
422
423
424
425
426
# File 'lib/vimamsa/editor.rb', line 418

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})"
  $macro.overwrite_current_action(eval_str)
  return $search.set(input_str, "simple", vma.buf)
end

#expand_if_existing(fpath) ⇒ Object



201
202
203
204
205
206
# File 'lib/vimamsa/util.rb', line 201

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



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

def fatal_error(msg)
  debug msg
  exit!
end

#file_is_text_file(fpath) ⇒ Object



637
638
639
640
641
642
643
644
645
646
# File 'lib/vimamsa/editor.rb', line 637

def file_is_text_file(fpath)
  debug "file_is_text_file(#{fpath})"
  fpath = File.expand_path(fpath)
  return false if !File.exist?(fpath)
  r = exec_cmd("file", fpath)
  debug "DEBUG:#{r}"
  return true if r.match(/UTF-8.*text/)
  return true if r.match(/ASCII.*text/)
  return false
end

#file_saveas(filename) ⇒ Object



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

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

#filter_buffer(buf) ⇒ Object



529
530
531
532
533
534
535
536
537
538
539
# File 'lib/vimamsa/editor.rb', line 529

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

#filter_items(item_list, item_key, search_str) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/vimamsa/actions.rb', line 123

def filter_items(item_list, item_key, search_str)
  #    Ripl.start :binding => binding
  item_hash = {}
  puts item_list.inspect
  scores = Parallel.map(item_list, in_threads: 8) do |item|
    if item[:str].class != String
      puts item.inspect
      exit!
    end
    [item, srn_dst(search_str, item[:str])]
  end
  scores.sort_by! { |x| -x[1] }
  debug scores.inspect
  scores = scores[0..30]

  return scores
end

#find_project_dir_of_cur_bufferObject



672
673
674
675
676
677
678
679
680
# File 'lib/vimamsa/editor.rb', line 672

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



658
659
660
661
662
663
664
665
666
667
668
669
670
# File 'lib/vimamsa/editor.rb', line 658

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
    candfn = "#{pdir}/.vma_project"
    if File.exist?(candfn)
      projdir = pdir
      break
    end
  end
  return projdir
end

#focus_outObject

Try to clear modifiers when program loses focus e.g. after alt-tab



550
551
552
553
# File 'lib/vimamsa/key_binding_tree.rb', line 550

def focus_out
  debug "RB Clear modifiers"
  $kbd.clear_modifiers()
end

#fuzzy_filter(search_str, list, maxfinds) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/vimamsa/file_history.rb', line 69

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

#get_clipboardObject



321
322
323
# File 'lib/vimamsa/editor.rb', line 321

def get_clipboard()
  return $clipboard[-1]
end

#get_dot_path(sfx) ⇒ Object



617
618
619
620
621
622
# File 'lib/vimamsa/editor.rb', line 617

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

#get_file_line_pointer(s) ⇒ Object



624
625
626
627
628
629
630
631
632
633
634
# File 'lib/vimamsa/editor.rb', line 624

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



75
76
77
78
79
80
81
# File 'lib/vimamsa/gui.rb', line 75

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

#grep_cur_buffer(search_str, b = nil) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/vimamsa/search_replace.rb', line 89

def grep_cur_buffer(search_str, b = nil)
  debug "grep_cur_buffer(search_str)"
  lines = vma.buf.split("\n")
  r = Regexp.new(Regexp.escape(search_str), Regexp::IGNORECASE)
  fpath = ""
  fpath = vma.buf.pathname.expand_path.to_s + ":" if vma.buf.pathname
  res_str = ""

  hlparts = []
  $grep_matches = []
  lines.each_with_index { |l, i|
    if r.match(l)
      res_str << "#{i + 1}:"
      # ind = scan_indexes(l, r)
      res_str << "#{l}\n"
      $grep_matches << i + 1 # Lines start from index 1
    end
  }
  $grep_bufid = vma.buffers.current_buf
  b = create_new_buffer(res_str, "grep")
  vbuf = vma.gui.view.buffer

  highlight_match(b, search_str, color: "#10bd8e")

  b.line_action_handler = proc { |lineno|
    debug "GREP HANDLER:#{lineno}"
    jumpto = $grep_matches[lineno]
    if jumpto.class == Integer
      vma.buffers.set_current_buffer($grep_bufid, update_history = true)
      buf.jump_to_line(jumpto)
    end
  }
end

#gui_ackObject



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/vimamsa/ack.rb', line 95

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

  nfo = "<html><h2>Search contents of all files using ack</h2>
  <div style='width:300px'>
  <p>Hint: add empty file named .vma_project to dirs you want to search.</p>\n<p>If .vma_project exists in parent dir of current file, searches within that dir</p></div></html>"

  nfo = "<span size='x-large'>Search contents of all files using ack</span>
Will search the following directories:
#{search_paths}
  
<span>Hint: add empty file named .vma_project to directories you want to search in. 
 If .vma_project exists in parent directory of current file, searches within that directory.
  </span>"

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

#gui_add_image(imgpath, pos) ⇒ Object



137
138
# File 'lib/vimamsa/gui.rb', line 137

def gui_add_image(imgpath, pos)
end

#gui_create_buffer(id, bufo) ⇒ 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
123
124
# File 'lib/vimamsa/gui.rb', line 98

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

  view.register_signals()
  $debug = true

  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: Monospace; font-size: 11pt; }")
  view.style_context.add_provider(provider)
  view.wrap_mode = :char
  view.set_tab_width(conf(:tab_width))

  $vmag.buffers[id] = view
end

#gui_file_history_select_callback(search_str, idx) ⇒ Object



100
101
102
103
104
105
106
# File 'lib/vimamsa/file_history.rb', line 100

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



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

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



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

def gui_file_saveas(dirpath)
  dialog = Gtk::FileChooserDialog.new(:title => "Save as",
                                      :action => :save,
                                      :buttons => [["Save", :accept],
                                                   ["Cancel", :cancel]])
  # dialog.set_current_folder(dirpath) #TODO:gtk4
  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 = $macro.named_macros[selected[0]].clone
  debug "SELECTED MACRO:#{selected}, #{m}"
  id = $macro.last_macro
  $macro.recorded_macros[id] = m
  $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 = $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_grepObject



65
66
67
68
69
# File 'lib/vimamsa/search_replace.rb', line 65

def gui_grep()
  callback = proc { |x| grep_cur_buffer(x) }
  # gui_one_input_action("Grep", "Search:", "grep", "grep_cur_buffer")
  gui_one_input_action("Grep", "Search:", "grep", callback)
end

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



123
124
125
126
127
# File 'lib/vimamsa/search_replace.rb', line 123

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



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

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.set_current_folder(Gio::File.new_for_path("/tmp"))

  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_replace_callback(vals) ⇒ Object

def gui_replace_callback(search_str, replace_str)



130
131
132
133
134
135
136
# File 'lib/vimamsa/search_replace.rb', line 130

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



139
140
141
142
143
144
145
146
147
148
149
# File 'lib/vimamsa/search_replace.rb', line 139

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:?



141
142
# File 'lib/vimamsa/gui.rb', line 141

def gui_select_window_close(arg = nil)
end

#gui_set_buffer_contents(id, txt) ⇒ Object



144
145
146
147
# File 'lib/vimamsa/gui.rb', line 144

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

#gui_set_current_buffer(id) ⇒ Object



154
155
156
157
# File 'lib/vimamsa/gui.rb', line 154

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

#gui_set_cursor_pos(id, pos) ⇒ Object

TODO: remove



150
151
152
# File 'lib/vimamsa/gui.rb', line 150

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

#gui_set_file_lang(id, lname) ⇒ Object



126
127
128
129
130
131
132
133
134
135
# File 'lib/vimamsa/gui.rb', line 126

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



159
160
161
162
163
164
# File 'lib/vimamsa/gui.rb', line 159

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?



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

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

#handle_drag_and_drop(fname) ⇒ Object



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

def handle_drag_and_drop(fname)
  debug "EDITOR:handle_drag_and_drop"
  buf.handle_drag_and_drop(fname)
end

#handle_key_event(event) ⇒ Object



555
556
557
# File 'lib/vimamsa/key_binding_tree.rb', line 555

def handle_key_event(event)
  $kbd.handle_key_event(event)
end

#highlight_match(bf, str, color: "#aa0000ff") ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/vimamsa/search_replace.rb', line 71

def highlight_match(bf, str, color: "#aa0000ff")
  vbuf = bf.view.buffer
  r = Regexp.new(Regexp.escape(str), Regexp::IGNORECASE)

  hlparts = []

  tt = vma.gui.view.buffer.create_tag("highlight_match_tag")
  tt.weight = 650
  tt.foreground = color

  ind = scan_indexes(bf, r)
  ind.each { |x|
    itr = vbuf.get_iter_at(:offset => x)
    itr2 = vbuf.get_iter_at(:offset => x + str.size)
    vbuf.apply_tag(tt, itr, itr2)
  }
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

#hook_drawObject



612
613
614
615
# File 'lib/vimamsa/editor.rb', line 612

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
# 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
    # Ripl.start :binding => binding

    fpfx = m[3]
    if vma.buf.fname
      dn = File.dirname(vma.buf.fname)

      fcands = []
      if 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.exists?(fc)
          fn = fc
          break
        end
      end

      if fn
        if m[2] == "audio"
          # Thread.new { Audio.play(fn) }
          Audio.play(fn) 
        else
          message "HPT opening file #{fn}"
          return fn
        end
        # open_existing_file(fn)
        # return true
      else
        message "File not found: #{fpfx}"
      end
    end
  end
  return nil
end

#hpt_scan_audio(bf = nil) ⇒ Object

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



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/vimamsa/hyper_plain_text.rb', line 63

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



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/vimamsa/hyper_plain_text.rb', line 91

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
  GLib::Idle.add(proc { vma.gui.scale_all_images })

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

#idle_funcObject



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/vimamsa/gui.rb', line 39

def idle_func
  # debug "IDLEFUNC"
  if $idle_scroll_to_mark
    # $view.get_visible_rect
    vr = $view.visible_rect

    # iter = b.get_iter_at(:offset => i)

    b = $view.buffer
    iter = b.get_iter_at(:offset => b.cursor_position)
    iterxy = $view.get_iter_location(iter)
    # debug "ITERXY" + iterxy.inspect

    intr = iterxy.intersect(vr)
    if intr.nil?
      $view.set_cursor_pos($view.buffer.cursor_position)
    else
      $idle_scroll_to_mark = false
    end

    sleep(0.1)
  end
  sleep(0.01)
  return true
end

#invoke_commandObject



414
415
416
# File 'lib/vimamsa/editor.rb', line 414

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

#invoke_replaceObject



151
152
153
# File 'lib/vimamsa/search_replace.rb', line 151

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 $kbd.mode_root_state.to_s() == "C"
  return false
end

#is_existing_file(s) ⇒ Object



216
217
218
219
220
221
222
# File 'lib/vimamsa/util.rb', line 216

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



224
225
226
227
228
229
# File 'lib/vimamsa/util.rb', line 224

def is_image_file(fpath)
  return false if !File.exist?(fpath)
  return false if !fpath.match(/.(jpg|jpeg|png)$/i)
  #TODO: check contents of file
  return true
end

#is_path(s) ⇒ Object



238
239
240
241
242
243
244
# File 'lib/vimamsa/util.rb', line 238

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

#is_path_writable(fpath) ⇒ Object



2067
2068
2069
2070
2071
2072
2073
# File 'lib/vimamsa/buffer.rb', line 2067

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_text_file(fpath) ⇒ Object



231
232
233
234
235
236
# File 'lib/vimamsa/util.rb', line 231

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

#is_url(s) ⇒ Object



197
198
199
# File 'lib/vimamsa/util.rb', line 197

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 $kbd.mode_root_state.to_s() == "V"
  return 0
end

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



561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
# File 'lib/vimamsa/editor.rb', line 561

def jump_to_file(filename, linenum = nil, charn = nil)
  open_new_file(filename)

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

  # Link to line
  if !linenum.nil?
    buf.jump_to_line(linenum)
    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

#last_actionObject



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

def last_action
  return $acth[-1]
end

#load_buffer(fname) ⇒ Object



541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
# File 'lib/vimamsa/editor.rb', line 541

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



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

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

#message(s) ⇒ Object



466
467
468
469
470
471
472
473
474
# File 'lib/vimamsa/editor.rb', line 466

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



435
436
437
438
439
440
# File 'lib/vimamsa/editor.rb', line 435

def minibuffer_cancel()
  debug "minibuffer_cancel"
  $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



457
458
459
# File 'lib/vimamsa/editor.rb', line 457

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

#minibuffer_endObject



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

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

#minibuffer_new_char(c) ⇒ Object



442
443
444
445
446
447
448
449
450
451
# File 'lib/vimamsa/editor.rb', line 442

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



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

def missing_callfunc
  debug "missing_callfunc"
end

#mkdir_if_not_exists(_dirpath) ⇒ Object



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

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?



582
583
584
# File 'lib/vimamsa/editor.rb', line 582

def open_existing_file(filename)
  open_new_file(filename)
end

#open_file_dialogObject



303
304
305
306
307
# File 'lib/vimamsa/editor.rb', line 303

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



586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
# File 'lib/vimamsa/editor.rb', line 586

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}"
    vma.buffers.set_current_buffer(b)
  else
    if !is_path_writable(filename)
      message("Path #{filename} cannot be written to")
      return false
    end
    message "New file opened: #{filename}"
    fname = filename
    bf = load_buffer(fname)
    vma.buffers.set_current_buffer_by_id(bf.id)
  end
end

#open_url(url) ⇒ Object



14
15
16
# File 'lib/vimamsa/util.rb', line 14

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

#open_with_default_program(url) ⇒ Object



18
19
20
# File 'lib/vimamsa/util.rb', line 18

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

#page_downObject



88
89
90
91
# File 'lib/vimamsa/gui.rb', line 88

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

#page_upObject



83
84
85
86
# File 'lib/vimamsa/gui.rb', line 83

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

#paste_register(char) ⇒ Object



653
654
655
656
# File 'lib/vimamsa/editor.rb', line 653

def paste_register(char)
  $c = $register[char]
  message("Paste: #{$c}")
end

#ppath(s) ⇒ Object



208
209
210
211
212
213
214
# File 'lib/vimamsa/util.rb', line 208

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



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/vimamsa/util.rb', line 156

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



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

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



357
358
359
360
# File 'lib/vimamsa/editor.rb', line 357

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

#repeat_last_findObject



362
363
364
365
366
# File 'lib/vimamsa/editor.rb', line 362

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) ⇒ Object

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



6
7
8
9
10
11
12
# File 'lib/vimamsa/util.rb', line 6

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

#run_cmd(cmd) ⇒ Object



22
23
24
25
26
27
28
29
# File 'lib/vimamsa/util.rb', line 22

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_random_jump_test__tmpl(test_time = 60 * 60 * 10) ⇒ Object



112
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
# File 'lib/vimamsa/debug.rb', line 112

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



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

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



82
83
84
85
# File 'lib/vimamsa/debug.rb', line 82

def run_tests()
  run_test("01")
  run_test("02")
end

#sanitize_input(str) ⇒ Object



187
188
189
190
191
192
193
# File 'lib/vimamsa/util.rb', line 187

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



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

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

#savedebug(message, e) ⇒ Object



51
52
53
54
55
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
# File 'lib/vimamsa/debug.rb', line 51

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"] = $cnf
  dbginfo["register"] = $register
  dbginfo["clipboard"] = $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



58
59
60
61
62
# File 'lib/vimamsa/rbvma.rb', line 58

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



606
607
608
609
610
# File 'lib/vimamsa/editor.rb', line 606

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

#search_actionsObject



55
56
57
58
59
60
61
62
63
64
# File 'lib/vimamsa/actions.rb', line 55

def search_actions()
  l = []
  opt = { :title => "Search for actions", :desc => "Fuzzy search for actions. <up> or <down> to change selcted. <enter> to select current." }
  $select_keys = ["h", "l", "f", "d", "s", "a", "g", "z"]

  gui_select_update_window(l, $select_keys.collect { |x| x.upcase },
                           "search_actions_select_callback",
                           "search_actions_update_callback",
                           opt)
end

#search_actions_select_callback(search_str, idx) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/vimamsa/actions.rb', line 108

def search_actions_select_callback(search_str, idx)
  item = $item_list[idx][2]
  acc = item[0][:action]

  debug "Selected:" + acc.to_s
  gui_select_window_close(0)

  if acc.class == String
    eval(acc)
  elsif acc.class == Symbol
    debug "Symbol"
    call_action(acc)
  end
end

#search_actions_update_callback(search_str = "") ⇒ Object



68
69
70
71
72
73
74
75
76
77
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
104
105
106
# File 'lib/vimamsa/actions.rb', line 68

def search_actions_update_callback(search_str = "")
  return [] if search_str == ""

  item_list2 = []
  for act_id in $actions.keys
    act = $actions[act_id]
    item = {}
    item[:key] = ""

    for mode_str in ["C", "V"]
      c_kbd = vma.kbd.act_bindings[mode_str][act_id]
      if c_kbd.class == String
        item[:key] = "[#{mode_str} #{c_kbd}] "
        break
      end
    end
    # c_kbd = vma.kbd.act_bindings[mode_str][nfo[:action]]
    item[:action] = act_id
    item[:str] = act_id.to_s
    if $actions[act_id].method_name != ""
      item[:str] = $actions[act_id].method_name
    end
    item_list2 << item
  end

  item_list = item_list2

  a = filter_items(item_list, 0, search_str)
  debug a.inspect

  r = a.collect { |x| [x[0][0], 0, x] }
  debug r.inspect
  $item_list = r

  # Ripl.start :binding => binding

  r = a.collect { |x| ["#{x[0][:key]}#{x[0][:str]}", 0, x] }
  return r
end

#set_clipboard(s) ⇒ Object



325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/vimamsa/editor.rb', line 325

def set_clipboard(s)
  if !(s.class <= String) or s.size == 0
    debug s.inspect
    debug [s, s.class, s.size]
    log_error("s.class != String or s.size == 0")
    # Ripl.start :binding => binding
    return
  end
  $clipboard << s
  set_system_clipboard(s)
  $register[$cur_register] = s
  debug "SET CLIPBOARD: [#{s}]"
  debug "REGISTER: #{$cur_register}:#{$register[$cur_register]}"
end

#set_conf(id, val) ⇒ Object



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

def set_conf(id, val)
  $cnf[id] = val
end

#set_cursor_pos(new_pos) ⇒ Object



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

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



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

def set_last_command(cmd)
  $command_history << cmd
end

#set_margin_all(widget, m) ⇒ Object



208
209
210
211
212
213
# File 'lib/vimamsa/search_replace.rb', line 208

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



368
369
370
371
372
373
374
375
# File 'lib/vimamsa/editor.rb', line 368

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_register(char) ⇒ Object



648
649
650
651
# File 'lib/vimamsa/editor.rb', line 648

def set_register(char)
  $cur_register = char
  message("Set register #{char}")
end

#set_system_clipboard(arg) ⇒ Object



94
95
96
# File 'lib/vimamsa/gui.rb', line 94

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

#setcnf(id, val) ⇒ Object



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

def setcnf(id, val)
  set_conf(id, val)
end

#show_key_bindingsObject



383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
# File 'lib/vimamsa/editor.rb', line 383

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

  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 << vma.kbd.to_s
  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



377
378
379
380
381
# File 'lib/vimamsa/editor.rb', line 377

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

#start_riplObject



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

def start_ripl
  Ripl.start :binding => binding
end

#system_clipboard_changed(clipboard_contents) ⇒ Object

TODO:delete?



310
311
312
313
314
315
316
317
318
319
# File 'lib/vimamsa/editor.rb', line 310

def system_clipboard_changed(clipboard_contents)
  max_clipboard_items = 100
  if clipboard_contents != $clipboard[-1]
    #TODO: HACK
    $paste_lines = false
  end
  $clipboard << clipboard_contents
  # debug $clipboard[-1]
  $clipboard = $clipboard[-([$clipboard.size, max_clipboard_items].min)..-1]
end

#translate_path(fn, bf) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/vimamsa/hyper_plain_text.rb', line 45

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”



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

def unimplemented
  debug "unimplemented"
end

#vmaObject



53
54
55
# File 'lib/vimamsa/main.rb', line 53

def vma()
  return $vma
end

#which(cmd) ⇒ Object



139
140
141
142
143
144
145
146
147
148
# File 'lib/vimamsa/util.rb', line 139

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



2059
2060
2061
2062
2063
2064
2065
# File 'lib/vimamsa/buffer.rb', line 2059

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