Implement vim edit inside delimiters
This commit is contained in:
parent
87613a7619
commit
3986233b5c
|
@ -3,6 +3,7 @@ local Highlighter = require "core.doc.highlighter"
|
|||
local syntax = require "core.syntax"
|
||||
local config = require "core.config"
|
||||
local common = require "core.common"
|
||||
local translate = require "core.doc.translate"
|
||||
|
||||
|
||||
local Doc = Object:extend()
|
||||
|
@ -399,4 +400,10 @@ function Doc:select_to(...)
|
|||
end
|
||||
|
||||
|
||||
function Doc:select_with_delimiters(delims, outer)
|
||||
local line, col = self:get_selection()
|
||||
self:set_selection(self:position_offset(line, col, translate.inside_delimiters, delims, outer))
|
||||
end
|
||||
|
||||
|
||||
return Doc
|
||||
|
|
|
@ -145,4 +145,45 @@ function translate.end_of_doc(doc, line, col)
|
|||
end
|
||||
|
||||
|
||||
function translate.inside_delimiters(doc, line, col, delims, outer)
|
||||
print('translate.inside_delimiters', delims[2], outer)
|
||||
local line1, col1 = line, col
|
||||
while true do
|
||||
local lineb, colb = doc:position_offset(line1, col1, -1)
|
||||
local char = doc:get_char(lineb, colb)
|
||||
if char == delims[1]
|
||||
or line1 == lineb and col1 == colb then
|
||||
break
|
||||
end
|
||||
line1, col1 = lineb, colb
|
||||
end
|
||||
|
||||
if outer then
|
||||
line1, col1 = doc:position_offset(line1, col1, -1)
|
||||
end
|
||||
|
||||
local line2, col2 = line, col
|
||||
while true do
|
||||
local linef, colf = doc:position_offset(line2, col2, 1)
|
||||
local char = doc:get_char(line2, col2)
|
||||
if char == delims[2]
|
||||
or linef == line2 and colf == col2 then
|
||||
break
|
||||
end
|
||||
line2, col2 = linef, colf
|
||||
end
|
||||
|
||||
if outer then
|
||||
line2, col2 = doc:position_offset(line2, col2, 1)
|
||||
while doc:get_char(line2, col2) == ' ' do
|
||||
local nline2, ncol2 = doc:position_offset(line2, col2, 1)
|
||||
if nline2 == line2 and ncol2 == col2 then break end
|
||||
line2, col2 = nline2, ncol2
|
||||
end
|
||||
end
|
||||
|
||||
return line1, col1, line2, col2
|
||||
end
|
||||
|
||||
|
||||
return translate
|
||||
|
|
|
@ -3,11 +3,12 @@ local command = require "core.command"
|
|||
|
||||
local vim = {}
|
||||
|
||||
local command_buffer = {verb = '.', mult_accu = ''}
|
||||
local command_buffer = {verb = '.', mult_accu = '', inside = ''}
|
||||
|
||||
function command_buffer:reset()
|
||||
self.verb = '.'
|
||||
self.mult_accu = ''
|
||||
self.inside = ''
|
||||
end
|
||||
|
||||
function command_buffer:mult()
|
||||
|
@ -28,7 +29,7 @@ local verbs_obj = {'c', 'd', 'y'}
|
|||
local verbs_imm = {'a', 'h', 'i', 'j', 'k', 'l', 'o', 'p', 'u', 'v', 'x', 'O',
|
||||
'left', 'right', 'up', 'down', 'escape'}
|
||||
|
||||
local vim_objects = {'b', 'd', 'e', 'w', 'y', '^', '0', '$'}
|
||||
local vim_objects = {'a', 'b', 'd', 'e', 'i', 'w', 'y', '^', '0', '$'}
|
||||
|
||||
local vim_object_map = {
|
||||
['b'] = 'start-of-word',
|
||||
|
@ -39,6 +40,15 @@ local vim_object_map = {
|
|||
['0'] = 'start-of-line',
|
||||
}
|
||||
|
||||
local inside_delims = {
|
||||
[')'] = {'(', ')'},
|
||||
[']'] = {'[', ']'},
|
||||
['}'] = {'{', '}'},
|
||||
['>'] = {'<', '>'},
|
||||
['"'] = {'"', '"'},
|
||||
["'"] = {"'", "'"},
|
||||
}
|
||||
|
||||
local function doc_command(action, command)
|
||||
return 'doc:' .. action .. '-' .. command
|
||||
end
|
||||
|
@ -125,27 +135,48 @@ local function vim_execute(mode, verb, mult, object)
|
|||
return true
|
||||
end
|
||||
|
||||
function vim.on_text_input(mode, text, stroke)
|
||||
text = text or stroke
|
||||
function vim.on_text_input(mode, text_raw, stroke)
|
||||
local text = text_raw or stroke
|
||||
if mode == 'command' or mode == 'visual' then
|
||||
if command_buffer.verb == '.' and table_find(verbs_imm, text) then
|
||||
if command_buffer.inside ~= '' and inside_delims[text] then
|
||||
-- got character for inside delimiter edits
|
||||
local view = core.active_view
|
||||
local outer = command_buffer.inside == 'a'
|
||||
view.doc:select_with_delimiters(inside_delims[text], outer)
|
||||
command.perform('doc:delete')
|
||||
if command_buffer.verb == 'c' then
|
||||
view:set_editing_mode('insert')
|
||||
end
|
||||
command_buffer:reset()
|
||||
return true
|
||||
elseif command_buffer.verb == '.' and table_find(verbs_imm, text) then
|
||||
-- execute immediate vim command
|
||||
vim_execute(mode, text, command_buffer:mult())
|
||||
command_buffer:reset()
|
||||
return true
|
||||
elseif command_buffer.verb == '.' and table_find(verbs_obj, text) then
|
||||
-- vim command that takes an object
|
||||
if mode == 'command' then
|
||||
-- store the command without executing
|
||||
command_buffer.verb = text
|
||||
else
|
||||
-- visual mode: execute the command
|
||||
vim_execute(mode, text, command_buffer:mult())
|
||||
command_buffer:reset()
|
||||
end
|
||||
return true
|
||||
elseif string.byte(text) >= string.byte('0') and string.byte(text) <= string.byte('9') then
|
||||
command_buffer:add_mult_char(text)
|
||||
elseif text_raw and string.byte(text_raw) >= string.byte('0') and string.byte(text_raw) <= string.byte('9') then
|
||||
-- numeric command multiplier
|
||||
command_buffer:add_mult_char(text_raw)
|
||||
return true
|
||||
elseif table_find(vim_objects, text) then
|
||||
vim_execute(mode, command_buffer.verb, command_buffer:mult(), text)
|
||||
command_buffer:reset()
|
||||
-- object of a verb
|
||||
if text == 'i' or text == 'a' then
|
||||
command_buffer.inside = text
|
||||
else
|
||||
vim_execute(mode, command_buffer.verb, command_buffer:mult(), text)
|
||||
command_buffer:reset()
|
||||
end
|
||||
return true
|
||||
elseif stroke == 'escape' then
|
||||
core.active_view:set_editing_mode('command')
|
||||
|
|
Loading…
Reference in New Issue