vimamsa 0.1.9 → 0.1.11
Sign up to get free protection for your applications and to get access to all the features.
- 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"
|