First preliminary implementation of vim-mode
The basic is there and sort-of-work but largely incomplete and not yet usable.
This commit is contained in:
parent
3810b6ba6c
commit
97a00f946d
|
@ -58,6 +58,18 @@ function command.perform(...)
|
|||
end
|
||||
|
||||
|
||||
function command.perform_many(n, name)
|
||||
local cmd = command.map[name]
|
||||
if not cmd or not cmd.predicate() then return false end
|
||||
pcall(function()
|
||||
for i = 1, n do
|
||||
cmd.perform()
|
||||
end
|
||||
end)
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
function command.add_defaults()
|
||||
local reg = { "core", "root", "command", "doc", "findreplace", "files" }
|
||||
for _, name in ipairs(reg) do
|
||||
|
|
|
@ -171,4 +171,16 @@ command.add(nil, {
|
|||
return common.home_encode_list(common.dir_list_suggest(text, dir_list))
|
||||
end)
|
||||
end,
|
||||
|
||||
["core:set-insert-mode"] = function()
|
||||
core.mode = 'insert'
|
||||
end,
|
||||
|
||||
["core:set-command-mode"] = function()
|
||||
core.mode = 'command'
|
||||
end,
|
||||
|
||||
["core:set-standard-mode"] = function()
|
||||
core.mode = 'standard'
|
||||
end,
|
||||
})
|
||||
|
|
|
@ -394,6 +394,7 @@ function core.init()
|
|||
core.clip_rect_stack = {{ 0,0,0,0 }}
|
||||
core.log_items = {}
|
||||
core.docs = {}
|
||||
core.mode = 'standard'
|
||||
core.threads = setmetatable({}, { __mode = "k" })
|
||||
|
||||
local project_dir_abs = system.absolute_path(project_dir)
|
||||
|
@ -716,12 +717,12 @@ end
|
|||
|
||||
function core.on_event(type, ...)
|
||||
local did_keymap = false
|
||||
if type == "textinput" then
|
||||
if type == "textinput" and (core.mode == 'insert' or core.mode == 'standard') then
|
||||
core.root_view:on_text_input(...)
|
||||
elseif type == "keypressed" then
|
||||
did_keymap = keymap.on_key_pressed(...)
|
||||
did_keymap = keymap.on_key_pressed(core.mode, ...)
|
||||
elseif type == "keyreleased" then
|
||||
keymap.on_key_released(...)
|
||||
keymap.on_key_released(core.mode, ...)
|
||||
elseif type == "mousemoved" then
|
||||
core.root_view:on_mouse_moved(...)
|
||||
elseif type == "mousepressed" then
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
local core = require "core"
|
||||
local command = require "core.command"
|
||||
local keymap = {}
|
||||
|
||||
|
@ -14,6 +15,57 @@ local modkey_map = {
|
|||
["right alt"] = "altgr",
|
||||
}
|
||||
|
||||
function keymap.reset_vim_command()
|
||||
keymap.command_verb = '.'
|
||||
keymap.command_mult = 1
|
||||
end
|
||||
|
||||
|
||||
local function table_find(t, e)
|
||||
for i = 1, #t do
|
||||
if t[i] == e then return i end
|
||||
end
|
||||
end
|
||||
|
||||
keymap.vim_verbs_obj = {'d', 'c'}
|
||||
keymap.vim_verbs_imm = {'y', 'p', 'h', 'j', 'k', 'l', 'x', 'i'}
|
||||
keymap.vim_objects = {'w', '$'}
|
||||
|
||||
local vim_object_map = {
|
||||
['w'] = 'end-of-word',
|
||||
['$'] = 'end-of-line',
|
||||
}
|
||||
|
||||
function keymap.vim_execute(verb, mult, object)
|
||||
if verb == '.' then
|
||||
return command.perform_many(mult, 'doc:move-to-' .. vim_object_map[object])
|
||||
elseif verb == 'd' then
|
||||
return command.perform_many(mult, 'doc:delete-to-' .. vim_object_map[object])
|
||||
elseif verb == 'c' then
|
||||
command.perform_many(mult, 'doc:select-to-' .. vim_object_map[object])
|
||||
command.perform('doc:copy')
|
||||
command.perform('doc:cut')
|
||||
command.perform('core:set-insert-mode')
|
||||
elseif verb == 'h' then
|
||||
command.perform_many(mult, 'doc:move-to-previous-char')
|
||||
elseif verb == 'j' then
|
||||
command.perform_many(mult, 'doc:move-to-next-line')
|
||||
elseif verb == 'k' then
|
||||
command.perform_many(mult, 'doc:move-to-previous-line')
|
||||
elseif verb == 'l' then
|
||||
command.perform_many(mult, 'doc:move-to-next-char')
|
||||
elseif verb == 'x' then
|
||||
command.perform_many(mult, 'doc:delete')
|
||||
elseif verb == 'i' then
|
||||
command.perform('core:set-insert-mode')
|
||||
else
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
keymap.reset_vim_command()
|
||||
|
||||
local modkeys = { "ctrl", "alt", "altgr", "shift" }
|
||||
|
||||
local function key_to_stroke(k)
|
||||
|
@ -52,7 +104,7 @@ function keymap.get_binding(cmd)
|
|||
end
|
||||
|
||||
|
||||
function keymap.on_key_pressed(k)
|
||||
function keymap.on_key_pressed(editor_mode, k)
|
||||
local mk = modkey_map[k]
|
||||
if mk then
|
||||
keymap.modkeys[mk] = true
|
||||
|
@ -62,6 +114,29 @@ function keymap.on_key_pressed(k)
|
|||
end
|
||||
else
|
||||
local stroke = key_to_stroke(k)
|
||||
if editor_mode == 'command' then
|
||||
if keymap.command_verb == '.' and table_find(keymap.vim_verbs_imm, stroke) then
|
||||
keymap.vim_execute(stroke, keymap.command_mult)
|
||||
keymap.reset_vim_command()
|
||||
return true
|
||||
elseif keymap.command_verb == '.' and table_find(keymap.vim_verbs_obj, stroke) then
|
||||
keymap.command_verb = stroke
|
||||
return true
|
||||
elseif string.byte(stroke) >= string.byte(1) and string.byte(stroke) <= string.byte(9) then
|
||||
keymap.command_mult = tonumber(stroke)
|
||||
return true
|
||||
elseif table_find(keymap.vim_objects, stroke) then
|
||||
keymap.vim_execute(keymap.command_verb, keymap.command_mult, stroke)
|
||||
keymap.reset_vim_command()
|
||||
return true
|
||||
end
|
||||
elseif editor_mode == 'insert' then
|
||||
if stroke == 'escape' then
|
||||
core.mode = 'command'
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
local commands = keymap.map[stroke]
|
||||
if commands then
|
||||
for _, cmd in ipairs(commands) do
|
||||
|
@ -75,7 +150,7 @@ function keymap.on_key_pressed(k)
|
|||
end
|
||||
|
||||
|
||||
function keymap.on_key_released(k)
|
||||
function keymap.on_key_released(editor_mode, k)
|
||||
local mk = modkey_map[k]
|
||||
if mk then
|
||||
keymap.modkeys[mk] = false
|
||||
|
|
|
@ -124,7 +124,8 @@ function StatusView:get_items()
|
|||
self.separator,
|
||||
string.format("%d%%", line / #dv.doc.lines * 100),
|
||||
}, {
|
||||
style.text, indent_label, indent_size,
|
||||
style.caret, core.mode ~= 'standard' and string.upper(core.mode) or '', style.text, self.separator2,
|
||||
indent_label, indent_size,
|
||||
style.dim, self.separator2, style.text,
|
||||
style.icon_font, "g",
|
||||
style.font, style.dim, self.separator2, style.text,
|
||||
|
|
Loading…
Reference in New Issue