Merge pull request #18438 from famiu/feat/api/nvim_parse_cmd

fix(api): make `nvim_parse_cmd` propagate errors
This commit is contained in:
bfredl 2022-05-06 10:30:48 +02:00 committed by GitHub
commit e3edcd06e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 13 deletions

View File

@ -802,10 +802,15 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err)
// Parse command line
exarg_T ea;
CmdParseInfo cmdinfo;
char_u *cmdline = (char_u *)string_to_cstr(str);
char *cmdline = string_to_cstr(str);
char *errormsg = NULL;
if (!parse_cmdline(cmdline, &ea, &cmdinfo)) {
api_set_error(err, kErrorTypeException, "Error while parsing command line");
if (!parse_cmdline(cmdline, &ea, &cmdinfo, &errormsg)) {
if (errormsg != NULL) {
api_set_error(err, kErrorTypeException, "Error while parsing command line: %s", errormsg);
} else {
api_set_error(err, kErrorTypeException, "Error while parsing command line");
}
goto end;
}

View File

@ -1359,12 +1359,17 @@ static int parse_count(exarg_T *eap, char **errormsg)
/// Parse command line and return information about the first command.
///
/// @param cmdline Command line string
/// @param[out] eap Ex command arguments
/// @param[out] cmdinfo Command parse information
/// @param[out] errormsg Error message, if any
///
/// @return Success or failure
bool parse_cmdline(char_u *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo)
bool parse_cmdline(char *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo, char **errormsg)
{
char *errormsg = NULL;
char *cmd;
char *p;
char *after_modifier = NULL;
cmdmod_T save_cmdmod = cmdmod;
// Initialize cmdinfo
@ -1374,15 +1379,17 @@ bool parse_cmdline(char_u *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo)
memset(eap, 0, sizeof(*eap));
eap->line1 = 1;
eap->line2 = 1;
eap->cmd = (char *)cmdline;
eap->cmdlinep = (char **)&cmdline;
eap->cmd = cmdline;
eap->cmdlinep = &cmdline;
eap->getline = NULL;
eap->cookie = NULL;
// Parse command modifiers
if (parse_command_modifiers(eap, &errormsg, false) == FAIL) {
if (parse_command_modifiers(eap, errormsg, false) == FAIL) {
return false;
}
after_modifier = eap->cmd;
// Revert the side-effects of `parse_command_modifiers`
if (eap->save_msg_silent != -1) {
cmdinfo->silent = !!msg_silent;
@ -1422,7 +1429,7 @@ bool parse_cmdline(char_u *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo)
// Set command attribute type and parse command range
set_cmd_addr_type(eap, (char_u *)p);
eap->cmd = cmd;
if (parse_cmd_address(eap, &errormsg, false) == FAIL) {
if (parse_cmd_address(eap, errormsg, false) == FAIL) {
return false;
}
@ -1434,6 +1441,11 @@ bool parse_cmdline(char_u *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo)
}
// Fail if command is invalid
if (eap->cmdidx == CMD_SIZE) {
STRCPY(IObuff, _("E492: Not an editor command"));
// If the modifier was parsed OK the error must be in the following command
char *cmdname = after_modifier ? after_modifier : cmdline;
append_command(cmdname);
*errormsg = (char *)IObuff;
return false;
}
@ -1472,10 +1484,12 @@ bool parse_cmdline(char_u *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo)
}
// Fail if command doesn't support bang but is used with a bang
if (!(eap->argt & EX_BANG) && eap->forceit) {
*errormsg = _(e_nobang);
return false;
}
// Fail if command doesn't support a range but it is given a range
if (!(eap->argt & EX_RANGE) && eap->addr_count > 0) {
*errormsg = _(e_norange);
return false;
}
// Set default range for command if required
@ -1485,7 +1499,7 @@ bool parse_cmdline(char_u *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo)
// Parse register and count
parse_register(eap);
if (parse_count(eap, NULL) == FAIL) {
if (parse_count(eap, errormsg) == FAIL) {
return false;
}

View File

@ -3426,10 +3426,15 @@ describe('API', function()
}, meths.parse_cmd('MyCommand test it', {}))
end)
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, '', {}))
eq('Error while parsing command line', pcall_err(meths.parse_cmd, '" foo', {}))
eq('Error while parsing command line: E492: Not an editor command: Fubar',
pcall_err(meths.parse_cmd, 'Fubar', {}))
command('command! Fubar echo foo')
eq('Error while parsing command line', pcall_err(meths.parse_cmd, 'Fubar!', {}))
eq('Error while parsing command line', pcall_err(meths.parse_cmd, '4,6Fubar', {}))
eq('Error while parsing command line: E477: No ! allowed',
pcall_err(meths.parse_cmd, 'Fubar!', {}))
eq('Error while parsing command line: E481: No range allowed',
pcall_err(meths.parse_cmd, '4,6Fubar', {}))
end)
end)
end)