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:
Famiu Haque
2022-05-07 08:57:21 +06:00
parent b2a8ed0855
commit 14f3383c0d
4 changed files with 45 additions and 10 deletions

View File

@@ -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.

View File

@@ -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));

View File

@@ -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;
} }

View File

@@ -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',