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 syntax = require "core.syntax"
|
||||||
local config = require "core.config"
|
local config = require "core.config"
|
||||||
local common = require "core.common"
|
local common = require "core.common"
|
||||||
|
local translate = require "core.doc.translate"
|
||||||
|
|
||||||
|
|
||||||
local Doc = Object:extend()
|
local Doc = Object:extend()
|
||||||
|
@ -399,4 +400,10 @@ function Doc:select_to(...)
|
||||||
end
|
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
|
return Doc
|
||||||
|
|
|
@ -145,4 +145,45 @@ function translate.end_of_doc(doc, line, col)
|
||||||
end
|
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
|
return translate
|
||||||
|
|
|
@ -3,11 +3,12 @@ local command = require "core.command"
|
||||||
|
|
||||||
local vim = {}
|
local vim = {}
|
||||||
|
|
||||||
local command_buffer = {verb = '.', mult_accu = ''}
|
local command_buffer = {verb = '.', mult_accu = '', inside = ''}
|
||||||
|
|
||||||
function command_buffer:reset()
|
function command_buffer:reset()
|
||||||
self.verb = '.'
|
self.verb = '.'
|
||||||
self.mult_accu = ''
|
self.mult_accu = ''
|
||||||
|
self.inside = ''
|
||||||
end
|
end
|
||||||
|
|
||||||
function command_buffer:mult()
|
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',
|
local verbs_imm = {'a', 'h', 'i', 'j', 'k', 'l', 'o', 'p', 'u', 'v', 'x', 'O',
|
||||||
'left', 'right', 'up', 'down', 'escape'}
|
'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 = {
|
local vim_object_map = {
|
||||||
['b'] = 'start-of-word',
|
['b'] = 'start-of-word',
|
||||||
|
@ -39,6 +40,15 @@ local vim_object_map = {
|
||||||
['0'] = 'start-of-line',
|
['0'] = 'start-of-line',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local inside_delims = {
|
||||||
|
[')'] = {'(', ')'},
|
||||||
|
[']'] = {'[', ']'},
|
||||||
|
['}'] = {'{', '}'},
|
||||||
|
['>'] = {'<', '>'},
|
||||||
|
['"'] = {'"', '"'},
|
||||||
|
["'"] = {"'", "'"},
|
||||||
|
}
|
||||||
|
|
||||||
local function doc_command(action, command)
|
local function doc_command(action, command)
|
||||||
return 'doc:' .. action .. '-' .. command
|
return 'doc:' .. action .. '-' .. command
|
||||||
end
|
end
|
||||||
|
@ -125,27 +135,48 @@ local function vim_execute(mode, verb, mult, object)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function vim.on_text_input(mode, text, stroke)
|
function vim.on_text_input(mode, text_raw, stroke)
|
||||||
text = text or stroke
|
local text = text_raw or stroke
|
||||||
if mode == 'command' or mode == 'visual' then
|
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())
|
vim_execute(mode, text, command_buffer:mult())
|
||||||
command_buffer:reset()
|
command_buffer:reset()
|
||||||
return true
|
return true
|
||||||
elseif command_buffer.verb == '.' and table_find(verbs_obj, text) then
|
elseif command_buffer.verb == '.' and table_find(verbs_obj, text) then
|
||||||
|
-- vim command that takes an object
|
||||||
if mode == 'command' then
|
if mode == 'command' then
|
||||||
|
-- store the command without executing
|
||||||
command_buffer.verb = text
|
command_buffer.verb = text
|
||||||
else
|
else
|
||||||
|
-- visual mode: execute the command
|
||||||
vim_execute(mode, text, command_buffer:mult())
|
vim_execute(mode, text, command_buffer:mult())
|
||||||
command_buffer:reset()
|
command_buffer:reset()
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
elseif string.byte(text) >= string.byte('0') and string.byte(text) <= string.byte('9') then
|
elseif text_raw and string.byte(text_raw) >= string.byte('0') and string.byte(text_raw) <= string.byte('9') then
|
||||||
command_buffer:add_mult_char(text)
|
-- numeric command multiplier
|
||||||
|
command_buffer:add_mult_char(text_raw)
|
||||||
return true
|
return true
|
||||||
elseif table_find(vim_objects, text) then
|
elseif table_find(vim_objects, text) then
|
||||||
vim_execute(mode, command_buffer.verb, command_buffer:mult(), text)
|
-- object of a verb
|
||||||
command_buffer:reset()
|
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
|
return true
|
||||||
elseif stroke == 'escape' then
|
elseif stroke == 'escape' then
|
||||||
core.active_view:set_editing_mode('command')
|
core.active_view:set_editing_mode('command')
|
||||||
|
|
Loading…
Reference in New Issue