fix(excmd): nlua_call_excmd require() failure is a "lua_error"

Although `nlua_call_excmd` is semantically for implementing Ex-commands,
the `require()` should never fail, so that's a "Lua error".

But if the call itself fails (the later `semsg` call), that's an "Ex
cmd" error.
This commit is contained in:
Justin M. Keyes
2026-04-19 17:37:03 +02:00
parent 919a109951
commit a38451be40
5 changed files with 22 additions and 7 deletions

View File

@@ -48,7 +48,7 @@ local dup_allowed = {
E509 = 2,
E5101 = 2,
E5102 = 2,
E5108 = 6,
E5108 = 5,
E5111 = 2,
E513 = 2,
E521 = 2,

View File

@@ -378,7 +378,9 @@ bool do_intthrow(cstack_T *cstack)
return true;
}
/// Get an exception message that is to be stored in current_exception->value.
/// Gets an exception message that is to be stored in current_exception->value.
///
/// For error exceptions (ET_ERROR), formats the message as "Vim(cmdname):Exx: …".
char *get_exception_string(void *value, except_type_T type, char *cmdname, bool *should_free)
{
char *ret;

View File

@@ -1785,8 +1785,7 @@ bool nlua_call_excmd(const char *module, const char *func, exarg_T *eap, const c
lua_getglobal(lstate, "require");
lua_pushstring(lstate, module);
if (lua_pcall(lstate, 1, 1, 0) != 0) {
semsg("E5108: %s", lua_tostring(lstate, -1));
lua_pop(lstate, 1);
nlua_error(lstate, "E5108: %s");
return false;
}
lua_getfield(lstate, -1, func);
@@ -1802,7 +1801,8 @@ bool nlua_call_excmd(const char *module, const char *func, exarg_T *eap, const c
}
if (nlua_pcall(lstate, nargs, 0)) {
semsg("E5108: %s", lua_tostring(lstate, -1));
// Not "E5108" because this is a logical/application error, not a "Lua error".
emsg(lua_tostring(lstate, -1));
lua_pop(lstate, 1);
return false;
}

View File

@@ -8,7 +8,20 @@ local fn = n.fn
local pcall_err = t.pcall_err
local assert_alive = n.assert_alive
describe('Ex cmds', function()
describe('nlua_call_excmd excmds', function()
-- Exercise nlua_call_excmd by testing commands implemented with it (:log, :lsp).
before_each(function()
clear()
end)
it('error propagation, formatting', function()
t.eq('Vim(lsp):E5800: Invalid :lsp subcommand: bogus', pcall_err(command, 'lsp bogus'))
t.matches('Vim%(log%):E5200: No such log.*', pcall_err(command, 'log bogus'))
end)
end)
describe('excmds', function()
before_each(function()
clear()
end)

View File

@@ -29,7 +29,7 @@ describe(':lsp', function()
env = { VIMRUNTIME = 'non-existent' },
}
t.matches(
[[Vim%(lsp%):E%d+: .*module 'vim%.lsp' not found:]],
[[.*module 'vim%.lsp' not found:]],
vim.split(t.pcall_err(n.command, 'lsp enable dummy'), '\n')[1]
)
end)