refactor(api): make range in nvim_parse_cmd an array

Changes the `range` value in `nvim_parse_cmd` into an array to describe
range information more concisely. Also makes `range` and `count` be
mutually exclusive by making count `-1` when command takes a range
instead of a count. Additionally corrects the behavior of `count` for
built-in commands by making the default count `0`.
This commit is contained in:
Famiu Haque 2022-05-05 01:49:29 +06:00
parent e6c71574a0
commit 7aedcd8feb
3 changed files with 36 additions and 85 deletions

View File

@ -1775,14 +1775,15 @@ nvim_parse_cmd({str}, {opts}) *nvim_parse_cmd()*
Dictionary containing command information, with these Dictionary containing command information, with these
keys: keys:
• cmd: (string) Command name. • cmd: (string) Command name.
• range: (number) Number of items in the command • range: (array) Command <range>. Can have 0-2 elements
|<range>|. Can be 0, 1 or 2. depending on how many items the range contains. Has no
• line1: (number) Starting line of command |<range>|. -1 elements if command doesn't accept a range or if no
if command cannot take a range. |<line1>| range was specified, one element if only a single range
• line2: (number) Final line of command |<range>|. -1 if item was specified and two elements if both range items
command cannot take a range. |<line2>| 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. command. -1 if command cannot take a count. Mutually
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

@ -747,13 +747,12 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E
/// @param[out] err Error details, if any. /// @param[out] err Error details, if any.
/// @return Dictionary containing command information, with these keys: /// @return Dictionary containing command information, with these keys:
/// - cmd: (string) Command name. /// - cmd: (string) Command name.
/// - range: (number) Number of items in the command |<range>|. Can be 0, 1 or 2. /// - range: (array) Command <range>. Can have 0-2 elements depending on how many items the
/// - line1: (number) Starting line of command |<range>|. -1 if command cannot take a range. /// range contains. Has no elements if command doesn't accept a range or if
/// |<line1>| /// no range was specified, one element if only a single range item was
/// - line2: (number) Final line of command |<range>|. -1 if command cannot take a range. /// specified and two elements if both range items were specified.
/// |<line2>|
/// - 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. /// take a count. Mutually exclusive with "range".
/// - 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.
@ -849,15 +848,24 @@ 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)));
} }
PUT(result, "range", INTEGER_OBJ(ea.addr_count)); if ((ea.argt & EX_RANGE) && !(ea.argt & EX_COUNT) && ea.addr_count > 0) {
PUT(result, "line1", INTEGER_OBJ((ea.argt & EX_RANGE) ? ea.line1 : -1)); Array range = ARRAY_DICT_INIT;
PUT(result, "line2", INTEGER_OBJ((ea.argt & EX_RANGE) ? ea.line2 : -1)); if (ea.addr_count > 1) {
ADD(range, INTEGER_OBJ(ea.line1));
}
ADD(range, INTEGER_OBJ(ea.line2));
PUT(result, "range", ARRAY_OBJ(range));;
} else {
PUT(result, "range", ARRAY_OBJ(ARRAY_DICT_INIT));
}
if (ea.argt & EX_COUNT) { if (ea.argt & EX_COUNT) {
if (ea.addr_count > 0 || cmd == NULL) { if (ea.addr_count > 0) {
PUT(result, "count", INTEGER_OBJ(ea.line2)); PUT(result, "count", INTEGER_OBJ(ea.line2));
} else { } else if (cmd != NULL) {
PUT(result, "count", INTEGER_OBJ(cmd->uc_def)); PUT(result, "count", INTEGER_OBJ(cmd->uc_def));
} else {
PUT(result, "count", INTEGER_OBJ(0));
} }
} else { } else {
PUT(result, "count", INTEGER_OBJ(-1)); PUT(result, "count", INTEGER_OBJ(-1));

View File

@ -3104,9 +3104,7 @@ describe('API', function()
cmd = 'echo', cmd = 'echo',
args = { 'foo' }, args = { 'foo' },
bang = false, bang = false,
line1 = -1, range = {},
line2 = -1,
range = 0,
count = -1, count = -1,
reg = '', reg = '',
addr = 'none', addr = 'none',
@ -3142,9 +3140,7 @@ describe('API', function()
cmd = 'substitute', cmd = 'substitute',
args = { '/math.random/math.max/' }, args = { '/math.random/math.max/' },
bang = false, bang = false,
line1 = 4, range = { 4, 6 },
line2 = 6,
range = 2,
count = -1, count = -1,
reg = '', reg = '',
addr = 'line', addr = 'line',
@ -3180,9 +3176,7 @@ describe('API', function()
cmd = 'buffer', cmd = 'buffer',
args = {}, args = {},
bang = false, bang = false,
line1 = 1, range = {},
line2 = 1,
range = 1,
count = 1, count = 1,
reg = '', reg = '',
addr = 'buf', addr = 'buf',
@ -3218,9 +3212,7 @@ describe('API', function()
cmd = 'put', cmd = 'put',
args = {}, args = {},
bang = false, bang = false,
line1 = 1, range = {},
line2 = 1,
range = 0,
count = -1, count = -1,
reg = '+', reg = '+',
addr = 'line', addr = 'line',
@ -3256,9 +3248,7 @@ describe('API', function()
cmd = 'write', cmd = 'write',
args = {}, args = {},
bang = true, bang = true,
line1 = 1, range = {},
line2 = 1,
range = 0,
count = -1, count = -1,
reg = '', reg = '',
addr = 'line', addr = 'line',
@ -3294,9 +3284,7 @@ describe('API', function()
cmd = 'split', cmd = 'split',
args = { 'foo.txt' }, args = { 'foo.txt' },
bang = false, bang = false,
line1 = 1, range = {},
line2 = 1,
range = 0,
count = -1, count = -1,
reg = '', reg = '',
addr = '?', addr = '?',
@ -3333,9 +3321,7 @@ describe('API', function()
cmd = 'MyCommand', cmd = 'MyCommand',
args = { 'test', 'it' }, args = { 'test', 'it' },
bang = true, bang = true,
line1 = 4, range = { 4, 6 },
line2 = 6,
range = 2,
count = -1, count = -1,
reg = '', reg = '',
addr = 'line', addr = 'line',
@ -3371,9 +3357,7 @@ describe('API', function()
cmd = 'argadd', cmd = 'argadd',
args = { 'a.txt' }, args = { 'a.txt' },
bang = false, bang = false,
line1 = 0, range = {},
line2 = 0,
range = 0,
count = -1, count = -1,
reg = '', reg = '',
addr = 'arg', addr = 'arg',
@ -3410,9 +3394,7 @@ describe('API', function()
cmd = 'MyCommand', cmd = 'MyCommand',
args = { 'test it' }, args = { 'test it' },
bang = false, bang = false,
line1 = -1, range = {},
line2 = -1,
range = 0,
count = -1, count = -1,
reg = '', reg = '',
addr = 'none', addr = 'none',
@ -3443,46 +3425,6 @@ describe('API', function()
} }
}, meths.parse_cmd('MyCommand test it', {})) }, meths.parse_cmd('MyCommand test it', {}))
end) end)
it('sets correct default range', function()
command('command -range=% -addr=buffers MyCommand echo foo')
command('new')
eq({
cmd = 'MyCommand',
args = {},
bang = false,
line1 = 1,
line2 = 2,
range = 0,
count = -1,
reg = '',
addr = 'buf',
magic = {
file = false,
bar = false
},
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('MyCommand', {}))
end)
it('errors for invalid command', function() it('errors for invalid command', function()
eq('Error while parsing command line', pcall_err(meths.parse_cmd, 'Fubar', {})) eq('Error while parsing command line', pcall_err(meths.parse_cmd, 'Fubar', {}))
command('command! Fubar echo foo') command('command! Fubar echo foo')