mirror of
https://github.com/neovim/neovim.git
synced 2025-10-16 14:56:08 +00:00
fix(api): nvim_parse_cmd handle nextcmd for commands without EX_TRLBAR (#36055)
Problem: nvim_parse_cmd('exe "ls"|edit foo', {}) fails to separate nextcmd, returning args as { '"ls"|edit', 'foo' } instead of { '"ls"' } with nextcmd='edit foo'. Solution: Skip expressions before checking for '|' separator.
This commit is contained in:
@@ -1986,11 +1986,7 @@ void set_context_for_expression(expand_T *xp, char *arg, cmdidx_T cmdidx)
|
||||
}
|
||||
|
||||
// ":exe one two" completes "two"
|
||||
if ((cmdidx == CMD_execute
|
||||
|| cmdidx == CMD_echo
|
||||
|| cmdidx == CMD_echon
|
||||
|| cmdidx == CMD_echomsg)
|
||||
&& xp->xp_context == EXPAND_EXPRESSION) {
|
||||
if (cmd_has_expr_args(cmdidx) && xp->xp_context == EXPAND_EXPRESSION) {
|
||||
while (true) {
|
||||
char *const n = skiptowhite(arg);
|
||||
|
||||
|
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "auto/config.h"
|
||||
#include "nvim/api/private/defs.h"
|
||||
#include "nvim/api/private/dispatch.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/api/ui.h"
|
||||
#include "nvim/api/vimscript.h"
|
||||
@@ -1507,6 +1508,16 @@ static bool parse_bang(const exarg_T *eap, char **p)
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Check if command expects expression arguments that need special parsing
|
||||
bool cmd_has_expr_args(cmdidx_T cmdidx)
|
||||
{
|
||||
return cmdidx == CMD_execute
|
||||
|| cmdidx == CMD_echo
|
||||
|| cmdidx == CMD_echon
|
||||
|| cmdidx == CMD_echomsg
|
||||
|| cmdidx == CMD_echoerr;
|
||||
}
|
||||
|
||||
/// Parse command line and return information about the first command.
|
||||
/// If parsing is done successfully, need to free cmod_filter_pat and cmod_filter_regmatch.regprog
|
||||
/// after calling, usually done using undo_cmdmod() or execute_cmd().
|
||||
@@ -1596,6 +1607,22 @@ bool parse_cmdline(char **cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, const ch
|
||||
// Don't do this for ":read !cmd" and ":write !cmd".
|
||||
if ((eap->argt & EX_TRLBAR)) {
|
||||
separate_nextcmd(eap);
|
||||
} else if (cmd_has_expr_args(eap->cmdidx)) {
|
||||
// For commands without EX_TRLBAR, check for '|' separator
|
||||
// by skipping over expressions (including string literals)
|
||||
char *arg = eap->arg;
|
||||
while (*arg != NUL && *arg != '|' && *arg != '\n') {
|
||||
char *start = arg;
|
||||
skip_expr(&arg, NULL);
|
||||
// If skip_expr didn't advance, move forward to avoid infinite loop
|
||||
if (arg == start) {
|
||||
arg++;
|
||||
}
|
||||
}
|
||||
if (*arg == '|' || *arg == '\n') {
|
||||
eap->nextcmd = check_nextcmd(arg);
|
||||
*arg = NUL;
|
||||
}
|
||||
}
|
||||
// Fail if command doesn't support bang but is used with a bang
|
||||
if (!(eap->argt & EX_BANG) && eap->forceit) {
|
||||
|
@@ -4849,6 +4849,12 @@ describe('API', function()
|
||||
result = api.nvim_parse_cmd('copen 5', {})
|
||||
eq(5, result.count)
|
||||
end)
|
||||
it('parses nextcmd for commands #36029', function()
|
||||
local result = api.nvim_parse_cmd('exe "ls"|edit foo', {})
|
||||
eq({ '"ls"' }, result.args)
|
||||
eq('execute', result.cmd)
|
||||
eq('edit foo', result.nextcmd)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('nvim_cmd', function()
|
||||
|
Reference in New Issue
Block a user