vimamsa 0.1.22 → 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/custom_example.rb +4 -1
- data/img/screenshot1.png +0 -0
- data/img/screenshot2.png +0 -0
- data/lib/vimamsa/buffer.rb +129 -8
- data/lib/vimamsa/buffer_changetext.rb +19 -2
- data/lib/vimamsa/buffer_cursor.rb +9 -3
- data/lib/vimamsa/buffer_list.rb +12 -0
- data/lib/vimamsa/buffer_manager.rb +1 -1
- data/lib/vimamsa/conf.rb +3 -1
- data/lib/vimamsa/diff_buffer.rb +137 -0
- data/lib/vimamsa/editor.rb +98 -16
- data/lib/vimamsa/gui.rb +93 -82
- data/lib/vimamsa/gui_dialog.rb +2 -0
- data/lib/vimamsa/gui_file_panel.rb +93 -0
- data/lib/vimamsa/gui_form_generator.rb +4 -2
- data/lib/vimamsa/gui_image.rb +2 -4
- data/lib/vimamsa/gui_menu.rb +12 -1
- data/lib/vimamsa/gui_select_window.rb +1 -0
- data/lib/vimamsa/gui_settings.rb +155 -0
- data/lib/vimamsa/gui_sourceview.rb +80 -6
- data/lib/vimamsa/key_actions.rb +32 -10
- data/lib/vimamsa/key_binding_tree.rb +72 -8
- data/lib/vimamsa/key_bindings_vimlike.rb +44 -35
- data/lib/vimamsa/main.rb +1 -0
- data/lib/vimamsa/rbvma.rb +3 -0
- data/lib/vimamsa/string_util.rb +56 -0
- data/lib/vimamsa/util.rb +3 -36
- data/lib/vimamsa/version.rb +1 -1
- metadata +8 -2
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
SETTINGS_DEFS = [
|
|
2
|
+
{
|
|
3
|
+
:label => "Tab / Indent",
|
|
4
|
+
:settings => [
|
|
5
|
+
{ :key => [:tab, :width], :label => "Tab width", :type => :int, :min => 1, :max => 16, :step => 1 },
|
|
6
|
+
{ :key => [:tab, :to_spaces_default], :label => "Use spaces instead of tabs (default)", :type => :bool },
|
|
7
|
+
{ :key => [:indent_based_on_last_line], :label => "Auto-indent based on last line", :type => :bool },
|
|
8
|
+
],
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
:label => "Font",
|
|
12
|
+
:settings => [
|
|
13
|
+
{ :key => [:font, :family], :label => "Font family", :type => :string },
|
|
14
|
+
{ :key => [:font, :size], :label => "Font size (pt)", :type => :int, :min => 4, :max => 72, :step => 1 },
|
|
15
|
+
],
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
:label => "Appearance",
|
|
19
|
+
:settings => [
|
|
20
|
+
{ :key => [:match, :highlight, :color], :label => "Search highlight color", :type => :string },
|
|
21
|
+
{ :key => [:kbd, :show_prev_action], :label => "Show previous action in toolbar", :type => :bool },
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
:label => "Behavior",
|
|
26
|
+
:settings => [
|
|
27
|
+
{ :key => [:lsp, :enabled], :label => "Enable LSP (Language Server)", :type => :bool },
|
|
28
|
+
{ :key => [:experimental], :label => "Enable experimental features", :type => :bool },
|
|
29
|
+
{ :key => [:macro, :animation_delay], :label => "Macro animation delay (sec)", :type => :float, :min => 0.0, :max => 2.0, :step => 0.0001 },
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
class SettingsDialog
|
|
35
|
+
def initialize
|
|
36
|
+
@widgets = {}
|
|
37
|
+
@window = Gtk::Window.new
|
|
38
|
+
@window.set_transient_for($vmag.window) if $vmag&.window
|
|
39
|
+
@window.modal = true
|
|
40
|
+
@window.title = "Preferences"
|
|
41
|
+
@window.default_width = 500
|
|
42
|
+
|
|
43
|
+
outer = Gtk::Box.new(:vertical, 12)
|
|
44
|
+
# outer.margin = 16
|
|
45
|
+
@window.set_child(outer)
|
|
46
|
+
|
|
47
|
+
notebook = Gtk::Notebook.new
|
|
48
|
+
outer.append(notebook)
|
|
49
|
+
|
|
50
|
+
SETTINGS_DEFS.each do |section|
|
|
51
|
+
grid = Gtk::Grid.new
|
|
52
|
+
grid.row_spacing = 10
|
|
53
|
+
grid.column_spacing = 16
|
|
54
|
+
grid.margin_top = 12
|
|
55
|
+
grid.margin_bottom = 12
|
|
56
|
+
grid.margin_start = 12
|
|
57
|
+
grid.margin_end = 12
|
|
58
|
+
|
|
59
|
+
section[:settings].each_with_index do |s, row|
|
|
60
|
+
label = Gtk::Label.new(s[:label])
|
|
61
|
+
label.halign = :start
|
|
62
|
+
label.hexpand = true
|
|
63
|
+
|
|
64
|
+
widget = make_widget(s)
|
|
65
|
+
@widgets[s[:key]] = { :widget => widget, :type => s[:type] }
|
|
66
|
+
|
|
67
|
+
grid.attach(label, 0, row, 1, 1)
|
|
68
|
+
grid.attach(widget, 1, row, 1, 1)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
notebook.append_page(grid, Gtk::Label.new(section[:label]))
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
hbox = Gtk::Box.new(:horizontal, 8)
|
|
75
|
+
hbox.halign = :end
|
|
76
|
+
|
|
77
|
+
cancel_btn = Gtk::Button.new(:label => "Cancel")
|
|
78
|
+
save_btn = Gtk::Button.new(:label => "Save")
|
|
79
|
+
cancel_btn.signal_connect("clicked") { @window.destroy }
|
|
80
|
+
save_btn.signal_connect("clicked") { save_and_close }
|
|
81
|
+
|
|
82
|
+
hbox.append(cancel_btn)
|
|
83
|
+
hbox.append(save_btn)
|
|
84
|
+
outer.append(hbox)
|
|
85
|
+
|
|
86
|
+
press = Gtk::EventControllerKey.new
|
|
87
|
+
press.set_propagation_phase(Gtk::PropagationPhase::CAPTURE)
|
|
88
|
+
@window.add_controller(press)
|
|
89
|
+
press.signal_connect("key-pressed") do |_g, keyval, _kc, _y|
|
|
90
|
+
if keyval == Gdk::Keyval::KEY_Escape
|
|
91
|
+
@window.destroy
|
|
92
|
+
true
|
|
93
|
+
else
|
|
94
|
+
false
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def make_widget(s)
|
|
100
|
+
cur = get(s[:key])
|
|
101
|
+
case s[:type]
|
|
102
|
+
when :bool
|
|
103
|
+
w = Gtk::Switch.new
|
|
104
|
+
w.active = cur == true
|
|
105
|
+
w.valign = :center
|
|
106
|
+
w
|
|
107
|
+
when :int
|
|
108
|
+
adj = Gtk::Adjustment.new(cur.to_f, s[:min].to_f, s[:max].to_f, s[:step].to_f, s[:step].to_f * 5, 0.0)
|
|
109
|
+
Gtk::SpinButton.new(adj, s[:step].to_f, 0)
|
|
110
|
+
when :float
|
|
111
|
+
adj = Gtk::Adjustment.new(cur.to_f, s[:min].to_f, s[:max].to_f, s[:step].to_f, s[:step].to_f * 5, 0.0)
|
|
112
|
+
digits = s[:step].to_s.split(".").last.to_s.length
|
|
113
|
+
digits = 2 if digits < 2
|
|
114
|
+
Gtk::SpinButton.new(adj, s[:step].to_f, digits)
|
|
115
|
+
when :string
|
|
116
|
+
w = Gtk::Entry.new
|
|
117
|
+
w.text = cur.to_s
|
|
118
|
+
w
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def save_and_close
|
|
123
|
+
@widgets.each do |key, info|
|
|
124
|
+
val = case info[:type]
|
|
125
|
+
when :bool then info[:widget].active?
|
|
126
|
+
when :int then info[:widget].value.to_i
|
|
127
|
+
when :float then info[:widget].value.to_f
|
|
128
|
+
when :string then info[:widget].text
|
|
129
|
+
end
|
|
130
|
+
set(key, val)
|
|
131
|
+
end
|
|
132
|
+
save_settings_to_file
|
|
133
|
+
gui_refresh_font
|
|
134
|
+
@window.destroy
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def run
|
|
138
|
+
@window.show
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def show_settings_dialog
|
|
143
|
+
SettingsDialog.new.run
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def gui_refresh_font
|
|
147
|
+
return unless $vmag
|
|
148
|
+
provider = Gtk::CssProvider.new
|
|
149
|
+
provider.load(data: "textview { font-family: #{get(cnf.font.family)}; font-size: #{get(cnf.font.size)}pt; }")
|
|
150
|
+
for _k, window in $vmag.windows
|
|
151
|
+
view = window[:sw].child
|
|
152
|
+
next if view.nil?
|
|
153
|
+
view.style_context.add_provider(provider)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
class VSourceView < GtkSource::View
|
|
3
3
|
attr_accessor :bufo, :autocp_active, :cpl_list
|
|
4
4
|
|
|
5
|
-
|
|
6
5
|
# def initialize(title = nil,bufo=nil)
|
|
7
6
|
def initialize(title, bufo)
|
|
8
7
|
# super(:toplevel)
|
|
@@ -19,6 +18,7 @@ class VSourceView < GtkSource::View
|
|
|
19
18
|
@tt = nil
|
|
20
19
|
|
|
21
20
|
# Mainly after page-up or page-down
|
|
21
|
+
|
|
22
22
|
signal_connect("move-cursor") do |widget, event|
|
|
23
23
|
# if event.name == "GTK_MOVEMENT_PAGES" and (vma.actions.last_action == "page_up" or vma.actions.last_action == "page_down")
|
|
24
24
|
# handle_scrolling()
|
|
@@ -174,9 +174,24 @@ class VSourceView < GtkSource::View
|
|
|
174
174
|
i = coord_to_iter(x, y, true)
|
|
175
175
|
pp i
|
|
176
176
|
@range_start = i
|
|
177
|
+
@drag_start_x = x
|
|
178
|
+
@drag_start_y = y
|
|
177
179
|
buf.start_selection
|
|
178
180
|
end
|
|
179
181
|
|
|
182
|
+
@cnt_drag.signal_connect "drag-update" do |gesture, offset_x, offset_y|
|
|
183
|
+
next unless @range_start
|
|
184
|
+
cur_x = @drag_start_x + offset_x
|
|
185
|
+
cur_y = @drag_start_y + offset_y
|
|
186
|
+
debug "drag-update 2 #{cur_x} #{cur_y}"
|
|
187
|
+
i = coord_to_iter(cur_x, cur_y, true)
|
|
188
|
+
@bufo.set_pos(i) if !i.nil? and @last_iter != i
|
|
189
|
+
if !i.nil? and (@range_start - i).abs >= 2
|
|
190
|
+
vma.kbd.set_mode(:visual)
|
|
191
|
+
end
|
|
192
|
+
@last_iter = i
|
|
193
|
+
end
|
|
194
|
+
|
|
180
195
|
@cnt_drag.signal_connect "drag-end" do |gesture, offsetx, offsety|
|
|
181
196
|
debug "drag-end", 2
|
|
182
197
|
if offsetx.abs < 5 and offsety.abs < 5
|
|
@@ -186,8 +201,7 @@ class VSourceView < GtkSource::View
|
|
|
186
201
|
elsif vma.kbd.get_scope != :editor
|
|
187
202
|
# Can't transition from editor wide mode to buffer specific mode
|
|
188
203
|
vma.kbd.set_mode(:visual)
|
|
189
|
-
else
|
|
190
|
-
buf.end_selection
|
|
204
|
+
else # The normal case
|
|
191
205
|
end
|
|
192
206
|
@range_start = nil
|
|
193
207
|
end
|
|
@@ -199,6 +213,19 @@ class VSourceView < GtkSource::View
|
|
|
199
213
|
@click = click
|
|
200
214
|
|
|
201
215
|
@range_start = nil
|
|
216
|
+
|
|
217
|
+
# Handle right click
|
|
218
|
+
rightclick = Gtk::GestureClick.new
|
|
219
|
+
rightclick.button = 3
|
|
220
|
+
self.add_controller(rightclick)
|
|
221
|
+
rightclick.signal_connect "pressed" do |gesture, n_press, x, y, z|
|
|
222
|
+
puts "SourceView, GestureClick rightclick released button=#{gesture.button} x=#{x} y=#{y}"
|
|
223
|
+
if gesture.button == 3
|
|
224
|
+
show_context_menu(x, y)
|
|
225
|
+
next true
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
202
229
|
click.signal_connect "pressed" do |gesture, n_press, x, y, z|
|
|
203
230
|
debug "SourceView, GestureClick released x=#{x} y=#{y}"
|
|
204
231
|
|
|
@@ -219,11 +246,19 @@ class VSourceView < GtkSource::View
|
|
|
219
246
|
end
|
|
220
247
|
|
|
221
248
|
@bufo.set_pos(i) if !i.nil?
|
|
249
|
+
if n_press == 2
|
|
250
|
+
#TODO: refactor to have one function for all line actions
|
|
251
|
+
if @bufo.module&.respond_to?(:select_line)
|
|
252
|
+
@bufo.module.select_line
|
|
253
|
+
else
|
|
254
|
+
@bufo.cur_nonwhitespace_word_action()
|
|
255
|
+
end
|
|
256
|
+
end
|
|
222
257
|
true
|
|
223
258
|
end
|
|
224
259
|
|
|
225
260
|
click.signal_connect "released" do |gesture, n_press, x, y, z|
|
|
226
|
-
debug "SourceView, GestureClick released x=#{x} y=#{y}"
|
|
261
|
+
debug "SourceView, GestureClick released x=#{x} y=#{y} button=#{gesture.button}"
|
|
227
262
|
|
|
228
263
|
xloc = (x - gutter_width).to_i
|
|
229
264
|
yloc = (y + visible_rect.y).to_i
|
|
@@ -587,7 +622,7 @@ class VSourceView < GtkSource::View
|
|
|
587
622
|
|
|
588
623
|
mode = vma.kbd.get_mode
|
|
589
624
|
ctype = vma.kbd.get_cursor_type
|
|
590
|
-
ctype = :visual if
|
|
625
|
+
ctype = :visual if @bufo.selection_active?
|
|
591
626
|
|
|
592
627
|
if [:command, :replace, :browse].include?(ctype)
|
|
593
628
|
set_cursor_color(ctype)
|
|
@@ -632,5 +667,44 @@ class VSourceView < GtkSource::View
|
|
|
632
667
|
self.cursor_visible = true
|
|
633
668
|
end
|
|
634
669
|
end #end draw_cursor
|
|
635
|
-
end
|
|
636
670
|
|
|
671
|
+
CONTEXT_MENU_ITEMS = [
|
|
672
|
+
["Paste", :paste_after_cursor],
|
|
673
|
+
["Previous buffer", :history_switch_backwards],
|
|
674
|
+
]
|
|
675
|
+
|
|
676
|
+
CONTEXT_MENU_ITEMS_SELECTION = [
|
|
677
|
+
["Copy", :copy_selection],
|
|
678
|
+
["Cut", :cut_selection],
|
|
679
|
+
]
|
|
680
|
+
|
|
681
|
+
def init_context_menu
|
|
682
|
+
all_items = CONTEXT_MENU_ITEMS + CONTEXT_MENU_ITEMS_SELECTION
|
|
683
|
+
all_items.each do |label, action_id|
|
|
684
|
+
actkey = "ctx_#{action_id}"
|
|
685
|
+
unless vma.gui.app.lookup_action(actkey)
|
|
686
|
+
act = Gio::SimpleAction.new(actkey)
|
|
687
|
+
vma.gui.app.add_action(act)
|
|
688
|
+
act.signal_connect("activate") do
|
|
689
|
+
call_action(action_id)
|
|
690
|
+
after_action
|
|
691
|
+
end
|
|
692
|
+
end
|
|
693
|
+
end
|
|
694
|
+
@context_menu = Gtk::PopoverMenu.new
|
|
695
|
+
@context_menu.set_parent(self)
|
|
696
|
+
@context_menu.has_arrow = false
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
def show_context_menu(x, y)
|
|
700
|
+
init_context_menu if @context_menu.nil?
|
|
701
|
+
menu = Gio::Menu.new
|
|
702
|
+
CONTEXT_MENU_ITEMS.each { |label, action_id| menu.append(label, "app.ctx_#{action_id}") }
|
|
703
|
+
if @bufo.selection_active?
|
|
704
|
+
CONTEXT_MENU_ITEMS_SELECTION.each { |label, action_id| menu.append(label, "app.ctx_#{action_id}") }
|
|
705
|
+
end
|
|
706
|
+
@context_menu.set_menu_model(menu)
|
|
707
|
+
@context_menu.set_pointing_to(Gdk::Rectangle.new(x.to_i, y.to_i, 1, 1))
|
|
708
|
+
@context_menu.popup
|
|
709
|
+
end
|
|
710
|
+
end
|
data/lib/vimamsa/key_actions.rb
CHANGED
|
@@ -35,9 +35,19 @@ reg_act(:lsp_jump_to_definition, proc { vma.buf.lsp_jump_to_def }, "LSP jump to
|
|
|
35
35
|
|
|
36
36
|
reg_act(:eval_buf, proc { vma.buf.eval_whole_buf }, "Eval whole current buffer as ruby code (DANGEROUS)")
|
|
37
37
|
|
|
38
|
+
reg_act(:show_settings, proc { show_settings_dialog }, "Show settings")
|
|
39
|
+
reg_act(:cut_selection, proc { buf.delete(SELECTION) }, "Cut selection to clipboard")
|
|
40
|
+
|
|
41
|
+
reg_act(:insert_backspace, proc { buf.selection_active? ? buf.delete(SELECTION) : buf.delete(BACKWARD_CHAR) }, "Delete backwards")
|
|
42
|
+
reg_act(:insert_select_up, proc { insert_select_move(BACKWARD_LINE) }, "Select texte upwards")
|
|
43
|
+
reg_act(:insert_select_down, proc { insert_select_move(BACKWARD_CHAR) }, "Select text downwards")
|
|
44
|
+
|
|
45
|
+
reg_act(:copy_selection, proc { buf.copy_active_selection }, "Copy selection to clipboard")
|
|
38
46
|
reg_act(:enable_debug, proc { cnf.debug = true }, "Enable debug")
|
|
39
47
|
reg_act(:disable_debug, proc { cnf.debug = false }, "Disable debug")
|
|
40
48
|
|
|
49
|
+
reg_act(:experimental_eval, proc { bindkey "V , e", "vma.buf.convert_selected_text(:eval)" }, "Enable key binding:\"[VISUAL] , e:\" Eval selected text")
|
|
50
|
+
|
|
41
51
|
reg_act(:easy_jump, proc { EasyJump.start }, "Easy jump")
|
|
42
52
|
reg_act(:gui_ensure_cursor_visible, proc { vma.gui.view.ensure_cursor_visible }, "Scroll to current cursor position")
|
|
43
53
|
reg_act(:gui_refresh_cursor, proc { vma.buf.refresh_cursor }, "Refresh cursor")
|
|
@@ -46,17 +56,18 @@ reg_act(:savedebug, "savedebug", "Save debug info", { :group => :debug })
|
|
|
46
56
|
reg_act(:open_file_dialog, "open_file_dialog", "Open file", { :group => :file })
|
|
47
57
|
reg_act(:create_new_file, "create_new_file", "Create new file", { :group => :file })
|
|
48
58
|
reg_act(:backup_all_buffers, proc { backup_all_buffers }, "Backup all buffers", { :group => :file })
|
|
49
|
-
reg_act(:e_move_forward_char, "e_move_forward_char", "", { :group => [:move, :basic] })
|
|
50
|
-
reg_act(:e_move_backward_char, "e_move_backward_char", "", { :group => [:move, :basic] })
|
|
59
|
+
reg_act(:e_move_forward_char, "e_move_forward_char", "Move forward", { :group => [:move, :basic] })
|
|
60
|
+
reg_act(:e_move_backward_char, "e_move_backward_char", "Move forward", { :group => [:move, :basic] })
|
|
51
61
|
# reg_act(:history_switch_backwards, proc{bufs.history_switch_backwards}, "", { :group => :file })
|
|
52
|
-
reg_act(:history_switch_backwards, proc{bufs.history_switch(-1)}, "", { :group => :file })
|
|
53
|
-
reg_act(:history_switch_forwards, proc{bufs.history_switch(+1)}, "", { :group => :file })
|
|
62
|
+
reg_act(:history_switch_backwards, proc{bufs.history_switch(-1)}, "Prev buffer", { :group => :file })
|
|
63
|
+
reg_act(:history_switch_forwards, proc{bufs.history_switch(+1)}, "Next buffer", { :group => :file })
|
|
64
|
+
reg_act(:print_buffer_access_list, proc { bufs.print_by_access_time }, "Print buffers by access time", { :group => :file })
|
|
54
65
|
reg_act(:center_on_current_line, "center_on_current_line", "", { :group => :view })
|
|
55
66
|
reg_act(:run_last_macro, proc { vma.macro.run_last_macro }, "Run last recorded or executed macro", { :group => :macro })
|
|
56
|
-
reg_act(:jump_to_next_edit, "jump_to_next_edit", "")
|
|
57
|
-
reg_act(:jump_to_last_edit, proc { buf.jump_to_last_edit }, "")
|
|
67
|
+
reg_act(:jump_to_next_edit, "jump_to_next_edit", "Jump to next edit pos")
|
|
68
|
+
reg_act(:jump_to_last_edit, proc { buf.jump_to_last_edit }, "Jump to last edit pos")
|
|
58
69
|
reg_act(:jump_to_random, proc { buf.jump_to_random_pos }, "")
|
|
59
|
-
reg_act(:insert_new_line, proc { buf.insert_new_line() }, "")
|
|
70
|
+
reg_act(:insert_new_line, proc { buf.insert_new_line() }, "Insert new line")
|
|
60
71
|
reg_act(:show_key_bindings, proc { show_key_bindings }, "Show key bindings")
|
|
61
72
|
reg_act(:put_file_path_to_clipboard, proc { buf.put_file_path_to_clipboard }, "Put file path of current file to clipboard")
|
|
62
73
|
reg_act(:put_file_ref_to_clipboard, proc { buf.put_file_ref_to_clipboard }, "Put file ref of current file to clipboard")
|
|
@@ -67,11 +78,15 @@ reg_act(:set_unencrypted, proc { buf.set_unencrypted }, "Set current file to sav
|
|
|
67
78
|
reg_act(:set_executable, proc { buf.set_executable }, "Set current file permissions to executable")
|
|
68
79
|
# reg_act(:close_all_buffers, proc { bufs.close_all_buffers() }, "Close all buffers")
|
|
69
80
|
reg_act(:close_current_buffer, proc { bufs.close_current_buffer(true) }, "Close current buffer")
|
|
70
|
-
reg_act(:
|
|
81
|
+
reg_act(:toggle_file_panel, proc { vma.gui.toggle_file_panel }, "Toggle file panel")
|
|
82
|
+
reg_act(:comment_selection, proc { buf.comment_selection }, "Comment selection")
|
|
71
83
|
reg_act(:delete_char_forward, proc { buf.delete(CURRENT_CHAR_FORWARD) }, "Delete char forward", { :group => [:edit, :basic] })
|
|
72
84
|
reg_act(:gui_file_finder, proc { vma.FileFinder.start_gui }, "Fuzzy file finder")
|
|
73
85
|
reg_act(:gui_file_history_finder, proc { vma.FileHistory.start_gui }, "Fuzzy file history finder")
|
|
74
86
|
reg_act(:gui_search_replace, proc { gui_search_replace }, "Search and replace")
|
|
87
|
+
reg_act(:find_next, proc { $search.jump_to_next() }, "Find next")
|
|
88
|
+
|
|
89
|
+
|
|
75
90
|
reg_act(:set_style_bold, proc { buf.style_transform(:bold) }, "Set text weight to bold")
|
|
76
91
|
reg_act(:set_style_link, proc { buf.style_transform(:link) }, "Set text as link")
|
|
77
92
|
reg_act(:V_join_lines, proc { vma.buf.convert_selected_text(:joinlines) }, "Join lines")
|
|
@@ -87,8 +102,10 @@ reg_act(:clear_line_styles, proc { buf.set_line_style(:clear) }, "Clear styles o
|
|
|
87
102
|
reg_act(:gui_select_buffer, proc { vma.kbd.set_mode("S"); gui_select_buffer }, "Select buffer")
|
|
88
103
|
reg_act :open_file_dialog, "open_file_dialog", "Open file"
|
|
89
104
|
reg_act :minibuffer_end, proc { minibuffer_end }
|
|
90
|
-
reg_act(:invoke_replace, "invoke_replace", "")
|
|
105
|
+
reg_act(:invoke_replace, "invoke_replace", "Invoke replace")
|
|
91
106
|
reg_act(:diff_buffer, "diff_buffer", "")
|
|
107
|
+
reg_act(:git_diff_buffer, proc { git_diff_buffer }, "Show git diff of current file")
|
|
108
|
+
reg_act(:diff_buffer_jump_to_source, proc { diff_buffer_jump_to_source }, "Jump to corresponding line in source from diff buffer")
|
|
92
109
|
# reg_act(:invoke_grep_search, proc{invoke_grep_search}, "")
|
|
93
110
|
reg_act(:invoke_grep_search, proc { gui_grep }, "Grep current buffer")
|
|
94
111
|
reg_act(:ack_search, proc { gui_ack }, "") #invoke_ack_search
|
|
@@ -98,7 +115,7 @@ reg_act :delete_to_next_word_start, proc { buf.delete2(:to_next_word) }, "Delete
|
|
|
98
115
|
reg_act :delete_to_line_start, proc { buf.delete2(:to_line_start) }, "Delete to line start", { :group => [:edit, :basic] }
|
|
99
116
|
|
|
100
117
|
|
|
101
|
-
reg_act(:ack_search, proc { gui_ack }, "")
|
|
118
|
+
reg_act(:ack_search, proc { gui_ack }, "Ack")
|
|
102
119
|
|
|
103
120
|
reg_act(:copy_cur_line, proc {buf.copy_line}, "Copy the current line")
|
|
104
121
|
reg_act(:paste_before_cursor, proc {buf.paste(BEFORE)}, "Paste text before the cursor")
|
|
@@ -119,6 +136,8 @@ reg_act(:move_next_line, proc { buf.move(FORWARD_LINE) }, "Move the cursor to th
|
|
|
119
136
|
reg_act(:move_backward_char, proc { buf.move(BACKWARD_CHAR) }, "Move one character backward")
|
|
120
137
|
reg_act(:start_visual_mode, proc { buf.start_selection;vma.kbd.set_mode(:visual) }, "Enter VISUAL mode (for selections)")
|
|
121
138
|
reg_act(:jump_last_edit, proc { buf.jump_to_last_edit }, "Jump to the last edit location")
|
|
139
|
+
reg_act(:install_demo_files, proc { install_demo_files }, "Install and show Demo")
|
|
140
|
+
reg_act(:reload_customrb, proc { reload_customrb }, "Reload custom.rb")
|
|
122
141
|
|
|
123
142
|
|
|
124
143
|
reg_act :start_browse_mode, proc {
|
|
@@ -188,6 +207,9 @@ act_list = {
|
|
|
188
207
|
|
|
189
208
|
:backward_line => { :proc => proc { buf.move(BACKWARD_LINE) },
|
|
190
209
|
:desc => "Move one line backward", :group => [:move, :basic] },
|
|
210
|
+
|
|
211
|
+
:increment_word => { :proc => proc { buf.increment_current_word},
|
|
212
|
+
:desc => "Increment word", :group => [:edit, :extra] },
|
|
191
213
|
|
|
192
214
|
# { :proc => proc { },
|
|
193
215
|
# :desc => "", :group => : },
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
#
|
|
20
20
|
|
|
21
21
|
class State
|
|
22
|
-
attr_accessor :key_name, :eval_rule, :children, :action, :label, :major_modes, :level, :cursor_type, :keywords
|
|
22
|
+
attr_accessor :key_name, :eval_rule, :children, :action, :label, :major_modes, :level, :cursor_type, :keywords, :root, :parent
|
|
23
23
|
attr_reader :cur_mode, :scope
|
|
24
24
|
|
|
25
25
|
def initialize(key_name, eval_rule = "", ctype = :command, scope: :buffer)
|
|
@@ -31,6 +31,8 @@ class State
|
|
|
31
31
|
@keywords = []
|
|
32
32
|
@action = nil
|
|
33
33
|
@level = 0
|
|
34
|
+
@root = self # parent of a parent ... until mode root
|
|
35
|
+
@parent = nil
|
|
34
36
|
@cursor_type = ctype
|
|
35
37
|
end
|
|
36
38
|
|
|
@@ -55,6 +57,7 @@ class KeyBindingTree
|
|
|
55
57
|
@last_action = nil
|
|
56
58
|
@cur_action = nil
|
|
57
59
|
@method_handles_repeat = false
|
|
60
|
+
@overwriting_state = nil # A branch which has priority over other branches
|
|
58
61
|
|
|
59
62
|
@modifiers = { :ctrl => false, :shift => false, :alt => false } # TODO: create a queue
|
|
60
63
|
@last_event = [nil, nil, nil, nil, nil]
|
|
@@ -68,8 +71,9 @@ class KeyBindingTree
|
|
|
68
71
|
return if get_mode == :label
|
|
69
72
|
@match_state = [@modes[label]] # used for matching input
|
|
70
73
|
@mode_root_state = @modes[label]
|
|
71
|
-
|
|
72
|
-
@default_mode_stack
|
|
74
|
+
|
|
75
|
+
#TODO: should not happen? @default_mode_stack[-1] should be always the same as get_mode ?
|
|
76
|
+
@default_mode_stack << label if label != @default_mode_stack[-1]
|
|
73
77
|
|
|
74
78
|
__set_mode(label)
|
|
75
79
|
if !vma.buf.nil?
|
|
@@ -258,11 +262,17 @@ class KeyBindingTree
|
|
|
258
262
|
end
|
|
259
263
|
|
|
260
264
|
def set_state_to_root
|
|
265
|
+
# if root state is a minor mode
|
|
261
266
|
if @mode_root_state.major_modes.size == 1
|
|
262
|
-
modelabel = @mode_root_state.major_modes[0]
|
|
263
|
-
|
|
264
|
-
|
|
267
|
+
modelabel = @mode_root_state.major_modes[0] #TODO: support multiple inheritance?
|
|
268
|
+
parent_mode = @modes[modelabel]
|
|
269
|
+
# Have two branches for the matching (both major and minor modes)
|
|
270
|
+
# @mode_root_state = minor, parent_mode = major
|
|
271
|
+
@match_state = [@mode_root_state, parent_mode]
|
|
272
|
+
@overwriting_state = @mode_root_state # States from this branch have priority over others.
|
|
265
273
|
else
|
|
274
|
+
# if root state is a major mode
|
|
275
|
+
@overwriting_state = nil
|
|
266
276
|
@match_state = [@mode_root_state]
|
|
267
277
|
end
|
|
268
278
|
|
|
@@ -378,7 +388,13 @@ class KeyBindingTree
|
|
|
378
388
|
mmid = st.major_modes.first
|
|
379
389
|
trailpfx = "#{@modes[mmid].to_s}>"
|
|
380
390
|
end
|
|
381
|
-
|
|
391
|
+
mode_str = st.to_s
|
|
392
|
+
mode_str = "COMMAND" if mode_str == "C"
|
|
393
|
+
mode_str = "INSERT" if mode_str == "I"
|
|
394
|
+
mode_str = "VISUAL" if mode_str == "V"
|
|
395
|
+
mode_str = "BROWSE" if mode_str == "B"
|
|
396
|
+
|
|
397
|
+
s_trail << "[#{trailpfx}#{mode_str}]"
|
|
382
398
|
else
|
|
383
399
|
s_trail << " #{st.to_s}"
|
|
384
400
|
end
|
|
@@ -491,7 +507,31 @@ class KeyBindingTree
|
|
|
491
507
|
state_with_children = new_state.select { |s| s.children.any? }
|
|
492
508
|
s_act = new_state.select { |s| s.action != nil }
|
|
493
509
|
|
|
494
|
-
|
|
510
|
+
# Multiple matching states/modes (search has forked)
|
|
511
|
+
if new_state.size > 1
|
|
512
|
+
# puts "AAA"
|
|
513
|
+
# Conflict: One of them has actions (matching should stop),
|
|
514
|
+
# another has children (matching should continue)
|
|
515
|
+
if s_act.any? and state_with_children.any?
|
|
516
|
+
# puts "AAA1"
|
|
517
|
+
a = s_act[0]
|
|
518
|
+
b = state_with_children[0]
|
|
519
|
+
# Running major+minor mode. Minor mode overwriting the major mode
|
|
520
|
+
if a.root == @overwriting_state or b.root == @overwriting_state
|
|
521
|
+
# puts "AAA3:del"
|
|
522
|
+
# Remove those states not belonging to the overwriting branch (minor mode)
|
|
523
|
+
[s_act, state_with_children, new_state].each { |z| z.delete_if { |x| x.root != @overwriting_state } }
|
|
524
|
+
end
|
|
525
|
+
end
|
|
526
|
+
end
|
|
527
|
+
# new_state[0].root.key_name
|
|
528
|
+
|
|
529
|
+
if s_act.any? and state_with_children.any?
|
|
530
|
+
# debug "Conflict: s_act.any? and state_with_children.any?"
|
|
531
|
+
# require "pry"; binding.pry
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
if s_act.any? and !state_with_children.any?
|
|
495
535
|
eval_s = s_act.first.action if eval_s == nil
|
|
496
536
|
# if eval_s.to_s.match(/end_recording/)
|
|
497
537
|
# require "pry"; binding.pry
|
|
@@ -625,6 +665,8 @@ class KeyBindingTree
|
|
|
625
665
|
end
|
|
626
666
|
s1 = new_state
|
|
627
667
|
@cur_state.children << new_state
|
|
668
|
+
new_state.root = @cur_state.root
|
|
669
|
+
new_state.parent = @cur_state
|
|
628
670
|
end
|
|
629
671
|
|
|
630
672
|
set_state(key_name, eval_rule) # TODO: check is ok?
|
|
@@ -639,6 +681,7 @@ class KeyBindingTree
|
|
|
639
681
|
end
|
|
640
682
|
|
|
641
683
|
def handle_key_bindigs_action(action, c)
|
|
684
|
+
trail_str = get_state_trail_str[0]
|
|
642
685
|
# $acth << action #TODO:needed here?
|
|
643
686
|
@method_handles_repeat = false #TODO:??
|
|
644
687
|
n = 1
|
|
@@ -685,6 +728,21 @@ class KeyBindingTree
|
|
|
685
728
|
if !(action.class == String and action.include?("set_next_command_count"))
|
|
686
729
|
@next_command_count = nil
|
|
687
730
|
end
|
|
731
|
+
|
|
732
|
+
if cnf.kbd.show_prev_action? and trail_str.class==String
|
|
733
|
+
len_limit = 35
|
|
734
|
+
action_desc = "UNK"
|
|
735
|
+
if action.class == String && (m = action.match(/\Abuf\.insert_txt\((.+)\)\z/))
|
|
736
|
+
char_part = m[1].gsub("&", "&").gsub("<", "<").gsub(">", ">")
|
|
737
|
+
action_desc = "insert #{char_part}"
|
|
738
|
+
puts action_desc.inspect
|
|
739
|
+
else
|
|
740
|
+
action_desc = vma.actions[action]&.method_name || action.to_s
|
|
741
|
+
action_desc = action_desc[0..len_limit] if action_desc.size > len_limit
|
|
742
|
+
end
|
|
743
|
+
trail_str = trail_str.gsub("&", "&").gsub("<", "<").gsub(">", ">")
|
|
744
|
+
vma.gui.action_trail_label.markup = "<span weight='bold'>#{action_desc}|#{trail_str}</span>"
|
|
745
|
+
end
|
|
688
746
|
end
|
|
689
747
|
end
|
|
690
748
|
|
|
@@ -734,6 +792,12 @@ def show_key_bindings()
|
|
|
734
792
|
done.concat(x.lines); kbd_s << x
|
|
735
793
|
kbd_s << "\n"
|
|
736
794
|
|
|
795
|
+
kbd_s << "◼ Hyper Plaintext\n"
|
|
796
|
+
x = vma.kbd.get_by_keywords(modes: ["C"], keywords: ["hyperplaintext"])
|
|
797
|
+
x2 = vma.kbd.get_by_keywords(modes: ["V"], keywords: ["hyperplaintext"])
|
|
798
|
+
done.concat(x.lines); kbd_s << x << "\n" << x2
|
|
799
|
+
kbd_s << "\n"
|
|
800
|
+
|
|
737
801
|
kbd_s << "◼ Core\n"
|
|
738
802
|
x = vma.kbd.get_by_keywords(modes: [], keywords: ["core"])
|
|
739
803
|
x << vma.kbd.get_by_keywords(modes: ["X"], keywords: ["intro"])
|