aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ex_docmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/ex_docmd.c')
-rw-r--r--src/nvim/ex_docmd.c122
1 files changed, 73 insertions, 49 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 4aa2ef6ae0..e06dd7e59c 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -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;
}
/*