mirror of
https://github.com/neovim/neovim.git
synced 2025-09-22 11:18:19 +00:00
feat(nvim_parse_cmd): add range, count, reg #18383
Adds range, count and reg to the return values of nvim_parse_cmd. Also makes line1 and line2 be -1 if the command does not take a range. Also moves nvim_parse_cmd to vimscript.c because it fits better there.
This commit is contained in:
@@ -1240,7 +1240,7 @@ static void set_cmd_addr_type(exarg_T *eap, char_u *p)
|
||||
}
|
||||
}
|
||||
|
||||
/// Set default command range based on the addr type of the command
|
||||
/// Set default command range for -range=% based on the addr type of the command
|
||||
static void set_cmd_default_range(exarg_T *eap)
|
||||
{
|
||||
buf_T *buf;
|
||||
@@ -1298,6 +1298,66 @@ static void set_cmd_default_range(exarg_T *eap)
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_register(exarg_T *eap)
|
||||
{
|
||||
// Accept numbered register only when no count allowed (:put)
|
||||
if ((eap->argt & EX_REGSTR)
|
||||
&& *eap->arg != NUL
|
||||
// Do not allow register = for user commands
|
||||
&& (!IS_USER_CMDIDX(eap->cmdidx) || *eap->arg != '=')
|
||||
&& !((eap->argt & EX_COUNT) && ascii_isdigit(*eap->arg))) {
|
||||
if (valid_yank_reg(*eap->arg, (eap->cmdidx != CMD_put
|
||||
&& !IS_USER_CMDIDX(eap->cmdidx)))) {
|
||||
eap->regname = *eap->arg++;
|
||||
// for '=' register: accept the rest of the line as an expression
|
||||
if (eap->arg[-1] == '=' && eap->arg[0] != NUL) {
|
||||
if (!eap->skip) {
|
||||
set_expr_line(vim_strsave(eap->arg));
|
||||
}
|
||||
eap->arg += STRLEN(eap->arg);
|
||||
}
|
||||
eap->arg = skipwhite(eap->arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int parse_count(exarg_T *eap, char **errormsg)
|
||||
{
|
||||
// Check for a count. When accepting a EX_BUFNAME, don't use "123foo" as a
|
||||
// count, it's a buffer name.
|
||||
char *p;
|
||||
long n;
|
||||
|
||||
if ((eap->argt & EX_COUNT) && ascii_isdigit(*eap->arg)
|
||||
&& (!(eap->argt & EX_BUFNAME) || *(p = (char *)skipdigits(eap->arg + 1)) == NUL
|
||||
|| ascii_iswhite(*p))) {
|
||||
n = getdigits_long(&eap->arg, false, -1);
|
||||
eap->arg = skipwhite(eap->arg);
|
||||
if (n <= 0 && (eap->argt & EX_ZEROR) == 0) {
|
||||
if (errormsg != NULL) {
|
||||
*errormsg = _(e_zerocount);
|
||||
}
|
||||
return FAIL;
|
||||
}
|
||||
if (eap->addr_type != ADDR_LINES) { // e.g. :buffer 2, :sleep 3
|
||||
eap->line2 = n;
|
||||
if (eap->addr_count == 0) {
|
||||
eap->addr_count = 1;
|
||||
}
|
||||
} else {
|
||||
eap->line1 = eap->line2;
|
||||
eap->line2 += n - 1;
|
||||
eap->addr_count++;
|
||||
// Be vi compatible: no error message for out of range.
|
||||
if (eap->line2 > curbuf->b_ml.ml_line_count) {
|
||||
eap->line2 = curbuf->b_ml.ml_line_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/// Parse command line and return information about the first command.
|
||||
///
|
||||
/// @return Success or failure
|
||||
@@ -1345,6 +1405,8 @@ bool parse_cmdline(char_u *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo)
|
||||
if (eap->verbose_save != -1) {
|
||||
cmdinfo->verbose = p_verbose;
|
||||
p_verbose = eap->verbose_save;
|
||||
} else {
|
||||
cmdinfo->verbose = -1;
|
||||
}
|
||||
cmdinfo->cmdmod = cmdmod;
|
||||
cmdmod = save_cmdmod;
|
||||
@@ -1422,6 +1484,12 @@ bool parse_cmdline(char_u *cmdline, exarg_T *eap, CmdParseInfo *cmdinfo)
|
||||
set_cmd_default_range(eap);
|
||||
}
|
||||
|
||||
// Parse register and count
|
||||
parse_register(eap);
|
||||
if (parse_count(eap, NULL) == FAIL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove leading whitespace and colon from next command
|
||||
if (eap->nextcmd) {
|
||||
eap->nextcmd = (char_u *)skip_colon_white((char *)eap->nextcmd, true);
|
||||
@@ -1460,7 +1528,6 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
|
||||
{
|
||||
char *p;
|
||||
linenr_T lnum;
|
||||
long n;
|
||||
char *errormsg = NULL; // error message
|
||||
char *after_modifier = NULL;
|
||||
exarg_T ea;
|
||||
@@ -1899,53 +1966,10 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
|
||||
set_cmd_default_range(&ea);
|
||||
}
|
||||
|
||||
// accept numbered register only when no count allowed (:put)
|
||||
if ((ea.argt & EX_REGSTR)
|
||||
&& *ea.arg != NUL
|
||||
// Do not allow register = for user commands
|
||||
&& (!IS_USER_CMDIDX(ea.cmdidx) || *ea.arg != '=')
|
||||
&& !((ea.argt & EX_COUNT) && ascii_isdigit(*ea.arg))) {
|
||||
if (valid_yank_reg(*ea.arg, (ea.cmdidx != CMD_put
|
||||
&& !IS_USER_CMDIDX(ea.cmdidx)))) {
|
||||
ea.regname = *ea.arg++;
|
||||
// for '=' register: accept the rest of the line as an expression
|
||||
if (ea.arg[-1] == '=' && ea.arg[0] != NUL) {
|
||||
if (!ea.skip) {
|
||||
set_expr_line(vim_strsave(ea.arg));
|
||||
}
|
||||
ea.arg += STRLEN(ea.arg);
|
||||
}
|
||||
ea.arg = skipwhite(ea.arg);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check for a count. When accepting a EX_BUFNAME, don't use "123foo" as a
|
||||
// count, it's a buffer name.
|
||||
///
|
||||
if ((ea.argt & EX_COUNT) && ascii_isdigit(*ea.arg)
|
||||
&& (!(ea.argt & EX_BUFNAME) || *(p = (char *)skipdigits(ea.arg + 1)) == NUL
|
||||
|| ascii_iswhite(*p))) {
|
||||
n = getdigits_long(&ea.arg, false, -1);
|
||||
ea.arg = skipwhite(ea.arg);
|
||||
if (n <= 0 && !ni && (ea.argt & EX_ZEROR) == 0) {
|
||||
errormsg = _(e_zerocount);
|
||||
goto doend;
|
||||
}
|
||||
if (ea.addr_type != ADDR_LINES) { // e.g. :buffer 2, :sleep 3
|
||||
ea.line2 = n;
|
||||
if (ea.addr_count == 0) {
|
||||
ea.addr_count = 1;
|
||||
}
|
||||
} else {
|
||||
ea.line1 = ea.line2;
|
||||
ea.line2 += n - 1;
|
||||
++ea.addr_count;
|
||||
// Be vi compatible: no error message for out of range.
|
||||
if (ea.line2 > curbuf->b_ml.ml_line_count) {
|
||||
ea.line2 = curbuf->b_ml.ml_line_count;
|
||||
}
|
||||
}
|
||||
// Parse register and count
|
||||
parse_register(&ea);
|
||||
if (parse_count(&ea, &errormsg) == FAIL) {
|
||||
goto doend;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user