mirror of
https://github.com/neovim/neovim.git
synced 2025-12-01 06:23:01 +00:00
feat(nvim_cmd): allow using first argument as count
Allows `nvim_cmd` to use the first argument as count for applicable commands. Also adds support for non-String arguments to `nvim_cmd`.
This commit is contained in:
@@ -1339,6 +1339,20 @@ static int parse_count(exarg_T *eap, char **errormsg, bool validate)
|
||||
|| ascii_iswhite(*p))) {
|
||||
long n = getdigits_long(&eap->arg, false, -1);
|
||||
eap->arg = skipwhite(eap->arg);
|
||||
|
||||
if (eap->args != NULL) {
|
||||
assert(eap->argc > 0 && eap->arg >= eap->args[0]);
|
||||
// If eap->arg is still pointing to the first argument, just make eap->args[0] point to the
|
||||
// same location. This is needed for usecases like vim.cmd.sleep('10m'). If eap->arg is
|
||||
// pointing outside the first argument, shift arguments by 1.
|
||||
if (eap->arg < eap->args[0] + eap->arglens[0]) {
|
||||
eap->arglens[0] -= (size_t)(eap->arg - eap->args[0]);
|
||||
eap->args[0] = eap->arg;
|
||||
} else {
|
||||
shift_cmd_args(eap);
|
||||
}
|
||||
}
|
||||
|
||||
if (n <= 0 && (eap->argt & EX_ZEROR) == 0) {
|
||||
if (errormsg != NULL) {
|
||||
*errormsg = _(e_zerocount);
|
||||
@@ -1512,6 +1526,30 @@ end:
|
||||
return retval;
|
||||
}
|
||||
|
||||
// Shift Ex-command arguments to the right.
|
||||
static void shift_cmd_args(exarg_T *eap)
|
||||
{
|
||||
assert(eap->args != NULL && eap->argc > 0);
|
||||
|
||||
char **oldargs = eap->args;
|
||||
size_t *oldarglens = eap->arglens;
|
||||
|
||||
eap->argc--;
|
||||
eap->args = eap->argc > 0 ? xcalloc(eap->argc, sizeof(char *)) : NULL;
|
||||
eap->arglens = eap->argc > 0 ? xcalloc(eap->argc, sizeof(size_t)) : NULL;
|
||||
|
||||
for (size_t i = 0; i < eap->argc; i++) {
|
||||
eap->args[i] = oldargs[i + 1];
|
||||
eap->arglens[i] = oldarglens[i + 1];
|
||||
}
|
||||
|
||||
// If there are no arguments, make eap->arg point to the end of string.
|
||||
eap->arg = (eap->argc > 0 ? eap->args[0] : (oldargs[0] + oldarglens[0]));
|
||||
|
||||
xfree(oldargs);
|
||||
xfree(oldarglens);
|
||||
}
|
||||
|
||||
static int execute_cmd0(int *retv, exarg_T *eap, char **errormsg, bool preview)
|
||||
{
|
||||
// If filename expansion is enabled, expand filenames
|
||||
@@ -1551,15 +1589,7 @@ static int execute_cmd0(int *retv, exarg_T *eap, char **errormsg, bool preview)
|
||||
eap->args[0] + eap->arglens[0],
|
||||
(eap->argt & EX_BUFUNL) != 0, false, false);
|
||||
eap->addr_count = 1;
|
||||
// Shift each argument by 1
|
||||
for (size_t i = 0; i < eap->argc - 1; i++) {
|
||||
eap->args[i] = eap->args[i + 1];
|
||||
}
|
||||
// Make the last argument point to the NUL terminator at the end of string
|
||||
eap->args[eap->argc - 1] = eap->args[eap->argc - 1] + eap->arglens[eap->argc - 1];
|
||||
eap->argc -= 1;
|
||||
|
||||
eap->arg = eap->args[0];
|
||||
shift_cmd_args(eap);
|
||||
}
|
||||
if (eap->line2 < 0) { // failed
|
||||
return FAIL;
|
||||
@@ -1658,6 +1688,11 @@ int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview)
|
||||
(void)hasFolding(eap->line2, NULL, &eap->line2);
|
||||
}
|
||||
|
||||
// Use first argument as count when possible
|
||||
if (parse_count(eap, &errormsg, true) == FAIL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Execute the command
|
||||
execute_cmd0(&retv, eap, &errormsg, preview);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user