fix(Mode): cursor position doesn't update because of `getchar` (#27)

The solution here has been to use `vim.highlight.range` and hide the
real cursor.

SEE neovim/neovim#20793
pull/32/head
Iron-E 2 months ago committed by GitHub
parent 45577b6e19
commit 3966014dbc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -11,6 +11,7 @@ local utils = require 'libmodal.utils' --- @type libmodal.utils
--- @field private instruction fun()|{[string]: fun()|string}
--- @field private mappings libmodal.collections.ParseTable
--- @field private name string
--- @field private ns number the namespace where cursor highlights are drawn on
--- @field private popups libmodal.collections.Stack
--- @field private show_name fun()
--- @field private supress_exit boolean
@ -29,12 +30,14 @@ TIMEOUT.CHAR_NUMBER = TIMEOUT.CHAR:byte()
--- execute the `instruction`.
--- @param instruction fun()|string a Lua function or Vimscript command.
--- @return nil
function Mode.execute_instruction(instruction)
function Mode:execute_instruction(instruction)
if type(instruction) == 'function' then
instruction()
else
vim.api.nvim_command(instruction)
end
self:redraw_virtual_cursor()
end
--- check the user's input against the `self.instruction` mappings to see if there is anything to execute.
@ -67,7 +70,7 @@ function Mode:check_input_for_mapping()
TIMEOUT:SEND()
-- if there is a command, execute it.
if cmd[ParseTable.CR] then
self.execute_instruction(cmd[ParseTable.CR])
self:execute_instruction(cmd[ParseTable.CR])
end
-- clear input
self.input_bytes = {}
@ -76,13 +79,18 @@ function Mode:check_input_for_mapping()
)
else -- the command was an actual vim command.
--- @diagnostic disable-next-line:param-type-mismatch already checked `cmd` != `table`
self.execute_instruction(cmd)
self:execute_instruction(cmd)
self.input_bytes = {}
end
self.popups:peek():refresh(self.input_bytes)
end
--- clears the virtual cursor from the screen
function Mode:clear_virt_cursor()
vim.api.nvim_buf_clear_namespace(0, self.ns, 0, -1);
end
--- enter this mode.
--- @return nil
function Mode:enter()
@ -92,6 +100,11 @@ function Mode:enter()
self.popups:push(utils.Popup.new())
end
--- HACK: https://github.com/neovim/neovim/issues/20793
vim.api.nvim_command 'highlight Cursor blend=100'
vim.schedule(function() vim.opt.guicursor:append { 'a:Cursor/lCursor' } end)
self:render_virt_cursor()
self.previous_mode_name = vim.g.libmodalActiveModeName
vim.g.libmodalActiveModeName = self.name
@ -170,6 +183,11 @@ function Mode:tear_down()
self.popups:pop():close()
end
--- HACK: https://github.com/neovim/neovim/issues/20793
self:clear_virt_cursor()
vim.schedule(function() vim.opt.guicursor:remove { 'a:Cursor/lCursor' } end)
vim.api.nvim_command 'highlight Cursor blend=0'
if self.previous_mode_name and #vim.trim(self.previous_mode_name) < 1 then
vim.g.libmodalActiveModeName = nil
else
@ -179,6 +197,19 @@ function Mode:tear_down()
utils.api.redraw()
end
--- clears and then renders the virtual cursor
function Mode:redraw_virtual_cursor()
self:clear_virt_cursor()
self:render_virt_cursor()
end
--- render the virtual cursor using extmarks
function Mode:render_virt_cursor()
local line_nr, col_nr = unpack(vim.api.nvim_win_get_cursor(0))
line_nr = line_nr - 1 -- win_get_cursor returns +1 for our purpose
vim.highlight.range(0, self.ns, 'Cursor', { line_nr, col_nr }, { line_nr, col_nr + 1 }, {})
end
--- create a new mode.
--- @param name string the name of the mode.
--- @param instruction fun()|string|table a Lua function, keymap dictionary, Vimscript command.
@ -193,6 +224,7 @@ function Mode.new(name, instruction, supress_exit)
input = utils.Vars.new('input', name),
instruction = instruction,
name = name,
ns = vim.api.nvim_create_namespace('libmodal' .. name),
},
Mode
)

Loading…
Cancel
Save