fix(input): discard following keys when discarding <Cmd>/K_LUA (#36498)

Technically the current behavior does match documentation. However, the
keys following <Cmd>/K_LUA aren't normally received by vim.on_key()
callbacks either, so it does makes sense to discard them along with the
preceding key.

One may also argue that vim.on_key() callbacks should instead receive
the following keys together with the <Cmd>/K_LUA, but doing that may
cause some performance problems, and even in that case the keys should
still be discarded together.
This commit is contained in:
zeertzjq
2025-11-20 12:33:02 +08:00
committed by GitHub
parent 3b6df3ae55
commit a04c73cc17
8 changed files with 112 additions and 16 deletions

View File

@@ -986,7 +986,7 @@ static int insert_handle_key(InsertState *s)
goto check_pum;
case K_LUA:
map_execute_lua(false);
map_execute_lua(false, false);
check_pum:
// nvim_select_popupmenu_item() can be called from the handling of

View File

@@ -1296,7 +1296,7 @@ static int command_line_execute(VimState *state, int key)
} else if (s->c == K_COMMAND) {
do_cmdline(NULL, getcmdkeycmd, NULL, DOCMD_NOWAIT);
} else {
map_execute_lua(false);
map_execute_lua(false, false);
}
// If the window changed incremental search state is not valid.
if (s->is_state.winid != curwin->handle) {

View File

@@ -1798,6 +1798,16 @@ int vgetc(void)
// Execute Lua on_key callbacks.
kvi_push(on_key_buf, NUL);
if (nlua_execute_on_key(c, on_key_buf.items)) {
// Keys following K_COMMAND/K_LUA/K_PASTE_START aren't normally received by
// vim.on_key() callbacks, so discard them along with the current key.
if (c == K_COMMAND) {
xfree(getcmdkeycmd(NUL, NULL, 0, false));
} else if (c == K_LUA) {
map_execute_lua(false, true);
} else if (c == K_PASTE_START) {
paste_repeat(0);
}
// Discard the current key.
c = K_IGNORE;
}
kvi_destroy(on_key_buf);
@@ -3213,9 +3223,10 @@ char *getcmdkeycmd(int promptc, void *cookie, int indent, bool do_concat)
/// Handle a Lua mapping: get its LuaRef from typeahead and execute it.
///
/// @param may_repeat save the LuaRef for redoing with "." later
/// @param discard discard the keys instead of executing the LuaRef
///
/// @return false if getting the LuaRef was aborted, true otherwise
bool map_execute_lua(bool may_repeat)
bool map_execute_lua(bool may_repeat, bool discard)
{
garray_T line_ga;
int c1 = -1;
@@ -3241,9 +3252,9 @@ bool map_execute_lua(bool may_repeat)
no_mapping--;
if (aborted) {
if (aborted || discard) {
ga_clear(&line_ga);
return false;
return !aborted;
}
LuaRef ref = (LuaRef)atoi(line_ga.ga_data);

View File

@@ -3191,7 +3191,7 @@ static void nv_colon(cmdarg_T *cap)
}
if (is_lua) {
cmd_result = map_execute_lua(true);
cmd_result = map_execute_lua(true, false);
} else {
// get a command line and execute it
cmd_result = do_cmdline(NULL, is_cmdkey ? getcmdkeycmd : getexline, NULL,

View File

@@ -986,7 +986,7 @@ static int terminal_execute(VimState *state, int key)
break;
case K_LUA:
map_execute_lua(false);
map_execute_lua(false, false);
break;
case Ctrl_N: