aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/lua/executor.c
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2026-05-02 10:46:23 -0400
committerGitHub <noreply@github.com>2026-05-02 10:46:23 -0400
commitd788dd2811bfbfb0daa915ef974d072075a6bceb (patch)
tree1ef170ffe3819171b3881db63a5aa6fc2bee4056 /src/nvim/lua/executor.c
parent22f3b283672bc3e4a8d87cfa18e9764abdf876b7 (diff)
downloadrneovim-d788dd2811bfbfb0daa915ef974d072075a6bceb.tar.gz
rneovim-d788dd2811bfbfb0daa915ef974d072075a6bceb.tar.bz2
rneovim-d788dd2811bfbfb0daa915ef974d072075a6bceb.zip
refactor(excmd): pass fargs to Lua for builtin cmds #39528
Problem: The fallback that tokenizes `eap->arg` by unescaped whitespace (when the parser doesn't pre-split via `EX_EXPAND` etc.) lives in `nlua_do_ucmd`, so only user-command callbacks got `eap.fargs`. Builtin commands routed through `nlua_call_excmd` have to re-parse the args themselves (e.g. `M.ex_lsp`). Solution: - Move the tokenization into `nlua_push_eap` so every Lua handler sees `eap.fargs`. Keep only the `EX_NOSPC` override in `nlua_do_ucmd` (the `nargs=1`/`?` case which is genuinely user-command-specific). - Drop the re-parse in `M.ex_lsp`.
Diffstat (limited to 'src/nvim/lua/executor.c')
-rw-r--r--src/nvim/lua/executor.c49
1 files changed, 25 insertions, 24 deletions
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 7078a0650e..fda848e51c 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -223,13 +223,35 @@ static void nlua_push_eap(lua_State *lstate, exarg_T *eap, const cmdmod_T *cmod)
lua_setfield(lstate, -2, "reg");
// Push pre-split args as "fargs" list, if available (set by the command-line parser).
- if (eap->args != NULL && eap->argc > 0) {
+ // - Or fall back to splitting `eap->arg` on unescaped whitespace.
+ // - Usercmds with nargs=1/? need different splitting, handled by `nlua_do_ucmd`.
+ if (eap->args != NULL) {
lua_createtable(lstate, (int)eap->argc, 0);
for (size_t i = 0; i < eap->argc; i++) {
lua_pushlstring(lstate, eap->args[i], eap->arglens[i]);
lua_rawseti(lstate, -2, (int)i + 1);
}
lua_setfield(lstate, -2, "fargs");
+ } else {
+ lua_newtable(lstate);
+ size_t length = strlen(eap->arg);
+ if (length > 0) {
+ size_t end = 0;
+ size_t len = 0;
+ int i = 1;
+ char *buf = xcalloc(length, sizeof(char));
+ bool done = false;
+ while (!done) {
+ done = uc_split_args_iter(eap->arg, length, &end, buf, &len);
+ if (len > 0) {
+ lua_pushlstring(lstate, buf, len);
+ lua_rawseti(lstate, -2, i);
+ i++;
+ }
+ }
+ xfree(buf);
+ }
+ lua_setfield(lstate, -2, "fargs");
}
}
@@ -2336,37 +2358,16 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview)
lua_setfield(lstate, -2, "count");
}
- // Override fargs for user command-specific splitting (nlua_push_eap already set it
- // for the eap->args!=NULL case, but user commands need special handling for nargs).
+ // Override fargs for nargs=1/? (EX_NOSPC): the whole arg as one element (or empty).
+ // Other cases are handled by `nlua_push_eap`.
if (cmd->uc_argt & EX_NOSPC) {
- // nargs=1 or "?": fargs is the whole arg as a single element, or empty.
lua_createtable(lstate, 1, 0);
if ((cmd->uc_argt & EX_NEEDARG) || *eap->arg != NUL) {
lua_pushstring(lstate, eap->arg);
lua_rawseti(lstate, -2, 1);
}
lua_setfield(lstate, -2, "fargs");
- } else if (eap->args == NULL) {
- // Pre-split args not available: tokenize eap->arg by unescaped whitespace.
- lua_newtable(lstate);
- size_t length = strlen(eap->arg);
- size_t end = 0;
- size_t len = 0;
- int i = 1;
- char *buf = xcalloc(length, sizeof(char));
- bool done = false;
- while (!done) {
- done = uc_split_args_iter(eap->arg, length, &end, buf, &len);
- if (len > 0) {
- lua_pushlstring(lstate, buf, len);
- lua_rawseti(lstate, -2, i);
- i++;
- }
- }
- xfree(buf);
- lua_setfield(lstate, -2, "fargs");
}
- // else: eap->args was available, nlua_push_eap already set fargs.
char nargs[2];
if (cmd->uc_argt & EX_EXTRA) {