diff --git a/runtime/lua/vim/_core/ex_cmd.lua b/runtime/lua/vim/_core/ex_cmd.lua index a1a7ddb07d..2c3b73dd7e 100644 --- a/runtime/lua/vim/_core/ex_cmd.lua +++ b/runtime/lua/vim/_core/ex_cmd.lua @@ -174,19 +174,13 @@ local available_subcmds = vim.tbl_keys(actions) --- Implements command: `:lsp {subcmd} {name}?`. --- @param eap vim._core.ExCmdArgs function M.ex_lsp(eap) - local fargs = api.nvim_parse_cmd('lsp ' .. eap.args, {}).args - if not fargs then - return - end - local subcmd = fargs[1] + local subcmd = eap.fargs[1] if not vim.list_contains(available_subcmds, subcmd) then echo_err(N_('E5800: Invalid :lsp subcommand: %s'):format(subcmd)) return end - local clients = { unpack(fargs, 2) } - - actions[subcmd](clients) + actions[subcmd]({ unpack(eap.fargs, 2) }) end --- Completion logic for `:lsp` command diff --git a/runtime/lua/vim/_core/swapfile.lua b/runtime/lua/vim/_core/swapfile.lua index 7e3bee993f..12f9b56a50 100644 --- a/runtime/lua/vim/_core/swapfile.lua +++ b/runtime/lua/vim/_core/swapfile.lua @@ -52,7 +52,7 @@ end --- @param items string[] List of swapfile paths. function M.select_swap(items) vim.ui.select(items, { - prompt = N_('Enter number of swap file to use (q or empty cancels):'), + prompt = N_('Select a swapfile:'), kind = 'swap', format_item = format_swap, }, function(_, idx) diff --git a/runtime/lua/vim/_core/tag.lua b/runtime/lua/vim/_core/tag.lua index 3c0c2f544f..82ab6d5e4f 100644 --- a/runtime/lua/vim/_core/tag.lua +++ b/runtime/lua/vim/_core/tag.lua @@ -30,7 +30,7 @@ function M.select_tag(eap, extra) end vim.ui.select(items, { - prompt = N_('Type number and (q or empty cancels):'), + prompt = N_('Select a tag:'), kind = 'tag', format_item = function(m) local marker = m.cur and '>' or ' ' 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) { diff --git a/test/functional/ex_cmds/lsp_spec.lua b/test/functional/ex_cmds/lsp_spec.lua index 5da3c79779..3922c55b14 100644 --- a/test/functional/ex_cmds/lsp_spec.lua +++ b/test/functional/ex_cmds/lsp_spec.lua @@ -4,7 +4,6 @@ local t_lsp = require('test.functional.plugin.lsp.testutil') local clear = n.clear local eq = t.eq -local pcall_err = t.pcall_err local exec_lua = n.exec_lua local create_server_definition = t_lsp.create_server_definition diff --git a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua index 0e827be33f..84a3bebfe0 100644 --- a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua +++ b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua @@ -172,7 +172,7 @@ describe("preserve and (R)ecover with custom 'directory'", function() text = text .. (#chunk >= 2 and chunk[2] or chunk[1]) end -- New ui.select-driven prompt; rich info from format_item. - eq(true, text:match('Enter number of swap file to use') ~= nil) + eq(true, text:match('Select a swapfile:') ~= nil) eq(true, text:match('%.swo') ~= nil) eq(true, text:match('%.swp') ~= nil) eq(true, text:match('host name:') ~= nil) @@ -183,7 +183,7 @@ describe("preserve and (R)ecover with custom 'directory'", function() else screen:expect({ any = { - vim.pesc('Enter number of swap file to use (q or empty cancels):'), + vim.pesc('Select a swapfile:'), '\n1:.*%.swo', '\n2:.*%.swp', 'host name:', diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index 44af9d478f..0307aa563b 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -413,7 +413,7 @@ describe('ui/ext_messages', function() for _, chunk in ipairs(msg.content) do text = text .. (#chunk >= 2 and chunk[2] or chunk[1]) end - t.matches('^Type number and %(q or empty cancels%):\n', text) + t.matches('^Select a tag:\n', text) t.matches('1: > F%s+help%.txt%s+', text) end screen.messages = {} diff --git a/test/old/testdir/test_tagjump.vim b/test/old/testdir/test_tagjump.vim index b03d256cc0..7b9431e2df 100644 --- a/test/old/testdir/test_tagjump.vim +++ b/test/old/testdir/test_tagjump.vim @@ -1241,7 +1241,7 @@ func Test_tselect_listing() let l = split(execute("tselect first"), "\n") " Nvim: :tselect goes through vim.ui.select(). let expected =<< [DATA] -Type number and (q or empty cancels): +Select a tag: 1: FS v first Xfoo 2: FS v first Xfoo [DATA]