vimamsa 0.1.14 → 0.1.15

Sign up to get free protection for your applications and to get access to all the features.
data/lib/vimamsa/gui.rb CHANGED
@@ -1,5 +1,25 @@
1
1
  $idle_scroll_to_mark = false
2
2
 
3
+ $removed_controllers = []
4
+
5
+ def gui_remove_controllers(widget)
6
+ clist = widget.observe_controllers
7
+ to_remove = []
8
+ (0..(clist.n_items - 1)).each { |x|
9
+ ctr = clist.get_item(x)
10
+ to_remove << ctr
11
+ }
12
+ if to_remove.size > 0
13
+ # debug "Removing controllers:"
14
+ # pp to_remove
15
+ to_remove.each { |x|
16
+ # To avoid GC. https://github.com/ruby-gnome/ruby-gnome/issues/15790
17
+ $removed_controllers << x
18
+ widget.remove_controller(x)
19
+ }
20
+ end
21
+ end
22
+
3
23
  def gui_open_file_dialog(dirpath)
4
24
  dialog = Gtk::FileChooserDialog.new(:title => "Open file",
5
25
  :action => :open,
@@ -53,17 +73,15 @@ def get_visible_area()
53
73
  return [startpos, endpos]
54
74
  end
55
75
 
56
- def page_up
57
- $view.signal_emit("move-cursor", Gtk::MovementStep.new(:PAGES), -1, false)
58
- return true
59
- end
60
-
61
- def page_down
62
- $view.signal_emit("move-cursor", Gtk::MovementStep.new(:PAGES), 1, false)
63
- return true
64
- end
65
-
76
+ # def page_up
77
+ # $view.signal_emit("move-cursor", Gtk::MovementStep.new(:PAGES), -1, false)
78
+ # return true
79
+ # end
66
80
 
81
+ # def page_down
82
+ # $view.signal_emit("move-cursor", Gtk::MovementStep.new(:PAGES), 1, false)
83
+ # return true
84
+ # end
67
85
 
68
86
  def gui_create_buffer(id, bufo)
69
87
  debug "gui_create_buffer(#{id})"
@@ -71,7 +89,6 @@ def gui_create_buffer(id, bufo)
71
89
  view = VSourceView.new(nil, bufo)
72
90
 
73
91
  view.register_signals()
74
- cnf.debug = true
75
92
 
76
93
  ssm = GtkSource::StyleSchemeManager.new
77
94
  ssm.set_search_path(ssm.search_path << ppath("styles/"))
@@ -85,10 +102,10 @@ def gui_create_buffer(id, bufo)
85
102
  view.set_buffer(buf1)
86
103
 
87
104
  provider = Gtk::CssProvider.new
88
- provider.load(data: "textview { font-family: Monospace; font-size: 11pt; }")
105
+
106
+ provider.load(data: "textview { font-family: #{cnf.font.family!}; font-size: #{cnf.font.size!}pt; }")
89
107
  view.style_context.add_provider(provider)
90
108
  view.wrap_mode = :char
91
- pp $cnf
92
109
  view.set_tab_width(conf(:tab_width))
93
110
 
94
111
  $vmag.buffers[id] = view
@@ -114,7 +131,8 @@ end
114
131
 
115
132
  def gui_set_buffer_contents(id, txt)
116
133
  debug "gui_set_buffer_contents(#{id}, txt)"
117
- vma.gui.buffers[id].buffer.set_text(txt)
134
+ # vma.gui.buffers[id].buffer.set_text(txt)
135
+ vma.gui.buffers[id].set_content(txt)
118
136
  end
119
137
 
120
138
  #TODO: remove
@@ -135,7 +153,7 @@ def gui_set_window_title(wtitle, subtitle = "")
135
153
  end
136
154
 
137
155
  class VMAgui
138
- attr_accessor :buffers, :sw, :sw1, :sw2, :view, :buf1, :window, :delex, :statnfo, :overlay, :overlay1, :overlay2, :sws, :two_c
156
+ attr_accessor :buffers, :sw, :sw1, :sw2, :view, :buf1, :window, :delex, :statnfo, :overlay, :sws, :two_c
139
157
  attr_reader :two_column, :windows, :subtitle, :app
140
158
 
141
159
  def initialize()
@@ -327,7 +345,6 @@ class VMAgui
327
345
  overlay = Gtk::Overlay.new
328
346
  overlay.set_child(sw)
329
347
  @vbox.attach(overlay, 0, 3, 2, 1)
330
- $sw2 = sw
331
348
  sw.set_size_request(-1, 12)
332
349
 
333
350
  view = VSourceView.new(nil, nil)
@@ -465,8 +482,8 @@ class VMAgui
465
482
  end
466
483
  }
467
484
  if to_remove.size > 0
468
- puts "Removing controllers:"
469
- pp to_remove
485
+ # debug "Removing controllers:"
486
+ # pp to_remove
470
487
  to_remove.each { |x| @window.remove_controller(x) }
471
488
  end
472
489
 
@@ -480,7 +497,7 @@ class VMAgui
480
497
  name = Gdk::Keyval.to_name(keyval)
481
498
  uki = Gdk::Keyval.to_unicode(keyval)
482
499
  keystr = uki.chr("UTF-8")
483
- puts "key-pressed #{keyval} #{keycode} name:#{name} str:#{keystr} unicode:#{uki}"
500
+ debug "key pressed #{keyval} #{keycode} name:#{name} str:#{keystr} unicode:#{uki}"
484
501
  buf.view.handle_key_event(keyval, keystr, :key_press)
485
502
  true
486
503
  end
@@ -501,19 +518,16 @@ class VMAgui
501
518
  # button1_mask?
502
519
  # ...
503
520
  # button5_mask?
504
- true
521
+ true # = handled, do not propagate further
505
522
  end
506
523
 
507
524
  press.signal_connect "key-released" do |gesture, keyval, keycode, y|
508
525
  name = Gdk::Keyval.to_name(keyval)
509
526
  uki = Gdk::Keyval.to_unicode(keyval)
510
527
  keystr = uki.chr("UTF-8")
511
- puts "key released #{keyval} #{keycode} name:#{name} str:#{keystr} unicode:#{uki}"
528
+ debug "key released #{keyval} #{keycode} name:#{name} str:#{keystr} unicode:#{uki}"
512
529
  buf.view.handle_key_event(keyval, keystr, :key_release)
513
- # vma.kbd.match_key_conf(keystr, nil, :key_press)
514
- # buf.view.handle_deltas
515
- # buf.view.handle_key_event(keyval, keystr, :key_press)
516
- true
530
+ true # = handled, do not propagate further
517
531
  end
518
532
  end
519
533
 
@@ -527,8 +541,8 @@ class VMAgui
527
541
  end
528
542
  }
529
543
  if to_remove.size > 0
530
- puts "Removing controllers:"
531
- pp to_remove
544
+ # puts "Removing controllers:"
545
+ # pp to_remove
532
546
  to_remove.each { |x| vma.gui.window.remove_controller(x) }
533
547
  end
534
548
  end
@@ -538,9 +552,8 @@ class VMAgui
538
552
  sleep 0.1
539
553
  width = @window.width / 2
540
554
  height = @window.height - 5
541
- # Ripl.start :binding => binding
542
555
  @window.unmaximize
543
- @window.set_size_request(width, height)
556
+ @window.set_default_size(width, height)
544
557
  return false
545
558
  end
546
559
 
@@ -575,7 +588,6 @@ class VMAgui
575
588
  @sw = Gtk::ScrolledWindow.new
576
589
  @sw.set_policy(:automatic, :automatic)
577
590
 
578
-
579
591
  @last_adj_time = Time.now
580
592
  @sw.vadjustment.signal_connect("value-changed") { |x|
581
593
  # pp x.page_increment
@@ -585,17 +597,10 @@ class VMAgui
585
597
  # pp x.value
586
598
  # pp x
587
599
  @last_adj_time = Time.now
588
- # puts "@sw.vadjustment"
589
600
  }
590
601
 
591
- # @sw.signal_connect("clicked") { puts "Hello World!" }
592
- # @sw.signal_connect("key-pressed") { puts "Hello World!" }
593
602
  @overlay = Gtk::Overlay.new
594
- # @overlay.add(@sw) #TODO:gtk4
595
- @overlay.add_overlay(@sw) #TODO:gtk4
596
- @overlay1 = @overlay
597
-
598
- # init_header_bar #TODO:gtk4
603
+ @overlay.add_overlay(@sw)
599
604
 
600
605
  @statnfo = Gtk::Label.new
601
606
  @subtitle = Gtk::Label.new("")
@@ -623,8 +628,6 @@ class VMAgui
623
628
 
624
629
  init_minibuffer
625
630
 
626
- # p = Gtk::Popover.new
627
-
628
631
  name = "save"
629
632
  window = @window
630
633
  action = Gio::SimpleAction.new(name)
@@ -661,16 +664,6 @@ class VMAgui
661
664
 
662
665
  @window.show
663
666
 
664
- press = Gtk::GestureClick.new
665
- press.button = Gdk::BUTTON_SECONDARY
666
- @window.add_controller(press)
667
- press.signal_connect "pressed" do |gesture, n_press, x, y|
668
- puts "FOOBARpressed"
669
- # clear_surface(surface)
670
- # drawing_area.queue_draw
671
- end
672
- @sw1 = @sw
673
-
674
667
  prov = Gtk::CssProvider.new
675
668
  # See gtk-4.9.4/gtk/theme/Default/_common.scss on how to theme
676
669
  # gtksourceview/gtksourcestyleschemepreview.c
@@ -696,6 +689,7 @@ class VMAgui
696
689
  min-width: 15px;
697
690
  }
698
691
 
692
+ popover background > contents { padding: 8px; border-radius: 20px; }
699
693
  ")
700
694
  @window.style_context.add_provider(prov)
701
695
 
@@ -715,6 +709,28 @@ class VMAgui
715
709
  Vimamsa::Menu.new(@menubar, @app)
716
710
  end
717
711
 
712
+ def toggle_two_column
713
+ if @two_column
714
+ set_one_column
715
+ else
716
+ set_two_column
717
+ end
718
+ end
719
+
720
+ def set_one_column
721
+ return if !@two_column
722
+ @windows[2][:sw].set_child(nil)
723
+ @windows.delete(2)
724
+
725
+ @pane.set_start_child(nil)
726
+ @pane.set_end_child(nil)
727
+
728
+ @vbox.remove(@pane)
729
+ @vbox.attach(@overlay, 0, 2, 2, 1)
730
+ @vbox.attach(@statbox, 1, 1, 1, 1)
731
+ @two_column = false
732
+ end
733
+
718
734
  def set_two_column
719
735
  return if @two_column
720
736
  # @window.set_default_size(800, 600) #TODO:gtk4
@@ -732,10 +748,10 @@ class VMAgui
732
748
 
733
749
  @vbox.remove(@overlay)
734
750
 
735
- # numbers: left, top, width, height
736
751
  @pane.set_start_child(@overlay2)
737
752
  @pane.set_end_child(@overlay)
738
753
 
754
+ # numbers: left, top, width, height
739
755
  @vbox.attach(@pane, 0, 2, 2, 1)
740
756
 
741
757
  @sw2.vexpand = true
@@ -747,8 +763,8 @@ class VMAgui
747
763
  @sw2.show
748
764
  @two_column = true
749
765
 
750
- if vma.buffers.size > 1
751
- last = vma.buffers.get_last_visited_id
766
+ last = vma.buffers.get_last_visited_id
767
+ if !last.nil?
752
768
  set_buffer_to_window(last, 2)
753
769
  else
754
770
  bf = create_new_buffer "\n\n", "buff", false
@@ -833,19 +849,53 @@ class VMAgui
833
849
  $vbuf = buf1
834
850
 
835
851
  # Check if buffer is already open in another column
836
- if @two_column and @active_column == 2 and id == @sw1.child.bufo.id
852
+ if @two_column and @active_column == 2 and id == @windows[1][:sw].child.bufo.id
837
853
  toggle_active_window
838
- elsif @two_column && @active_column == 1 && !@sw2.child.nil? && id == @sw2.child.bufo.id
854
+ elsif @two_column && @active_column == 1 && !@windows[2][:sw].child.nil? && id == @windows[2][:sw].child.bufo.id
839
855
  #TODO: should not need !@sw2.child.nil? here. If this happens then other column is empty.
840
856
  toggle_active_window
841
857
  else
858
+ #TODO: improve
859
+ @overlay.remove_overlay(@sw)
860
+ @sw.set_child(nil)
861
+ # Creating a new ScrolledWindow every time to avoid a layout bug
862
+ # https://gitlab.gnome.org/GNOME/gtk/-/issues/6189
863
+ @sw = new_scrolled_window
842
864
  @sw.set_child(view)
865
+ @overlay.add_overlay(@sw)
866
+ @active_window[:sw] = @sw
843
867
  end
844
868
  view.grab_focus
845
869
 
846
870
  idle_ensure_cursor_drawn
847
871
  end
848
872
 
873
+ def new_scrolled_window
874
+ sw = Gtk::ScrolledWindow.new
875
+ sw.set_policy(:automatic, :automatic)
876
+ @last_adj_time = Time.now
877
+ sw.vadjustment.signal_connect("value-changed") { |x|
878
+ @last_adj_time = Time.now
879
+ debug "@sw.vadjustment #{x.value}", 2
880
+ }
881
+ return sw
882
+ end
883
+
884
+ def page_down(multip: 1.0)
885
+ va = @sw.vadjustment
886
+ newval = va.value + va.page_increment * multip
887
+ va.value = newval
888
+ @sw.child.set_cursor_to_top
889
+ end
890
+
891
+ def page_up(multip: 1.0)
892
+ va = @sw.vadjustment
893
+ newval = va.value - va.page_increment * multip
894
+ newval = 0 if newval < 0
895
+ va.value = newval
896
+ @sw.child.set_cursor_to_top
897
+ end
898
+
849
899
  def idle_ensure_cursor_drawn
850
900
  run_as_idle proc { self.ensure_cursor_drawn }
851
901
  end
@@ -1,5 +1,5 @@
1
1
  module Gui
2
- def self.confirm(title, callback)
2
+ def self.confirm(title, callback, param: nil)
3
3
  params = {}
4
4
  params["title"] = title
5
5
  params["inputs"] = {}
@@ -31,6 +31,9 @@ module Vimamsa
31
31
  add_to_menu "Edit.Redo", { :label => "Redo edit", :action => :edit_redo }
32
32
  add_to_menu "Edit.SearchReplace", { :label => "Search and replace", :action => :gui_search_replace }
33
33
  add_to_menu "Edit.Find", { :label => "Find", :action => :find_in_buffer }
34
+
35
+ add_to_menu "Edit.StartCompletion", { :label => "StartCompletion", :action => :start_autocomplete }
36
+ add_to_menu "Edit.ShowCompletion", { :label => "ShowCompletion", :action => :show_autocomplete }
34
37
 
35
38
  add_to_menu "Actions.SearchForActions", { :label => "Search for Actions", :action => :search_actions }
36
39
 
@@ -44,8 +47,9 @@ module Vimamsa
44
47
  add_to_menu "Actions.experimental.DisableDebug", { :label => "Disable debug", :action => :disable_debug }
45
48
  add_to_menu "Actions.experimental.ShowImages", { :label => "Show images ⟦img:path⟧", :action => :show_images }
46
49
 
50
+ add_to_menu "Actions.debug.dumpkbd", { :label => "Dump kbd state", :action => :kbd_dump_state }
47
51
 
48
- add_to_menu "View.TwoColumn", { :label => "Start two column mode", :action => :toggle_two_column }
52
+ add_to_menu "View.TwoColumn", { :label => "Toggle two column mode", :action => :toggle_two_column }
49
53
 
50
54
 
51
55
  add_to_menu "Actions.EncryptFile", { :label => "Encrypt file", :action => :encrypt_file }
@@ -1,6 +1,6 @@
1
1
  # class VSourceView < Gtk::TextView
2
2
  class VSourceView < GtkSource::View
3
- attr_accessor :bufo
3
+ attr_accessor :bufo, :autocp_active, :cpl_list
4
4
  # :highlight_matching_brackets
5
5
 
6
6
  # def set_highlight_current_line(vbool)
@@ -18,7 +18,7 @@ class VSourceView < GtkSource::View
18
18
  @highlight_matching_brackets = true
19
19
  @idle_func_running = false
20
20
  super()
21
- @bufo = bufo #object of Buffer class buffer.rb
21
+ @bufo = bufo #object of Buffer class (buffer.rb)
22
22
  debug "vsource init"
23
23
  @last_keyval = nil
24
24
  @last_event = [nil, nil]
@@ -45,13 +45,14 @@ class VSourceView < GtkSource::View
45
45
  # true
46
46
  # end
47
47
 
48
+ # signal_connect("show-completion") do |x, y, z|
49
+ # debug "SHOW-COMPLETION", 2
50
+ # false
51
+ # end
52
+
48
53
  # Mainly after page-up or page-down
49
54
  signal_connect("move-cursor") do |widget, event|
50
55
  if event.name == "GTK_MOVEMENT_PAGES" and (last_action == "page_up" or last_action == "page_down")
51
- # Ripl.start :binding => binding
52
-
53
- debug("MOVE-CURSOR", 2)
54
- # $update_cursor = true
55
56
  handle_scrolling()
56
57
  end
57
58
 
@@ -77,6 +78,11 @@ class VSourceView < GtkSource::View
77
78
  @curpos_mark = nil
78
79
  end
79
80
 
81
+ def set_content(str)
82
+ delete_cursorchar
83
+ self.buffer.set_text(str)
84
+ end
85
+
80
86
  def gutter_width()
81
87
  winwidth = width
82
88
  view_width = visible_rect.width
@@ -106,8 +112,6 @@ class VSourceView < GtkSource::View
106
112
  end
107
113
  }
108
114
  if to_remove.size > 0
109
- debug "Removing controllers:"
110
- pp to_remove
111
115
  to_remove.each { |x|
112
116
  # To avoid GC. https://github.com/ruby-gnome/ruby-gnome/issues/15790
113
117
  @removed_controllers << x
@@ -138,17 +142,17 @@ class VSourceView < GtkSource::View
138
142
  i = coord_to_iter(x, y, true)
139
143
  pp i
140
144
  @range_start = i
141
- if !buf.visual_mode?
142
- buf.start_visual_mode
143
- end
145
+ buf.start_selection
144
146
  end
145
147
 
146
148
  @cnt_drag.signal_connect "drag-end" do |gesture, offsetx, offsety|
147
149
  debug "drag-end", 2
148
-
149
- # Not enough drag
150
150
  if offsetx.abs < 5 and offsety.abs < 5
151
- buf.end_visual_mode
151
+ debug "Not enough drag",2
152
+ @range_start = nil
153
+ elsif !buf.visual_mode? and vma.kbd.get_scope != :editor
154
+ # Can't transition from editor wide mode to buffer specific mode
155
+ buf.start_visual_mode
152
156
  end
153
157
  @range_start = nil
154
158
  end
@@ -228,6 +232,7 @@ class VSourceView < GtkSource::View
228
232
  end
229
233
 
230
234
  def handle_scrolling()
235
+ return # TODO
231
236
  delete_cursorchar
232
237
  # curpos = buffer.cursor_position
233
238
  # debug "MOVE CURSOR: #{curpos}"
@@ -247,6 +252,19 @@ class VSourceView < GtkSource::View
247
252
  }
248
253
  end
249
254
 
255
+ def set_cursor_to_top
256
+ debug "set_cursor_to_top", 2
257
+ delete_cursorchar
258
+ bc = window_to_buffer_coords(Gtk::TextWindowType::WIDGET, gutter_width + 2, 60)
259
+ if !bc.nil?
260
+ i = coord_to_iter(bc[0], bc[1])
261
+ if !i.nil?
262
+ @bufo.set_pos(i)
263
+ set_cursor_pos(i)
264
+ end
265
+ end
266
+ end
267
+
250
268
  # def handle_key_event(event, sig)
251
269
  def handle_key_event(keyval, keyname, sig)
252
270
  delete_cursorchar
@@ -291,7 +309,7 @@ class VSourceView < GtkSource::View
291
309
  keyval_trans[Gdk::Keyval::KEY_Shift_L] = "shift"
292
310
  keyval_trans[Gdk::Keyval::KEY_Shift_R] = "shift"
293
311
  keyval_trans[Gdk::Keyval::KEY_Tab] = "tab"
294
- keyval_trans[Gdk::Keyval::GDK_KEY_ISO_Left_Tab] = "tab"
312
+ keyval_trans[Gdk::Keyval::KEY_ISO_Left_Tab] = "tab"
295
313
 
296
314
  key_trans = {}
297
315
  key_trans["\e"] = "esc"
@@ -368,6 +386,10 @@ class VSourceView < GtkSource::View
368
386
  return [x, y]
369
387
  end
370
388
 
389
+ def cur_pos_xy
390
+ return pos_to_coord(buffer.cursor_position)
391
+ end
392
+
371
393
  def handle_deltas()
372
394
  delete_cursorchar
373
395
  any_change = false
@@ -411,7 +433,6 @@ class VSourceView < GtkSource::View
411
433
 
412
434
  def set_cursor_pos(pos)
413
435
  delete_cursorchar
414
- # return
415
436
  itr = buffer.get_iter_at(:offset => pos)
416
437
  itr2 = buffer.get_iter_at(:offset => pos + 1)
417
438
  buffer.place_cursor(itr)
@@ -436,7 +457,7 @@ class VSourceView < GtkSource::View
436
457
  end
437
458
 
438
459
  def cursor_visible_idle_func
439
- return false
460
+ # return false
440
461
  debug "cursor_visible_idle_func"
441
462
  # From https://picheta.me/articles/2013/08/gtk-plus--a-method-to-guarantee-scrolling.html
442
463
 
@@ -0,0 +1,141 @@
1
+ # require "trie"
2
+ require "rambling-trie"
3
+
4
+ class Autocomplete
5
+ @@trie = Rambling::Trie.create
6
+
7
+ def self.init
8
+ vma.hook.register(:file_saved, self.method("update_index"))
9
+ end
10
+
11
+ def self.update_index(bu)
12
+ debug "self.update_index", 2
13
+ add_words bu.scan_all_words
14
+ end
15
+
16
+ def self.update_dict
17
+ for bu in vma.buffers.list
18
+ for w in bu.scan_all_words
19
+ trie << w
20
+ end
21
+ end
22
+ @@trie = trie
23
+ end
24
+
25
+ def self.add_words(words)
26
+ for w in words
27
+ @@trie << w
28
+ end
29
+ end
30
+
31
+ def self.word_list
32
+ return @@dict.keys
33
+ end
34
+
35
+ def self.matching_words(beginning)
36
+ return @@trie.scan(beginning)
37
+ end
38
+ end
39
+
40
+ class VSourceView < GtkSource::View
41
+ def hide_completions
42
+ if @acwin.class == Gtk::Popover
43
+ @acwin.hide
44
+ end
45
+ @autocp_active = false
46
+ end
47
+
48
+ def autocp_select
49
+ return if !@autocp_active
50
+ bufo.complete_current_word(@cpl_list[@autocp_selected])
51
+ autocp_exit
52
+ end
53
+
54
+ def autocp_select_previous
55
+ return if @autocp_selected <= 0
56
+ autocp_hilight(@autocp_selected)
57
+ autocp_unhilight(@autocp_selected)
58
+ @autocp_selected -= 1
59
+ autocp_hilight(@autocp_selected)
60
+ end
61
+
62
+ def autocp_hilight(id)
63
+ l = @autocp_items[id]
64
+ l.set_text("<span foreground='#00ff00' weight='ultrabold'>#{cpl_list[id]}</span>")
65
+ l.use_markup = true
66
+ end
67
+
68
+ def autocp_unhilight(id)
69
+ l = @autocp_items[id]
70
+ l.set_text("<span>#{cpl_list[id]}</span>")
71
+ l.use_markup = true
72
+ end
73
+
74
+ def autocp_select_next
75
+ return if @autocp_selected >= cpl_list.size - 1
76
+ debug "autocp_select_next", 2
77
+ autocp_unhilight(@autocp_selected)
78
+ @autocp_selected += 1
79
+ autocp_hilight(@autocp_selected)
80
+ end
81
+
82
+ def autocp_exit
83
+ @autocp_items = []
84
+ @autocp_active = true
85
+ hide_completions
86
+ end
87
+
88
+ def try_autocomplete
89
+ end
90
+
91
+ def show_completions
92
+ hide_completions
93
+ bu = vma.buf
94
+ (w, range) = bu.get_word_in_pos(bu.pos - 1, boundary: :word)
95
+ debug [w, range].to_s, 2
96
+ matches = Autocomplete.matching_words w
97
+ return if matches.empty?
98
+ @autocp_active = true
99
+ @cpl_list = cpl_list = matches
100
+ win = Gtk::Popover.new()
101
+ win.parent = self
102
+ vbox = Gtk::Grid.new()
103
+ win.set_child(vbox)
104
+
105
+ i = 0
106
+ @autocp_items = []
107
+ @autocp_selected = 0
108
+ for x in cpl_list
109
+ l = Gtk::Label.new(x)
110
+ @autocp_items << l
111
+ # numbers: left, top, width, height
112
+ vbox.attach(l, 0, i, 1, 1)
113
+ i += 1
114
+ end
115
+ autocp_hilight(0)
116
+ (x, y) = cur_pos_xy
117
+ rec = Gdk::Rectangle.new(x, y + 8, 10, 10)
118
+ win.has_arrow = false
119
+ win.set_pointing_to(rec)
120
+ win.autohide = false
121
+ win.popup
122
+ gui_remove_controllers(win)
123
+ @acwin = win
124
+ end
125
+
126
+ def start_autocomplete
127
+ return
128
+ # Roughly following these examples:
129
+ # https://stackoverflow.com/questions/52359721/howto-maintain-gtksourcecompletion-when-changing-buffers-in-a-gtksourceview
130
+ # and gedit-plugins-41.0/plugins/wordcompletion/gedit-word-completion-plugin.c
131
+ # .. but it doesn't work. So implementing using Popover.
132
+ # Keeping this for reference
133
+
134
+ cp = self.completion
135
+ prov = GtkSource::CompletionWords.new("Autocomplete") # (name,icon)
136
+ prov.register(self.buffer)
137
+ cp.add_provider(prov)
138
+ pp prov
139
+ self.show_completion
140
+ end
141
+ end
@@ -1,11 +1,41 @@
1
1
  module Gui
2
- def self.highlight_match(bf, str, color: "#aa0000ff")
2
+ def self.hilight_range(bf, r, color: "#aa0000ff", weight: nil, tag: nil)
3
+ vbuf = bf.view.buffer
4
+
5
+ if tag.nil?
6
+ tag = vma.gui.view.buffer.create_tag
7
+ tag.weight = weight if !weight.nil?
8
+ tag.foreground = color
9
+ end
10
+
11
+ itr = vbuf.get_iter_at(:offset => r.begin)
12
+ itr2 = vbuf.get_iter_at(:offset => r.last)
13
+ vbuf.apply_tag(tag, itr, itr2)
14
+ end
15
+
16
+ def self.highlight_match(bf, str, color: "#aa0000ff", weight: 650)
17
+ r = Regexp.new(Regexp.escape(str), Regexp::IGNORECASE)
18
+ tag = vma.gui.view.buffer.create_tag
19
+ tag.weight = weight
20
+ tag.foreground = color
21
+ ind = scan_indexes(bf, r)
22
+ ind.each { |x|
23
+ r = x..(x + str.size)
24
+ self.hilight_range(bf, r, tag: tag)
25
+ }
26
+ end
27
+
28
+ def self.highlight_match_old(bf, str, color: "#aa0000ff")
3
29
  vbuf = bf.view.buffer
4
30
  r = Regexp.new(Regexp.escape(str), Regexp::IGNORECASE)
5
31
 
6
32
  hlparts = []
7
33
 
8
- tt = vma.gui.view.buffer.create_tag("highlight_match_tag")
34
+ tt = vma.gui.view.buffer.tag_table.lookup("highlight_match_tag")
35
+ if tt.nil?
36
+ tt = vma.gui.view.buffer.create_tag("highlight_match_tag")
37
+ end
38
+
9
39
  tt.weight = 650
10
40
  tt.foreground = color
11
41
 
@@ -39,12 +39,23 @@ def hpt_check_cur_word(w)
39
39
  # return true
40
40
  else
41
41
  message "File not found: #{fpfx}"
42
+ newfn = fcands[0]
43
+ if File.extname(newfn) == ""
44
+ newfn = fcands[1]
45
+ end
46
+ Gui.confirm("File does not exist. Create a new file? \r #{newfn}",
47
+ proc{hpt_create_new_file(newfn)})
48
+
42
49
  end
43
50
  end
44
51
  end
45
52
  return nil
46
53
  end
47
54
 
55
+ def hpt_create_new_file(fn)
56
+ create_new_file(fn)
57
+ end
58
+
48
59
  def translate_path(fn, bf)
49
60
  if File.exist?(fn)
50
61
  outfn = fn