diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-11-02 10:11:06 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-02 10:11:06 +0800 |
commit | 3688a333544251c887d78e6501eec55f0fb685f8 (patch) | |
tree | 746b606179500e2ecb5c4e93cac5b70e2e2e831f | |
parent | b25ae5d328fd58bae5052d1ae19bd1d17a991ea8 (diff) | |
download | rneovim-3688a333544251c887d78e6501eec55f0fb685f8.tar.gz rneovim-3688a333544251c887d78e6501eec55f0fb685f8.tar.bz2 rneovim-3688a333544251c887d78e6501eec55f0fb685f8.zip |
fix(lua): show stacktrace for error in vim.on_key() callback (#31021)
-rw-r--r-- | runtime/lua/vim/_editor.lua | 25 | ||||
-rw-r--r-- | src/nvim/lua/executor.c | 6 | ||||
-rw-r--r-- | test/functional/lua/vim_spec.lua | 27 |
3 files changed, 39 insertions, 19 deletions
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 3167721a70..cbab2a0165 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -701,11 +701,13 @@ end --- Executes the on_key callbacks. ---@private function vim._on_key(buf, typed_buf) - local failed_ns_ids = {} - local failed_messages = {} + local failed = {} ---@type [integer, string][] local discard = false for k, v in pairs(on_key_cbs) do - local ok, rv = pcall(v[1], buf, typed_buf) + local fn = v[1] + local ok, rv = xpcall(function() + return fn(buf, typed_buf) + end, debug.traceback) if ok and rv ~= nil then if type(rv) == 'string' and #rv == 0 then discard = true @@ -718,19 +720,16 @@ function vim._on_key(buf, typed_buf) end if not ok then vim.on_key(nil, k) - table.insert(failed_ns_ids, k) - table.insert(failed_messages, rv) + table.insert(failed, { k, rv }) end end - if failed_ns_ids[1] then - error( - string.format( - "Error executing 'on_key' with ns_ids '%s'\n Messages: %s", - table.concat(failed_ns_ids, ', '), - table.concat(failed_messages, '\n') - ) - ) + if #failed > 0 then + local errmsg = '' + for _, v in ipairs(failed) do + errmsg = errmsg .. string.format('\nWith ns_id %d: %s', v[1], v[2]) + end + error(errmsg) end return discard end diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 27ebfacc5f..e4da274204 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -2099,9 +2099,9 @@ bool nlua_execute_on_key(int c, char *typed_buf) int save_got_int = got_int; got_int = false; // avoid interrupts when the key typed is Ctrl-C bool discard = false; - if (nlua_pcall(lstate, 2, 1)) { - nlua_error(lstate, - _("Error executing vim.on_key Lua callback: %.*s")); + // Do not use nlua_pcall here to avoid duplicate stack trace information + if (lua_pcall(lstate, 2, 1, 0)) { + nlua_error(lstate, _("Error executing vim.on_key() callbacks: %.*s")); } else { if (lua_isboolean(lstate, -1)) { discard = lua_toboolean(lstate, -1); diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 55ca489a9a..9fd7184cb0 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -3312,10 +3312,17 @@ describe('lua stdlib', function() eq('inext lines<ESC>', exec_lua [[return table.concat(keys, '')]]) end) - it('skips any function that caused an error', function() + it('skips any function that caused an error and shows stacktrace', function() insert([[hello world]]) exec_lua [[ + local function ErrF2() + error("Dumb Error") + end + local function ErrF1() + ErrF2() + end + keys = {} return vim.on_key(function(buf) @@ -3326,7 +3333,7 @@ describe('lua stdlib', function() table.insert(keys, buf) if buf == 'l' then - error("Dumb Error") + ErrF1() end end) ]] @@ -3336,6 +3343,19 @@ describe('lua stdlib', function() -- Only the first letter gets added. After that we remove the callback eq('inext l', exec_lua [[ return table.concat(keys, '') ]]) + + local errmsg = api.nvim_get_vvar('errmsg') + matches( + [[ +^Error executing vim%.on%_key%(%) callbacks:.* +With ns%_id %d+: .*: Dumb Error +stack traceback: +.*: in function 'error' +.*: in function 'ErrF2' +.*: in function 'ErrF1' +.*]], + errmsg + ) end) it('argument 1 is keys after mapping, argument 2 is typed keys', function() @@ -3449,6 +3469,7 @@ describe('lua stdlib', function() -- second key produces an error which removes the callback exec_lua [[ n_call = 0 + vim.on_key(function(buf, typed_buf) if typed_buf == 'x' then n_call = n_call + 1 @@ -3460,7 +3481,7 @@ describe('lua stdlib', function() api.nvim_buf_set_lines(0, 0, -1, true, { '54321' }) local function cleanup_msg(msg) - return (remove_trace(msg):gsub('^Error.*\n *Messages: ', '')) + return msg:gsub('^Error .*\nWith ns%_id %d+: ', '') end feed('x') |