vimamsa 0.1.9 → 0.1.11
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 +29 -7
- data/custom_example.rb +12 -2
- data/demo.txt +2 -2
- data/exe/vimamsa +1 -1
- data/lib/vimamsa/ack.rb +57 -46
- data/lib/vimamsa/actions.rb +1 -1
- data/lib/vimamsa/buffer.rb +287 -55
- data/lib/vimamsa/buffer_list.rb +83 -48
- data/lib/vimamsa/buffer_manager.rb +19 -3
- data/lib/vimamsa/conf.rb +10 -1
- data/lib/vimamsa/debug.rb +15 -11
- data/lib/vimamsa/easy_jump.rb +9 -5
- data/lib/vimamsa/editor.rb +73 -54
- data/lib/vimamsa/encrypt.rb +2 -2
- data/lib/vimamsa/file_finder.rb +70 -72
- data/lib/vimamsa/file_history.rb +2 -3
- data/lib/vimamsa/file_manager.rb +10 -8
- data/lib/vimamsa/form_generator.rb +122 -0
- data/lib/vimamsa/gui.rb +469 -118
- data/lib/vimamsa/gui_image.rb +12 -6
- data/lib/vimamsa/gui_menu.rb +26 -21
- data/lib/vimamsa/gui_select_window.rb +40 -21
- data/lib/vimamsa/gui_sourceview.rb +173 -79
- data/lib/vimamsa/hyper_plain_text.rb +36 -3
- data/lib/vimamsa/key_actions.rb +13 -1
- data/lib/vimamsa/key_binding_tree.rb +32 -20
- data/lib/vimamsa/key_bindings_vimlike.rb +54 -25
- data/lib/vimamsa/langservp.rb +172 -0
- data/lib/vimamsa/macro.rb +9 -8
- data/lib/vimamsa/main.rb +3 -4
- data/lib/vimamsa/rbvma.rb +7 -4
- data/lib/vimamsa/search.rb +3 -2
- data/lib/vimamsa/search_replace.rb +50 -120
- data/lib/vimamsa/text_transforms.rb +1 -1
- data/lib/vimamsa/util.rb +47 -1
- data/lib/vimamsa/version.rb +1 -1
- data/lib/vimamsa.rb +1 -6
- data/styles/molokai_edit.xml +3 -0
- data/vimamsa.gemspec +10 -10
- metadata +22 -20
@@ -3,8 +3,8 @@ def hpt_check_cur_word(w)
|
|
3
3
|
m = w.match(/⟦(.*)⟧/)
|
4
4
|
if m
|
5
5
|
fpfx = m[1]
|
6
|
-
if
|
7
|
-
dn = File.dirname(
|
6
|
+
if vma.buf.fname
|
7
|
+
dn = File.dirname(vma.buf.fname)
|
8
8
|
|
9
9
|
fcands = []
|
10
10
|
if fpfx[0] != "/"
|
@@ -51,6 +51,35 @@ def translate_path(fn, bf)
|
|
51
51
|
return outfn
|
52
52
|
end
|
53
53
|
|
54
|
+
# Scan audio files inserted with ⟦audio:filepath⟧ syntax
|
55
|
+
#TODO: merge code with hpt_scan_images
|
56
|
+
def hpt_scan_audio(bf = nil)
|
57
|
+
bf = buf() if bf.nil?
|
58
|
+
return if bf.nil?
|
59
|
+
return if !bf.fname
|
60
|
+
return if !bf.fname.match(/.*txt$/)
|
61
|
+
imgpos = scan_indexes(bf, /⟦audio:.+?⟧/)
|
62
|
+
imgtags = bf.scan(/(⟦audio:(.+?)⟧)/)
|
63
|
+
c = 0
|
64
|
+
imgpos.each.with_index { |x, i|
|
65
|
+
a = imgpos[i]
|
66
|
+
t = imgtags[i]
|
67
|
+
insert_pos = a + t[0].size + c
|
68
|
+
fn = t[1]
|
69
|
+
imgfn = translate_path(fn, bf)
|
70
|
+
next if !File.exist?(imgfn)
|
71
|
+
# Show as image in gui, handle as empty space in txt file
|
72
|
+
|
73
|
+
if bf[insert_pos..(insert_pos + 2)] != "\n \n"
|
74
|
+
bf.insert_txt_at("\n \n", insert_pos)
|
75
|
+
bf.view.handle_deltas
|
76
|
+
c += 3
|
77
|
+
end
|
78
|
+
bf.add_audio(imgfn, insert_pos + 1)
|
79
|
+
}
|
80
|
+
# vma.gui.delex.run #TODO:gtk4
|
81
|
+
end
|
82
|
+
|
54
83
|
# Scan images inserted with ⟦img:filepath⟧ syntax
|
55
84
|
def hpt_scan_images(bf = nil)
|
56
85
|
bf = buf() if bf.nil?
|
@@ -76,5 +105,9 @@ def hpt_scan_images(bf = nil)
|
|
76
105
|
end
|
77
106
|
bf.add_image(imgfn, insert_pos + 1)
|
78
107
|
}
|
79
|
-
|
108
|
+
|
109
|
+
# Need to scale after buffer loaded
|
110
|
+
GLib::Idle.add(proc { vma.gui.scale_all_images })
|
111
|
+
|
112
|
+
# vma.gui.delex.run #TODO:gtk4
|
80
113
|
end
|
data/lib/vimamsa/key_actions.rb
CHANGED
@@ -28,6 +28,9 @@ def is_visual_mode()
|
|
28
28
|
return 0
|
29
29
|
end
|
30
30
|
|
31
|
+
reg_act(:lsp_debug, proc { vma.buf.lsp_get_def }, "LSP get definition")
|
32
|
+
reg_act(:lsp_jump_to_definition, proc { vma.buf.lsp_jump_to_def }, "LSP jump to definition")
|
33
|
+
|
31
34
|
reg_act(:enable_debug, proc { $debug = true }, "Enable debug")
|
32
35
|
reg_act(:disable_debug, proc { $debug = false }, "Disable debug")
|
33
36
|
|
@@ -48,6 +51,8 @@ reg_act(:jump_to_random, proc { buf.jump_to_random_pos }, "")
|
|
48
51
|
reg_act(:insert_new_line, proc { buf.insert_new_line() }, "")
|
49
52
|
reg_act(:show_key_bindings, proc { show_key_bindings }, "Show key bindings")
|
50
53
|
reg_act(:put_file_path_to_clipboard, proc { buf.put_file_path_to_clipboard }, "Put file path of current file to clipboard")
|
54
|
+
reg_act(:put_file_ref_to_clipboard, proc { buf.put_file_ref_to_clipboard }, "Put file ref of current file to clipboard")
|
55
|
+
|
51
56
|
# reg_act(:encrypt_file, proc{buf.set_encrypted},"Set current file to encrypt on save")
|
52
57
|
reg_act(:encrypt_file, proc { encrypt_cur_buffer }, "Set current file to encrypt on save")
|
53
58
|
reg_act(:set_unencrypted, proc { buf.set_unencrypted }, "Set current file to save unencrypted")
|
@@ -80,8 +85,9 @@ reg_act(:diff_buffer, "diff_buffer", "")
|
|
80
85
|
# reg_act(:invoke_grep_search, proc{invoke_grep_search}, "")
|
81
86
|
reg_act(:invoke_grep_search, proc { gui_grep }, "Grep current buffer")
|
82
87
|
reg_act(:ack_search, proc { gui_ack }, "") #invoke_ack_search
|
83
|
-
reg_act :update_file_index, proc {
|
88
|
+
reg_act :update_file_index, proc { FileFinder.update_index }, "Update file index"
|
84
89
|
reg_act :delete_to_word_end, proc { buf.delete2(:to_word_end) }, "Delete to file end", { :group => [:edit, :basic] }
|
90
|
+
reg_act :delete_to_next_word_start, proc { buf.delete2(:to_next_word) }, "Delete to start of next word", { :group => [:edit, :basic] }
|
85
91
|
reg_act :delete_to_line_start, proc { buf.delete2(:to_line_start) }, "Delete to line start", { :group => [:edit, :basic] }
|
86
92
|
reg_act :start_browse_mode, proc { $kbd.set_mode(:browse); $kbd.set_default_mode(:browse) }, "Start browse mode"
|
87
93
|
reg_act :exit_browse_mode, proc {
|
@@ -146,6 +152,12 @@ act_list = {
|
|
146
152
|
:search_actions => { :proc => proc { search_actions },
|
147
153
|
:desc => "Search actions", :group => :search },
|
148
154
|
|
155
|
+
:toggle_active_window => { :proc => proc { vma.gui.toggle_active_window },
|
156
|
+
:desc => "Toggle active window", :group => :search },
|
157
|
+
|
158
|
+
:toggle_two_column => { :proc => proc { vma.gui.set_two_column },
|
159
|
+
:desc => "Set two column mode", :group => :search },
|
160
|
+
|
149
161
|
:content_search => { :proc => proc { FileContentSearch.start_gui },
|
150
162
|
:desc => "Search content of files", :group => :search },
|
151
163
|
|
@@ -15,7 +15,7 @@
|
|
15
15
|
# 'C , r v b'=> 'revert_buffer',
|
16
16
|
#
|
17
17
|
# In insert mode: press and hold ctrl, press "a"
|
18
|
-
# 'I ctrl-a'=> '
|
18
|
+
# 'I ctrl-a'=> 'vma.buf.jump(BEGINNING_OF_LINE)',
|
19
19
|
#
|
20
20
|
|
21
21
|
$cnf = {} # TODO
|
@@ -36,15 +36,17 @@ setcnf :indent_based_on_last_line, true
|
|
36
36
|
setcnf :extensions_to_open, [".txt", ".h", ".c", ".cpp", ".hpp", ".rb", ".inc", ".php", ".sh", ".m", ".gd", ".js"]
|
37
37
|
|
38
38
|
class State
|
39
|
-
attr_accessor :key_name, :eval_rule, :children, :action, :label, :major_modes, :level
|
39
|
+
attr_accessor :key_name, :eval_rule, :children, :action, :label, :major_modes, :level, :cursor_type
|
40
|
+
attr_reader :cur_mode
|
40
41
|
|
41
|
-
def initialize(key_name, eval_rule = "")
|
42
|
+
def initialize(key_name, eval_rule = "", ctype = :command)
|
42
43
|
@key_name = key_name
|
43
44
|
@eval_rule = eval_rule
|
44
45
|
@children = []
|
45
46
|
@major_modes = []
|
46
47
|
@action = nil
|
47
48
|
@level = 0
|
49
|
+
@cursor_type = ctype
|
48
50
|
end
|
49
51
|
|
50
52
|
def to_s()
|
@@ -53,7 +55,7 @@ class State
|
|
53
55
|
end
|
54
56
|
|
55
57
|
class KeyBindingTree
|
56
|
-
attr_accessor :C, :I, :cur_state, :root, :match_state, :last_action, :cur_action
|
58
|
+
attr_accessor :C, :I, :cur_state, :root, :match_state, :last_action, :cur_action, :modifiers
|
57
59
|
attr_reader :mode_root_state, :state_trail, :act_bindings
|
58
60
|
|
59
61
|
def initialize()
|
@@ -66,7 +68,7 @@ class KeyBindingTree
|
|
66
68
|
@last_action = nil
|
67
69
|
@cur_action = nil
|
68
70
|
|
69
|
-
@modifiers =
|
71
|
+
@modifiers = { :ctrl => false, :shift => false, :alt => false } # TODO: create a queue
|
70
72
|
@last_event = [nil, nil, nil, nil, nil]
|
71
73
|
|
72
74
|
@override_keyhandling_callback = nil
|
@@ -84,9 +86,8 @@ class KeyBindingTree
|
|
84
86
|
set_mode(@default_mode)
|
85
87
|
end
|
86
88
|
|
87
|
-
|
88
|
-
|
89
|
-
mode = State.new(id)
|
89
|
+
def add_mode(id, label, cursortype = :command, name: nil)
|
90
|
+
mode = State.new(id, "", cursortype)
|
90
91
|
mode.level = 1
|
91
92
|
@modes[label] = mode
|
92
93
|
@root.children << mode
|
@@ -95,6 +96,7 @@ class KeyBindingTree
|
|
95
96
|
end
|
96
97
|
end
|
97
98
|
|
99
|
+
# Add keyboard key binding mode based on another mode
|
98
100
|
def add_minor_mode(id, label, major_mode_label)
|
99
101
|
mode = State.new(id)
|
100
102
|
@modes[label] = mode
|
@@ -103,7 +105,7 @@ class KeyBindingTree
|
|
103
105
|
end
|
104
106
|
|
105
107
|
def clear_modifiers()
|
106
|
-
@modifiers = []
|
108
|
+
# @modifiers = [] #TODO:remove?
|
107
109
|
end
|
108
110
|
|
109
111
|
def find_state(key_name, eval_rule)
|
@@ -174,14 +176,27 @@ class KeyBindingTree
|
|
174
176
|
end
|
175
177
|
end
|
176
178
|
end
|
179
|
+
@cur_mode = label
|
180
|
+
|
181
|
+
if !vma.gui.view.nil?
|
182
|
+
vma.gui.view.draw_cursor() #TODO: handle outside this class
|
177
183
|
|
178
|
-
|
184
|
+
# Ripl.start :binding => binding
|
185
|
+
end
|
179
186
|
end
|
180
187
|
|
181
188
|
def cur_mode_str()
|
182
189
|
return @mode_root_state.key_name
|
183
190
|
end
|
184
191
|
|
192
|
+
def get_cursor_type
|
193
|
+
@mode_root_state.cursor_type
|
194
|
+
end
|
195
|
+
|
196
|
+
def get_mode
|
197
|
+
return @cur_mode
|
198
|
+
end
|
199
|
+
|
185
200
|
def set_state(key_name, eval_rule = "")
|
186
201
|
new_state = find_state(key_name, eval_rule)
|
187
202
|
if new_state != nil
|
@@ -201,8 +216,6 @@ class KeyBindingTree
|
|
201
216
|
end
|
202
217
|
|
203
218
|
@state_trail = [@mode_root_state]
|
204
|
-
# debug get_state_trail_str()
|
205
|
-
# $next_command_count = nil # TODO: set somewhere else?
|
206
219
|
end
|
207
220
|
|
208
221
|
# Print key bindings to show as documentation or for debugging
|
@@ -274,8 +287,7 @@ class KeyBindingTree
|
|
274
287
|
# if yes, change state to child
|
275
288
|
# if no, go back to root
|
276
289
|
def match_key_conf(c, translated_c, event_type)
|
277
|
-
|
278
|
-
print "MATCH KEY CONF: #{[c, translated_c]}" if $debug
|
290
|
+
debug "MATCH KEY CONF: #{[c, translated_c]}"
|
279
291
|
|
280
292
|
if !@override_keyhandling_callback.nil?
|
281
293
|
ret = @override_keyhandling_callback.call(c, event_type)
|
@@ -333,7 +345,7 @@ class KeyBindingTree
|
|
333
345
|
end
|
334
346
|
|
335
347
|
if new_state == nil
|
336
|
-
|
348
|
+
debug("NO MATCH")
|
337
349
|
if event_type == :key_press and c != "shift"
|
338
350
|
# TODO:include other modifiers in addition to shift?
|
339
351
|
set_state_to_root
|
@@ -485,17 +497,17 @@ class KeyBindingTree
|
|
485
497
|
# like '20j' => go to next line 20 times.
|
486
498
|
end
|
487
499
|
rescue SyntaxError
|
488
|
-
|
500
|
+
message("SYNTAX ERROR with eval cmd #{action}: " + $!.to_s)
|
489
501
|
# rescue NoMethodError
|
490
502
|
# debug("NoMethodError with eval cmd #{action}: " + $!.to_s)
|
491
503
|
# rescue NameError
|
492
504
|
# debug("NameError with eval cmd #{action}: " + $!.to_s)
|
493
505
|
# raise
|
494
506
|
rescue Exception => e
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
507
|
+
puts "BACKTRACE"
|
508
|
+
puts e.backtrace
|
509
|
+
puts e.inspect
|
510
|
+
puts "BACKTRACE END"
|
499
511
|
if $!.class == SystemExit
|
500
512
|
exit
|
501
513
|
else
|
@@ -1,3 +1,14 @@
|
|
1
|
+
vma.kbd.add_mode("C", :command)
|
2
|
+
vma.kbd.add_mode("I", :insert, :insert)
|
3
|
+
vma.kbd.add_mode("V", :visual, :visual)
|
4
|
+
vma.kbd.add_mode("M", :minibuffer) #TODO: needed?
|
5
|
+
vma.kbd.add_mode("R", :readchar)
|
6
|
+
vma.kbd.add_mode("B", :browse, :command)
|
7
|
+
vma.kbd.add_mode("X", :replace, :command, name: "Replace")
|
8
|
+
vma.kbd.set_default_mode(:command)
|
9
|
+
vma.kbd.set_mode(:command)
|
10
|
+
vma.kbd.show_state_trail
|
11
|
+
|
1
12
|
bindkey ["VCB M", "B m"], :run_last_macro
|
2
13
|
|
3
14
|
bindkey "VC s", :easy_jump
|
@@ -15,6 +26,11 @@ bindkey "C x", :delete_char_forward
|
|
15
26
|
bindkey "C , , l t", :load_theme
|
16
27
|
bindkey "C , f", :gui_file_finder
|
17
28
|
bindkey "C , h", :gui_file_history_finder
|
29
|
+
bindkey "C , z", :gui_file_finder
|
30
|
+
|
31
|
+
bindkey "C ` k", :lsp_debug
|
32
|
+
bindkey "C ` j", :lsp_jump_to_definition
|
33
|
+
|
18
34
|
bindkey "C , r r", :gui_search_replace
|
19
35
|
bindkey "V , r r", :gui_search_replace
|
20
36
|
bindkey "V , t b", :set_style_bold
|
@@ -30,11 +46,15 @@ bindkey "C , t b", :set_line_style_bold
|
|
30
46
|
bindkey "C , t t", :set_line_style_title
|
31
47
|
bindkey "C , t c", :clear_line_styles
|
32
48
|
bindkey "C , b", :start_buf_manager
|
49
|
+
bindkey "C , w", :toggle_active_window
|
50
|
+
bindkey "C , , w", :toggle_two_column
|
51
|
+
|
33
52
|
# bindkey "C , f o", :open_file_dialog
|
34
53
|
bindkey "CI ctrl-o", :open_file_dialog
|
35
54
|
# bindkey "M enter", :minibuffer_end
|
36
55
|
bindkey "C , a", :ack_search
|
37
|
-
bindkey "C d w", :
|
56
|
+
bindkey "C d w", :delete_to_next_word_start
|
57
|
+
|
38
58
|
bindkey "C d 0", :delete_to_line_start
|
39
59
|
bindkey "C , , f", :file_finder
|
40
60
|
bindkey "VC h", :e_move_backward_char
|
@@ -66,6 +86,7 @@ bindkey "C d d", [:delete_line, proc { buf.delete_line }, "Delete current line"]
|
|
66
86
|
bindkey "C enter || C return", [:line_action, proc { buf.handle_line_action() }, "Line action"]
|
67
87
|
bindkey "C p", [:paste_after, proc { buf.paste(AFTER) }, ""] # TODO: implement as replace for visual mode
|
68
88
|
bindkey "V d", [:delete_selection, proc { buf.delete(SELECTION) }, ""]
|
89
|
+
bindkey "V a d", [:delete_append_selection, proc { buf.delete(SELECTION, :append) }, "Delete and append selection"]
|
69
90
|
|
70
91
|
default_keys = {
|
71
92
|
|
@@ -78,7 +99,7 @@ default_keys = {
|
|
78
99
|
# 'C , s'=> 'gui_select_buffer',
|
79
100
|
"C , r v b" => :buf_revert,
|
80
101
|
"C , c b" => "bufs.close_current_buffer",
|
81
|
-
#"C , b" => '
|
102
|
+
#"C , b" => 'vma.kbd.set_mode("S");gui_select_buffer',
|
82
103
|
"C , n b" => :buf_new,
|
83
104
|
# "C , , ." => "backup_all_buffers()",
|
84
105
|
"VC , , s" => :search_actions,
|
@@ -92,10 +113,10 @@ default_keys = {
|
|
92
113
|
"VC pagedown" => "page_down",
|
93
114
|
"VC pageup" => "page_up",
|
94
115
|
|
95
|
-
"
|
96
|
-
"
|
97
|
-
"
|
98
|
-
"
|
116
|
+
"VCIX left" => "buf.move(BACKWARD_CHAR)",
|
117
|
+
"VCIX right" => "buf.move(FORWARD_CHAR)",
|
118
|
+
"VCIX down" => "buf.move(FORWARD_LINE)",
|
119
|
+
"VCIX up" => "buf.move(BACKWARD_LINE)",
|
99
120
|
|
100
121
|
"VC w" => "buf.jump_word(FORWARD,WORD_START)",
|
101
122
|
"VC b" => "buf.jump_word(BACKWARD,WORD_START)",
|
@@ -131,7 +152,6 @@ default_keys = {
|
|
131
152
|
"C n" => "$search.jump_to_next()",
|
132
153
|
"C N" => "$search.jump_to_previous()",
|
133
154
|
|
134
|
-
|
135
155
|
"C C" => :content_search,
|
136
156
|
|
137
157
|
# Debug
|
@@ -144,11 +164,11 @@ default_keys = {
|
|
144
164
|
"VC O" => "buf.jump(END_OF_LINE)",
|
145
165
|
"VC $" => "buf.jump(END_OF_LINE)",
|
146
166
|
|
147
|
-
"C o" => 'buf.jump(END_OF_LINE);buf.insert_txt("\n")
|
167
|
+
"C o" => 'buf.jump(END_OF_LINE);buf.insert_txt("\n");vma.kbd.set_mode(:insert)',
|
148
168
|
"C X" => 'buf.jump(END_OF_LINE);buf.insert_txt("\n");',
|
149
|
-
"C A" => "buf.jump(END_OF_LINE)
|
150
|
-
"C I" => "buf.jump(FIRST_NON_WHITESPACE)
|
151
|
-
"C a" => "buf.move(FORWARD_CHAR)
|
169
|
+
"C A" => "buf.jump(END_OF_LINE);vma.kbd.set_mode(:insert)",
|
170
|
+
"C I" => "buf.jump(FIRST_NON_WHITESPACE);vma.kbd.set_mode(:insert)",
|
171
|
+
"C a" => "buf.move(FORWARD_CHAR);vma.kbd.set_mode(:insert)",
|
152
172
|
"C J" => "buf.join_lines()",
|
153
173
|
"C u" => "buf.undo()",
|
154
174
|
|
@@ -197,7 +217,7 @@ default_keys = {
|
|
197
217
|
"V g c" => :selection_capitalize,
|
198
218
|
"V g s" => :selection_swapcase,
|
199
219
|
"V g r" => :selection_reverse,
|
200
|
-
|
220
|
+
|
201
221
|
"VC j" => :forward_line,
|
202
222
|
"VC k" => :backward_line,
|
203
223
|
|
@@ -213,8 +233,17 @@ default_keys = {
|
|
213
233
|
'CV \' <char>' => "buf.jump_to_mark(<char>)",
|
214
234
|
# "CV ''" =>'jump_to_mark(NEXT_MARK)', #TODO
|
215
235
|
|
216
|
-
|
217
|
-
"C
|
236
|
+
# Switch to other mode
|
237
|
+
"C i" => "vma.kbd.set_mode(:insert)",
|
238
|
+
"C R" => "vma.kbd.set_mode(:replace)",
|
239
|
+
"C ctrl!" => "vma.kbd.set_mode(:insert)",
|
240
|
+
"C ctrl!" => "vma.kbd.set_mode(:insert)",
|
241
|
+
|
242
|
+
|
243
|
+
# "R esc || R ctrl!" => "vma.kbd.set_mode(:command)",
|
244
|
+
"X esc" => "vma.kbd.set_mode(:command)",
|
245
|
+
"X ctrl!" => "vma.kbd.set_mode(:command)",
|
246
|
+
"X <char>" => "buf.replace_with_char(<char>);buf.move(FORWARD_CHAR)",
|
218
247
|
|
219
248
|
# Macros
|
220
249
|
# (experimental, may not work correctly)
|
@@ -235,22 +264,22 @@ default_keys = {
|
|
235
264
|
# "CV Q" => :quit,
|
236
265
|
"CV ctrl-q" => :quit,
|
237
266
|
"CV , R" => "restart_application",
|
238
|
-
"I ctrl!" => "
|
267
|
+
"I ctrl!" => "vma.kbd.set_mode(:command)",
|
239
268
|
"C shift!" => "buf.save",
|
240
269
|
"I <char>" => "buf.insert_txt(<char>)",
|
241
|
-
"I esc" => "
|
270
|
+
"I esc" => "vma.kbd.set_mode(:command)",
|
242
271
|
|
243
272
|
"I ctrl-d" => "buf.delete2(:to_word_end)",
|
244
273
|
|
245
|
-
#
|
246
|
-
"
|
247
|
-
"
|
248
|
-
"
|
249
|
-
"
|
250
|
-
"
|
251
|
-
"
|
252
|
-
"
|
253
|
-
"
|
274
|
+
# Insert and Replace modes: Moving
|
275
|
+
"IX ctrl-a" => "buf.jump(BEGINNING_OF_LINE)",
|
276
|
+
"IX ctrl-b" => "buf.move(BACKWARD_CHAR)",
|
277
|
+
"IX ctrl-f" => "buf.move(FORWARD_CHAR)",
|
278
|
+
"IX ctrl-n" => "buf.move(FORWARD_LINE)",
|
279
|
+
"IX ctrl-p" => "buf.move(BACKWARD_LINE)",
|
280
|
+
"IX ctrl-e" => "buf.jump(END_OF_LINE)", # context: mode:I, buttons down: {C}
|
281
|
+
"IX alt-f" => "buf.jump_word(FORWARD,WORD_START)",
|
282
|
+
"IX alt-b" => "buf.jump_word(BACKWARD,WORD_START)",
|
254
283
|
|
255
284
|
"I tab" => 'buf.insert_txt(" ")',
|
256
285
|
"I space" => 'buf.insert_txt(" ")',
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require "language_server-protocol"
|
2
|
+
LSP = LanguageServer::Protocol
|
3
|
+
|
4
|
+
class LangSrv
|
5
|
+
@@languages = {}
|
6
|
+
attr_accessor :error
|
7
|
+
|
8
|
+
def self.get(lang)
|
9
|
+
if @@languages[lang].nil?
|
10
|
+
@@languages[lang] = LangSrv.new(lang)
|
11
|
+
@@languages[lang] = nil if @@languages[lang].error
|
12
|
+
end
|
13
|
+
return @@languages[lang]
|
14
|
+
end
|
15
|
+
|
16
|
+
def new_id()
|
17
|
+
return @id += 1
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(lang)
|
21
|
+
@error = true
|
22
|
+
clsp = conf(:custom_lsp)
|
23
|
+
|
24
|
+
# Use LSP server specified by user if available
|
25
|
+
@lang = lang
|
26
|
+
lspconf = clsp[lang]
|
27
|
+
if !lspconf.nil?
|
28
|
+
@io = IO.popen(lspconf[:command], "r+")
|
29
|
+
else
|
30
|
+
return nil
|
31
|
+
end
|
32
|
+
@writer = LSP::Transport::Io::Writer.new(@io)
|
33
|
+
@reader = LSP::Transport::Io::Reader.new(@io)
|
34
|
+
@id = 0
|
35
|
+
|
36
|
+
wf = []
|
37
|
+
for c in conf(:workspace_folders)
|
38
|
+
wf << LSP::Interface::WorkspaceFolder.new(uri: c[:uri], name: c[:name])
|
39
|
+
end
|
40
|
+
|
41
|
+
pid = Process.pid
|
42
|
+
|
43
|
+
if lspconf[:name] == "phpactor"
|
44
|
+
initp = LSP::Interface::InitializeParams.new(
|
45
|
+
process_id: pid,
|
46
|
+
root_uri: lspconf[:rooturi],
|
47
|
+
workspace_folders: wf,
|
48
|
+
capabilities: { 'workspace': { 'workspaceFolders': true } },
|
49
|
+
)
|
50
|
+
else
|
51
|
+
initp = LSP::Interface::InitializeParams.new(
|
52
|
+
process_id: pid,
|
53
|
+
root_uri: "null",
|
54
|
+
workspace_folders: wf,
|
55
|
+
capabilities: { 'workspace': { 'workspaceFolders': true } },
|
56
|
+
)
|
57
|
+
end
|
58
|
+
@resp = {}
|
59
|
+
|
60
|
+
@writer.write(id: new_id, params: initp, method: "initialize")
|
61
|
+
|
62
|
+
@lst = Thread.new {
|
63
|
+
@reader.read do |r|
|
64
|
+
@resp[r[:id]] = r
|
65
|
+
pp r
|
66
|
+
# exit
|
67
|
+
end
|
68
|
+
}
|
69
|
+
@error = false
|
70
|
+
end
|
71
|
+
|
72
|
+
def handle_delta(delta, fpath, version)
|
73
|
+
fpuri = URI.join("file:///", fpath).to_s
|
74
|
+
|
75
|
+
# delta[0]: char position
|
76
|
+
# delta[1]: INSERT or DELETE
|
77
|
+
# delta[2]: number of chars affected
|
78
|
+
# delta[3]: text to add in case of insert
|
79
|
+
|
80
|
+
changes = nil
|
81
|
+
if delta[1] == INSERT
|
82
|
+
changes = [{ 'rangeLength': 0, 'range': { 'start': { 'line': delta[4][0], 'character': delta[4][1] }, 'end': { 'line': delta[4][0], 'character': delta[4][1] } }, 'text': delta[3] }]
|
83
|
+
elsif delta[1] == DELETE
|
84
|
+
changes = [{ 'rangeLength': delta[2], 'range': { 'start': { 'line': delta[4][0], 'character': delta[4][1] }, 'end': { 'line': delta[5][0], 'character': delta[5][1] } }, 'text': "" }]
|
85
|
+
end
|
86
|
+
debug changes.inspect, 2
|
87
|
+
|
88
|
+
if !changes.nil?
|
89
|
+
a = LSP::Interface::DidChangeTextDocumentParams.new(
|
90
|
+
text_document: LSP::Interface::VersionedTextDocumentIdentifier.new(uri: fpuri, version: version),
|
91
|
+
content_changes: changes,
|
92
|
+
)
|
93
|
+
id = new_id
|
94
|
+
pp a
|
95
|
+
@writer.write(id: id, params: a, method: "textDocument/didChange")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def wait_for_response(id)
|
100
|
+
t = Time.now
|
101
|
+
debug "Waiting for response id:#{id}"
|
102
|
+
while @resp[id].nil?
|
103
|
+
sleep 0.03
|
104
|
+
if Time.now - t > 5
|
105
|
+
debug "Timeout LSP call id:#{id}"
|
106
|
+
return nil
|
107
|
+
end
|
108
|
+
end
|
109
|
+
debug "End waiting id:#{id}"
|
110
|
+
return @resp[id]
|
111
|
+
end
|
112
|
+
|
113
|
+
def add_workspaces() # TODO
|
114
|
+
# https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_workspaceFolders
|
115
|
+
debug "Add workspaces", 2
|
116
|
+
a = [LSP::Interface::WorkspaceFolder.new(uri: "file:///...", name: "vimamsa")]
|
117
|
+
id = new_id
|
118
|
+
# @writer.write(id: id, params: a, method: "textDocument/definition")
|
119
|
+
# @writer.write(id: id, params: a, method: "workspace/workspaceFolders")
|
120
|
+
@writer.write(id: id, params: a, method: "workspace/didChangeWorkspaceFolders")
|
121
|
+
r = wait_for_response(id)
|
122
|
+
pp r
|
123
|
+
end
|
124
|
+
|
125
|
+
def handle_responses()
|
126
|
+
#TODO
|
127
|
+
# r = @resp.delete_at(0)
|
128
|
+
end
|
129
|
+
|
130
|
+
def get_definition(fpuri, lpos, cpos)
|
131
|
+
a = LSP::Interface::DefinitionParams.new(
|
132
|
+
position: LSP::Interface::Position.new(line: lpos, character: cpos),
|
133
|
+
text_document: LSP::Interface::TextDocumentIdentifier.new(uri: fpuri),
|
134
|
+
)
|
135
|
+
id = new_id
|
136
|
+
pp a
|
137
|
+
@writer.write(id: id, params: a, method: "textDocument/definition")
|
138
|
+
r = wait_for_response(id)
|
139
|
+
return nil if r.nil?
|
140
|
+
# Ripl.start :binding => binding
|
141
|
+
pp r
|
142
|
+
line = HSafe.new(r)[:result][0][:range][:start][:line].val
|
143
|
+
uri = HSafe.new(r)[:result][0][:uri].val
|
144
|
+
|
145
|
+
if !uri.nil? and !line.nil?
|
146
|
+
puts "LINE:" + line.to_s
|
147
|
+
puts "URI:" + uri
|
148
|
+
fpath = URI.parse(uri).path
|
149
|
+
line = line + 1
|
150
|
+
return [fpath, line]
|
151
|
+
end
|
152
|
+
|
153
|
+
return nil
|
154
|
+
end
|
155
|
+
|
156
|
+
def open_file(fp, fc = nil)
|
157
|
+
debug "open_file", 2
|
158
|
+
fc = IO.read(fp) if fc.nil?
|
159
|
+
fpuri = URI.join("file:///", fp).to_s
|
160
|
+
|
161
|
+
a = LSP::Interface::DidOpenTextDocumentParams.new(
|
162
|
+
text_document: LSP::Interface::TextDocumentItem.new(
|
163
|
+
uri: fpuri,
|
164
|
+
text: fc,
|
165
|
+
language_id: "c++",
|
166
|
+
version: 1,
|
167
|
+
),
|
168
|
+
)
|
169
|
+
|
170
|
+
@writer.write(method: "textDocument/didOpen", params: a)
|
171
|
+
end
|
172
|
+
end
|
data/lib/vimamsa/macro.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
def gui_find_macro_update_callback(search_str = "")
|
3
2
|
debug "gui_find_macro_update_callback: #{search_str}"
|
4
3
|
heystack = $macro.named_macros
|
@@ -24,7 +23,7 @@ def gui_find_macro_select_callback(search_str, idx)
|
|
24
23
|
end
|
25
24
|
|
26
25
|
class Macro
|
27
|
-
|
26
|
+
attr_reader :running_macro
|
28
27
|
attr_accessor :recorded_macros, :recording, :named_macros, :last_macro
|
29
28
|
|
30
29
|
def initialize()
|
@@ -33,11 +32,12 @@ class Macro
|
|
33
32
|
@current_recording = []
|
34
33
|
@current_name = nil
|
35
34
|
@last_macro = "a"
|
35
|
+
@running_macro = false
|
36
36
|
|
37
37
|
#TODO:
|
38
38
|
@recorded_macros = vma.marshal_load("macros", {})
|
39
39
|
@named_macros = vma.marshal_load("named_macros", {})
|
40
|
-
|
40
|
+
vma.hook.register(:shutdown, self.method("save"))
|
41
41
|
end
|
42
42
|
|
43
43
|
def save()
|
@@ -52,15 +52,13 @@ class Macro
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def find_macro_gui()
|
55
|
-
# Ripl.start :binding => binding
|
56
|
-
|
57
55
|
l = $macro.named_macros.keys.sort.collect { |x| [x, 0] }
|
58
56
|
$macro_search_list = l
|
59
57
|
$select_keys = ["h", "l", "f", "d", "s", "a", "g", "z"]
|
60
58
|
|
61
59
|
gui_select_update_window(l, $select_keys.collect { |x| x.upcase },
|
62
|
-
|
63
|
-
|
60
|
+
"gui_find_macro_select_callback",
|
61
|
+
"gui_find_macro_update_callback")
|
64
62
|
end
|
65
63
|
|
66
64
|
def name_macro(name, id = nil)
|
@@ -129,14 +127,16 @@ class Macro
|
|
129
127
|
end
|
130
128
|
acts = @recorded_macros[name]
|
131
129
|
if acts.kind_of?(Array) and acts.any?
|
130
|
+
@running_macro = true
|
132
131
|
set_last_command({ method: $macro.method("run_macro"), params: [name] })
|
133
132
|
#
|
134
|
-
# Ripl.start :binding => binding
|
135
133
|
for a in acts
|
136
134
|
ret = exec_action(a)
|
137
135
|
debug ret
|
138
136
|
if ret == false
|
139
137
|
message("Error while running macro")
|
138
|
+
Ripl.start :binding => binding
|
139
|
+
|
140
140
|
break
|
141
141
|
end
|
142
142
|
end
|
@@ -144,6 +144,7 @@ class Macro
|
|
144
144
|
# debug(eval_str)
|
145
145
|
# eval(eval_str)
|
146
146
|
end
|
147
|
+
@running_macro = false
|
147
148
|
buf.set_pos(buf.pos)
|
148
149
|
end
|
149
150
|
|
data/lib/vimamsa/main.rb
CHANGED
@@ -24,7 +24,6 @@ $command_history = []
|
|
24
24
|
$clipboard = []
|
25
25
|
$register = Hash.new("")
|
26
26
|
$cnf = {}
|
27
|
-
$search_dirs = []
|
28
27
|
$errors = []
|
29
28
|
|
30
29
|
$cur_register = "a"
|
@@ -37,15 +36,15 @@ $experimental = false
|
|
37
36
|
|
38
37
|
# Return currently active buffer
|
39
38
|
def buf()
|
40
|
-
return
|
39
|
+
return vma.buf
|
41
40
|
end
|
42
41
|
|
43
42
|
def bufs()
|
44
|
-
return
|
43
|
+
return vma.buffers
|
45
44
|
end
|
46
45
|
|
47
46
|
def buflist()
|
48
|
-
return
|
47
|
+
return vma.buffers
|
49
48
|
end
|
50
49
|
|
51
50
|
require "vimamsa/editor.rb"
|