mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
fix(api): make nvim_parse_cmd
work correctly with both range and count
It seems range and count can be used together in commands. This PR fixes the behavior of `nvim_parse_cmd` for those cases by removing the mutual exclusivity of "range" and "count". It also removes range line number validation for `nvim_parse_cmd` as it's not its job to validate the command.
This commit is contained in:
@@ -1782,8 +1782,7 @@ nvim_parse_cmd({str}, {opts}) *nvim_parse_cmd()*
|
|||||||
item was specified and two elements if both range items
|
item was specified and two elements if both range items
|
||||||
were specified.
|
were specified.
|
||||||
• count: (number) Any |<count>| that was supplied to the
|
• count: (number) Any |<count>| that was supplied to the
|
||||||
command. -1 if command cannot take a count. Mutually
|
command. -1 if command cannot take a count.
|
||||||
exclusive with "range".
|
|
||||||
• reg: (number) The optional command |<register>|, if
|
• reg: (number) The optional command |<register>|, if
|
||||||
specified. Empty string if not specified or if command
|
specified. Empty string if not specified or if command
|
||||||
cannot take a register.
|
cannot take a register.
|
||||||
|
@@ -752,7 +752,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E
|
|||||||
/// no range was specified, one element if only a single range item was
|
/// no range was specified, one element if only a single range item was
|
||||||
/// specified and two elements if both range items were specified.
|
/// specified and two elements if both range items were specified.
|
||||||
/// - count: (number) Any |<count>| that was supplied to the command. -1 if command cannot
|
/// - count: (number) Any |<count>| that was supplied to the command. -1 if command cannot
|
||||||
/// take a count. Mutually exclusive with "range".
|
/// take a count.
|
||||||
/// - reg: (number) The optional command |<register>|, if specified. Empty string if not
|
/// - reg: (number) The optional command |<register>|, if specified. Empty string if not
|
||||||
/// specified or if command cannot take a register.
|
/// specified or if command cannot take a register.
|
||||||
/// - bang: (boolean) Whether command contains a |<bang>| (!) modifier.
|
/// - bang: (boolean) Whether command contains a |<bang>| (!) modifier.
|
||||||
@@ -853,7 +853,7 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err)
|
|||||||
PUT(result, "cmd", CSTR_TO_OBJ((char *)get_command_name(NULL, ea.cmdidx)));
|
PUT(result, "cmd", CSTR_TO_OBJ((char *)get_command_name(NULL, ea.cmdidx)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ea.argt & EX_RANGE) && !(ea.argt & EX_COUNT) && ea.addr_count > 0) {
|
if ((ea.argt & EX_RANGE) && ea.addr_count > 0) {
|
||||||
Array range = ARRAY_DICT_INIT;
|
Array range = ARRAY_DICT_INIT;
|
||||||
if (ea.addr_count > 1) {
|
if (ea.addr_count > 1) {
|
||||||
ADD(range, INTEGER_OBJ(ea.line1));
|
ADD(range, INTEGER_OBJ(ea.line1));
|
||||||
|
@@ -1320,7 +1320,7 @@ static void parse_register(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_count(exarg_T *eap, char **errormsg)
|
static int parse_count(exarg_T *eap, char **errormsg, bool validate)
|
||||||
{
|
{
|
||||||
// Check for a count. When accepting a EX_BUFNAME, don't use "123foo" as a
|
// Check for a count. When accepting a EX_BUFNAME, don't use "123foo" as a
|
||||||
// count, it's a buffer name.
|
// count, it's a buffer name.
|
||||||
@@ -1348,7 +1348,7 @@ static int parse_count(exarg_T *eap, char **errormsg)
|
|||||||
eap->line2 += n - 1;
|
eap->line2 += n - 1;
|
||||||
eap->addr_count++;
|
eap->addr_count++;
|
||||||
// Be vi compatible: no error message for out of range.
|
// Be vi compatible: no error message for out of range.
|
||||||
if (eap->line2 > curbuf->b_ml.ml_line_count) {
|
if (validate && eap->line2 > curbuf->b_ml.ml_line_count) {
|
||||||
eap->line2 = curbuf->b_ml.ml_line_count;
|
eap->line2 = curbuf->b_ml.ml_line_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1426,7 +1426,7 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er
|
|||||||
}
|
}
|
||||||
p = find_command(eap, NULL);
|
p = find_command(eap, NULL);
|
||||||
|
|
||||||
// Set command attribute type and parse command range
|
// Set command address type and parse command range
|
||||||
set_cmd_addr_type(eap, (char_u *)p);
|
set_cmd_addr_type(eap, (char_u *)p);
|
||||||
eap->cmd = cmd;
|
eap->cmd = cmd;
|
||||||
if (parse_cmd_address(eap, errormsg, false) == FAIL) {
|
if (parse_cmd_address(eap, errormsg, false) == FAIL) {
|
||||||
@@ -1499,7 +1499,7 @@ bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **er
|
|||||||
|
|
||||||
// Parse register and count
|
// Parse register and count
|
||||||
parse_register(eap);
|
parse_register(eap);
|
||||||
if (parse_count(eap, errormsg) == FAIL) {
|
if (parse_count(eap, errormsg, false) == FAIL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1981,7 +1981,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
|
|||||||
|
|
||||||
// Parse register and count
|
// Parse register and count
|
||||||
parse_register(&ea);
|
parse_register(&ea);
|
||||||
if (parse_count(&ea, &errormsg) == FAIL) {
|
if (parse_count(&ea, &errormsg, true) == FAIL) {
|
||||||
goto doend;
|
goto doend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3176,7 +3176,7 @@ describe('API', function()
|
|||||||
cmd = 'buffer',
|
cmd = 'buffer',
|
||||||
args = {},
|
args = {},
|
||||||
bang = false,
|
bang = false,
|
||||||
range = {},
|
range = { 1 },
|
||||||
count = 1,
|
count = 1,
|
||||||
reg = '',
|
reg = '',
|
||||||
addr = 'buf',
|
addr = 'buf',
|
||||||
@@ -3243,6 +3243,42 @@ describe('API', function()
|
|||||||
}
|
}
|
||||||
}, meths.parse_cmd('put +', {}))
|
}, meths.parse_cmd('put +', {}))
|
||||||
end)
|
end)
|
||||||
|
it('works with range, count and register', function()
|
||||||
|
eq({
|
||||||
|
cmd = 'delete',
|
||||||
|
args = {},
|
||||||
|
bang = false,
|
||||||
|
range = { 3, 7 },
|
||||||
|
count = 7,
|
||||||
|
reg = '*',
|
||||||
|
addr = 'line',
|
||||||
|
magic = {
|
||||||
|
file = false,
|
||||||
|
bar = true
|
||||||
|
},
|
||||||
|
nargs = '0',
|
||||||
|
nextcmd = '',
|
||||||
|
mods = {
|
||||||
|
browse = false,
|
||||||
|
confirm = false,
|
||||||
|
emsg_silent = false,
|
||||||
|
hide = false,
|
||||||
|
keepalt = false,
|
||||||
|
keepjumps = false,
|
||||||
|
keepmarks = false,
|
||||||
|
keeppatterns = false,
|
||||||
|
lockmarks = false,
|
||||||
|
noautocmd = false,
|
||||||
|
noswapfile = false,
|
||||||
|
sandbox = false,
|
||||||
|
silent = false,
|
||||||
|
vertical = false,
|
||||||
|
split = "",
|
||||||
|
tab = 0,
|
||||||
|
verbose = -1
|
||||||
|
}
|
||||||
|
}, meths.parse_cmd('1,3delete * 5', {}))
|
||||||
|
end)
|
||||||
it('works with bang', function()
|
it('works with bang', function()
|
||||||
eq({
|
eq({
|
||||||
cmd = 'write',
|
cmd = 'write',
|
||||||
|
Reference in New Issue
Block a user