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.c458
1 files changed, 266 insertions, 192 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 003c78b241..ccf7dd0f68 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -1086,7 +1086,10 @@ static int compute_buffer_local_count(int addr_type, int lnum, int offset)
return buf->b_fnum;
}
-static int current_win_nr(win_T *win)
+// Return the window number of "win".
+// When "win" is NULL return the number of windows.
+static int current_win_nr(const win_T *win)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
int nr = 0;
@@ -1163,7 +1166,7 @@ static void get_wincmd_addr_type(char_u *arg, exarg_T *eap)
case 'd':
case Ctrl_D:
// window size or any count
- eap->addr_type = ADDR_LINES; // -V1037
+ eap->addr_type = ADDR_OTHER; // -V1037
break;
case Ctrl_HAT:
@@ -1199,7 +1202,7 @@ static void get_wincmd_addr_type(char_u *arg, exarg_T *eap)
case '=':
case CAR:
// no count
- eap->addr_type = 0;
+ eap->addr_type = ADDR_NONE;
break;
}
}
@@ -1380,6 +1383,10 @@ static char_u * do_one_cmd(char_u **cmdlinep,
if (ea.cmdidx == CMD_wincmd && p != NULL) {
get_wincmd_addr_type(skipwhite(p), &ea);
}
+ // :.cc in quickfix window uses line number
+ if ((ea.cmdidx == CMD_cc || ea.cmdidx == CMD_ll) && bt_quickfix(curbuf)) {
+ ea.addr_type = ADDR_OTHER;
+ }
}
ea.cmd = cmd;
@@ -1411,7 +1418,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
}
if (*ea.cmd == '|' || (exmode_active && ea.line1 != ea.line2)) {
ea.cmdidx = CMD_print;
- ea.argt = RANGE | COUNT | TRLBAR;
+ ea.argt = EX_RANGE | EX_COUNT | EX_TRLBAR;
if ((errormsg = invalid_range(&ea)) == NULL) {
correct_range(&ea);
ex_print(&ea);
@@ -1490,20 +1497,18 @@ static char_u * do_one_cmd(char_u **cmdlinep,
ea.forceit = false;
}
- /*
- * 6. Parse arguments.
- */
+ // 6. Parse arguments. Then check for errors.
if (!IS_USER_CMDIDX(ea.cmdidx)) {
ea.argt = cmdnames[(int)ea.cmdidx].cmd_argt;
}
if (!ea.skip) {
- if (sandbox != 0 && !(ea.argt & SBOXOK)) {
+ if (sandbox != 0 && !(ea.argt & EX_SBOXOK)) {
// Command not allowed in sandbox.
errormsg = (char_u *)_(e_sandbox);
goto doend;
}
- if (!MODIFIABLE(curbuf) && (ea.argt & MODIFY)
+ if (!MODIFIABLE(curbuf) && (ea.argt & EX_MODIFY)
// allow :put in terminals
&& (!curbuf->terminal || ea.cmdidx != CMD_put)) {
/* Command not allowed in non-'modifiable' buffer */
@@ -1511,7 +1516,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
goto doend;
}
- if (text_locked() && !(ea.argt & CMDWIN)
+ if (text_locked() && !(ea.argt & EX_CMDWIN)
&& !IS_USER_CMDIDX(ea.cmdidx)) {
// Command not allowed when editing the command line.
errormsg = (char_u *)_(get_text_locked_msg());
@@ -1522,7 +1527,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
// Do allow ":checktime" (it is postponed).
// Do allow ":edit" (check for an argument later).
// Do allow ":file" with no arguments (check for an argument later).
- if (!(ea.argt & CMDWIN)
+ if (!(ea.argt & EX_CMDWIN)
&& ea.cmdidx != CMD_checktime
&& ea.cmdidx != CMD_edit
&& ea.cmdidx != CMD_file
@@ -1531,14 +1536,14 @@ static char_u * do_one_cmd(char_u **cmdlinep,
goto doend;
}
- if (!ni && !(ea.argt & RANGE) && ea.addr_count > 0) {
- /* no range allowed */
+ if (!ni && !(ea.argt & EX_RANGE) && ea.addr_count > 0) {
+ // no range allowed
errormsg = (char_u *)_(e_norange);
goto doend;
}
}
- if (!ni && !(ea.argt & BANG) && ea.forceit) { /* no <!> allowed */
+ if (!ni && !(ea.argt & EX_BANG) && ea.forceit) { // no <!> allowed
errormsg = (char_u *)_(e_nobang);
goto doend;
}
@@ -1547,12 +1552,10 @@ static char_u * do_one_cmd(char_u **cmdlinep,
* Don't complain about the range if it is not used
* (could happen if line_count is accidentally set to 0).
*/
- if (!ea.skip && !ni) {
- /*
- * If the range is backwards, ask for confirmation and, if given, swap
- * ea.line1 & ea.line2 so it's forwards again.
- * When global command is busy, don't ask, will fail below.
- */
+ if (!ea.skip && !ni && (ea.argt & EX_RANGE)) {
+ // If the range is backwards, ask for confirmation and, if given, swap
+ // ea.line1 & ea.line2 so it's forwards again.
+ // When global command is busy, don't ask, will fail below.
if (!global_busy && ea.line1 > ea.line2) {
if (msg_silent == 0) {
if ((flags & DOCMD_VERBOSE) || exmode_active) {
@@ -1571,12 +1574,14 @@ static char_u * do_one_cmd(char_u **cmdlinep,
goto doend;
}
- if ((ea.argt & NOTADR) && ea.addr_count == 0) /* default is 1, not cursor */
+ if ((ea.addr_type == ADDR_OTHER) && ea.addr_count == 0) {
+ // default is 1, not cursor
ea.line2 = 1;
+ }
correct_range(&ea);
- if (((ea.argt & WHOLEFOLD) || ea.addr_count >= 2) && !global_busy
+ if (((ea.argt & EX_WHOLEFOLD) || ea.addr_count >= 2) && !global_busy
&& ea.addr_type == ADDR_LINES) {
// Put the first line at the start of a closed fold, put the last line
// at the end of a closed fold.
@@ -1610,12 +1615,14 @@ static char_u * do_one_cmd(char_u **cmdlinep,
* Check for "++opt=val" argument.
* Must be first, allow ":w ++enc=utf8 !cmd"
*/
- if (ea.argt & ARGOPT)
- while (ea.arg[0] == '+' && ea.arg[1] == '+')
+ if (ea.argt & EX_ARGOPT) {
+ while (ea.arg[0] == '+' && ea.arg[1] == '+') {
if (getargopt(&ea) == FAIL && !ni) {
errormsg = (char_u *)_(e_invarg);
goto doend;
}
+ }
+ }
if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) {
if (*ea.arg == '>') { /* append */
@@ -1654,14 +1661,15 @@ static char_u * do_one_cmd(char_u **cmdlinep,
* Check for "+command" argument, before checking for next command.
* Don't do this for ":read !cmd" and ":write !cmd".
*/
- if ((ea.argt & EDITCMD) && !ea.usefilter)
+ if ((ea.argt & EX_CMDARG) && !ea.usefilter) {
ea.do_ecmd_cmd = getargcmd(&ea.arg);
+ }
/*
* Check for '|' to separate commands and '"' to start comments.
* Don't do this for ":read !cmd" and ":write !cmd".
*/
- if ((ea.argt & TRLBAR) && !ea.usefilter) {
+ if ((ea.argt & EX_TRLBAR) && !ea.usefilter) {
separate_nextcmd(&ea);
} else if (ea.cmdidx == CMD_bang
|| ea.cmdidx == CMD_terminal
@@ -1688,12 +1696,13 @@ static char_u * do_one_cmd(char_u **cmdlinep,
}
}
- if ((ea.argt & DFLALL) && ea.addr_count == 0) {
+ if ((ea.argt & EX_DFLALL) && ea.addr_count == 0) {
buf_T *buf;
ea.line1 = 1;
switch (ea.addr_type) {
case ADDR_LINES:
+ case ADDR_OTHER:
ea.line2 = curbuf->b_ml.ml_line_count;
break;
case ADDR_LOADED_BUFFERS:
@@ -1728,24 +1737,27 @@ static char_u * do_one_cmd(char_u **cmdlinep,
ea.line2 = ARGCOUNT;
}
break;
- case ADDR_QUICKFIX:
- ea.line2 = qf_get_size(&ea);
+ case ADDR_QUICKFIX_VALID:
+ ea.line2 = qf_get_valid_size(&ea);
if (ea.line2 == 0) {
ea.line2 = 1;
}
break;
case ADDR_NONE:
- IEMSG(_("INTERNAL: Cannot use DFLALL with ADDR_NONE"));
+ case ADDR_UNSIGNED:
+ case ADDR_QUICKFIX:
+ IEMSG(_("INTERNAL: Cannot use EX_DFLALL "
+ "with ADDR_NONE, ADDR_UNSIGNED or ADDR_QUICKFIX"));
break;
}
}
- /* accept numbered register only when no count allowed (:put) */
- if ((ea.argt & REGSTR)
+ // 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 & COUNT) && ascii_isdigit(*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++;
@@ -1759,19 +1771,19 @@ static char_u * do_one_cmd(char_u **cmdlinep,
}
//
- // Check for a count. When accepting a BUFNAME, don't use "123foo" as a
+ // Check for a count. When accepting a EX_BUFNAME, don't use "123foo" as a
// count, it's a buffer name.
///
- if ((ea.argt & COUNT) && ascii_isdigit(*ea.arg)
- && (!(ea.argt & BUFNAME) || *(p = skipdigits(ea.arg)) == NUL
+ if ((ea.argt & EX_COUNT) && ascii_isdigit(*ea.arg)
+ && (!(ea.argt & EX_BUFNAME) || *(p = skipdigits(ea.arg)) == NUL
|| ascii_iswhite(*p))) {
n = getdigits_long(&ea.arg, false, -1);
ea.arg = skipwhite(ea.arg);
- if (n <= 0 && !ni && (ea.argt & ZEROR) == 0) {
+ if (n <= 0 && !ni && (ea.argt & EX_ZEROR) == 0) {
errormsg = (char_u *)_(e_zerocount);
goto doend;
}
- if (ea.argt & NOTADR) { /* e.g. :buffer 2, :sleep 3 */
+ if (ea.addr_type != ADDR_LINES) { // e.g. :buffer 2, :sleep 3
ea.line2 = n;
if (ea.addr_count == 0)
ea.addr_count = 1;
@@ -1780,8 +1792,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
ea.line2 += n - 1;
++ea.addr_count;
// Be vi compatible: no error message for out of range.
- if (ea.addr_type == ADDR_LINES
- && ea.line2 > curbuf->b_ml.ml_line_count) {
+ if (ea.line2 > curbuf->b_ml.ml_line_count) {
ea.line2 = curbuf->b_ml.ml_line_count;
}
}
@@ -1790,16 +1801,17 @@ static char_u * do_one_cmd(char_u **cmdlinep,
/*
* Check for flags: 'l', 'p' and '#'.
*/
- if (ea.argt & EXFLAGS)
+ if (ea.argt & EX_FLAGS) {
get_flags(&ea);
- /* no arguments allowed */
- if (!ni && !(ea.argt & EXTRA) && *ea.arg != NUL
- && *ea.arg != '"' && (*ea.arg != '|' || (ea.argt & TRLBAR) == 0)) {
+ }
+ if (!ni && !(ea.argt & EX_EXTRA) && *ea.arg != NUL
+ && *ea.arg != '"' && (*ea.arg != '|' || (ea.argt & EX_TRLBAR) == 0)) {
+ // no arguments allowed but there is something
errormsg = (char_u *)_(e_trailing);
goto doend;
}
- if (!ni && (ea.argt & NEEDARG) && *ea.arg == NUL) {
+ if (!ni && (ea.argt & EX_NEEDARG) && *ea.arg == NUL) {
errormsg = (char_u *)_(e_argreq);
goto doend;
}
@@ -1828,9 +1840,9 @@ static char_u * do_one_cmd(char_u **cmdlinep,
case CMD_function:
break;
- /* Commands that handle '|' themselves. Check: A command should
- * either have the TRLBAR flag, appear in this list or appear in
- * the list at ":help :bar". */
+ // Commands that handle '|' themselves. Check: A command should
+ // either have the EX_TRLBAR flag, appear in this list or appear in
+ // the list at ":help :bar".
case CMD_aboveleft:
case CMD_and:
case CMD_belowright:
@@ -1901,16 +1913,17 @@ static char_u * do_one_cmd(char_u **cmdlinep,
}
}
- if (ea.argt & XFILE) {
- if (expand_filename(&ea, cmdlinep, &errormsg) == FAIL)
+ if (ea.argt & EX_XFILE) {
+ if (expand_filename(&ea, cmdlinep, &errormsg) == FAIL) {
goto doend;
+ }
}
/*
* Accept buffer name. Cannot be used at the same time with a buffer
* number. Don't do this for a user command.
*/
- if ((ea.argt & BUFNAME) && *ea.arg != NUL && ea.addr_count == 0
+ if ((ea.argt & EX_BUFNAME) && *ea.arg != NUL && ea.addr_count == 0
&& !IS_USER_CMDIDX(ea.cmdidx)
) {
/*
@@ -1926,10 +1939,11 @@ static char_u * do_one_cmd(char_u **cmdlinep,
while (p > ea.arg && ascii_iswhite(p[-1]))
--p;
}
- ea.line2 = buflist_findpat(ea.arg, p, (ea.argt & BUFUNL) != 0,
- FALSE, FALSE);
- if (ea.line2 < 0) /* failed */
+ ea.line2 = buflist_findpat(ea.arg, p, (ea.argt & EX_BUFUNL) != 0,
+ false, false);
+ if (ea.line2 < 0) { // failed
goto doend;
+ }
ea.addr_count = 1;
ea.arg = skipwhite(p);
}
@@ -2325,6 +2339,7 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
eap->line1 = eap->line2;
switch (eap->addr_type) {
case ADDR_LINES:
+ case ADDR_OTHER:
// default is current line number
eap->line2 = curwin->w_cursor.lnum;
break;
@@ -2345,9 +2360,13 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
eap->line2 = CURRENT_TAB_NR;
break;
case ADDR_TABS_RELATIVE:
+ case ADDR_UNSIGNED:
eap->line2 = 1;
break;
case ADDR_QUICKFIX:
+ eap->line2 = qf_get_cur_idx(eap);
+ break;
+ case ADDR_QUICKFIX_VALID:
eap->line2 = qf_get_cur_valid_idx(eap);
break;
case ADDR_NONE:
@@ -2365,6 +2384,7 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
eap->cmd++;
switch (eap->addr_type) {
case ADDR_LINES:
+ case ADDR_OTHER:
eap->line1 = 1;
eap->line2 = curbuf->b_ml.ml_line_count;
break;
@@ -2400,7 +2420,8 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
}
break;
case ADDR_TABS_RELATIVE:
- case ADDR_OTHER:
+ case ADDR_UNSIGNED:
+ case ADDR_QUICKFIX:
*errormsg = (char_u *)_(e_invrange);
return FAIL;
case ADDR_ARGUMENTS:
@@ -2411,9 +2432,9 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent)
eap->line2 = ARGCOUNT;
}
break;
- case ADDR_QUICKFIX:
+ case ADDR_QUICKFIX_VALID:
eap->line1 = 1;
- eap->line2 = qf_get_size(eap);
+ eap->line2 = qf_get_valid_size(eap);
if (eap->line2 == 0) {
eap->line2 = 1;
}
@@ -2522,14 +2543,13 @@ static void append_command(char_u *cmd)
*d = NUL;
}
-/*
- * Find an Ex command by its name, either built-in or user.
- * Start of the name can be found at eap->cmd.
- * Returns pointer to char after the command name.
- * "full" is set to TRUE if the whole command name matched.
- * Returns NULL for an ambiguous user command.
- */
+// Find an Ex command by its name, either built-in or user.
+// Start of the name can be found at eap->cmd.
+// Sets eap->cmdidx and returns a pointer to char after the command name.
+// "full" is set to TRUE if the whole command name matched.
+// Returns NULL for an ambiguous user command.
static char_u *find_command(exarg_T *eap, int *full)
+ FUNC_ATTR_NONNULL_ARG(1)
{
int len;
char_u *p;
@@ -2980,7 +3000,7 @@ const char * set_one_cmd_context(
const char *arg = (const char *)skipwhite((const char_u *)p);
// Skip over ++argopt argument
- if ((ea.argt & ARGOPT) && *arg != NUL && strncmp(arg, "++", 2) == 0) {
+ if ((ea.argt & EX_ARGOPT) && *arg != NUL && strncmp(arg, "++", 2) == 0) {
p = arg;
while (*p && !ascii_isspace(*p)) {
MB_PTR_ADV(p);
@@ -3015,9 +3035,9 @@ const char * set_one_cmd_context(
arg = (const char *)skipwhite((const char_u *)arg);
}
- /* Does command allow "+command"? */
- if ((ea.argt & EDITCMD) && !usefilter && *arg == '+') {
- /* Check if we're in the +command */
+ // Does command allow "+command"?
+ if ((ea.argt & EX_CMDARG) && !usefilter && *arg == '+') {
+ // Check if we're in the +command
p = arg + 1;
arg = (const char *)skip_cmd_arg((char_u *)arg, false);
@@ -3033,17 +3053,19 @@ const char * set_one_cmd_context(
* Check for '|' to separate commands and '"' to start comments.
* Don't do this for ":read !cmd" and ":write !cmd".
*/
- if ((ea.argt & TRLBAR) && !usefilter) {
+ if ((ea.argt & EX_TRLBAR) && !usefilter) {
p = arg;
/* ":redir @" is not the start of a comment */
if (ea.cmdidx == CMD_redir && p[0] == '@' && p[1] == '"')
p += 2;
while (*p) {
if (*p == Ctrl_V) {
- if (p[1] != NUL)
- ++p;
- } else if ( (*p == '"' && !(ea.argt & NOTRLCOM))
- || *p == '|' || *p == '\n') {
+ if (p[1] != NUL) {
+ p++;
+ }
+ } else if ((*p == '"' && !(ea.argt & EX_NOTRLCOM))
+ || *p == '|'
+ || *p == '\n') {
if (*(p - 1) != '\\') {
if (*p == '|' || *p == '\n')
return p + 1;
@@ -3054,8 +3076,8 @@ const char * set_one_cmd_context(
}
}
- // no arguments allowed
- if (!(ea.argt & EXTRA) && *arg != NUL && strchr("|\"", *arg) == NULL) {
+ if (!(ea.argt & EX_EXTRA) && *arg != NUL && strchr("|\"", *arg) == NULL) {
+ // no arguments allowed but there is something
return NULL;
}
@@ -3075,7 +3097,7 @@ const char * set_one_cmd_context(
}
}
- if (ea.argt & XFILE) {
+ if (ea.argt & EX_XFILE) {
int c;
int in_quote = false;
const char *bow = NULL; // Beginning of word.
@@ -3496,8 +3518,8 @@ const char * set_one_cmd_context(
case CMD_USER:
case CMD_USER_BUF:
if (context != EXPAND_NOTHING) {
- // XFILE: file names are handled above.
- if (!(ea.argt & XFILE)) {
+ // EX_XFILE: file names are handled above.
+ if (!(ea.argt & EX_XFILE)) {
if (context == EXPAND_MENUS) {
return (const char *)set_context_in_menu_cmd(xp, (char_u *)cmd,
(char_u *)arg, forceit);
@@ -3707,6 +3729,15 @@ char_u *skip_range(
return (char_u *)cmd;
}
+static void addr_error(cmd_addr_T addr_type)
+{
+ if (addr_type == ADDR_NONE) {
+ EMSG(_(e_norange));
+ } else {
+ EMSG(_(e_invrange));
+ }
+}
+
// Get a single EX address
//
// Set ptr to the next character after the part that was interpreted.
@@ -3716,14 +3747,13 @@ char_u *skip_range(
// Return MAXLNUM when no Ex address was found.
static linenr_T get_address(exarg_T *eap,
char_u **ptr,
- cmd_addr_T addr_type_arg,
+ cmd_addr_T addr_type,
int skip, // only skip the address, don't use it
bool silent, // no errors or side effects
int to_other_file, // flag: may jump to other file
int address_count) // 1 for first, >1 after comma
FUNC_ATTR_NONNULL_ALL
{
- const int addr_type = addr_type_arg;
int c;
int i;
long n;
@@ -3741,6 +3771,7 @@ static linenr_T get_address(exarg_T *eap,
++cmd;
switch (addr_type) {
case ADDR_LINES:
+ case ADDR_OTHER:
lnum = curwin->w_cursor.lnum;
break;
case ADDR_WINDOWS:
@@ -3756,13 +3787,17 @@ static linenr_T get_address(exarg_T *eap,
case ADDR_TABS:
lnum = CURRENT_TAB_NR;
break;
- case ADDR_TABS_RELATIVE:
case ADDR_NONE:
- EMSG(_(e_invrange));
+ case ADDR_TABS_RELATIVE:
+ case ADDR_UNSIGNED:
+ addr_error(addr_type);
cmd = NULL;
goto error;
break;
case ADDR_QUICKFIX:
+ lnum = qf_get_cur_idx(eap);
+ break;
+ case ADDR_QUICKFIX_VALID:
lnum = qf_get_cur_valid_idx(eap);
break;
}
@@ -3772,6 +3807,7 @@ static linenr_T get_address(exarg_T *eap,
++cmd;
switch (addr_type) {
case ADDR_LINES:
+ case ADDR_OTHER:
lnum = curbuf->b_ml.ml_line_count;
break;
case ADDR_WINDOWS:
@@ -3796,9 +3832,10 @@ static linenr_T get_address(exarg_T *eap,
case ADDR_TABS:
lnum = LAST_TAB_NR;
break;
- case ADDR_TABS_RELATIVE:
case ADDR_NONE:
- EMSG(_(e_invrange));
+ case ADDR_TABS_RELATIVE:
+ case ADDR_UNSIGNED:
+ addr_error(addr_type);
cmd = NULL;
goto error;
break;
@@ -3808,6 +3845,12 @@ static linenr_T get_address(exarg_T *eap,
lnum = 1;
}
break;
+ case ADDR_QUICKFIX_VALID:
+ lnum = qf_get_valid_size(eap);
+ if (lnum == 0) {
+ lnum = 1;
+ }
+ break;
}
break;
@@ -3817,7 +3860,7 @@ static linenr_T get_address(exarg_T *eap,
goto error;
}
if (addr_type != ADDR_LINES) {
- EMSG(_(e_invaddr));
+ addr_error(addr_type);
cmd = NULL;
goto error;
}
@@ -3845,7 +3888,7 @@ static linenr_T get_address(exarg_T *eap,
case '?': /* '/' or '?' - search */
c = *cmd++;
if (addr_type != ADDR_LINES) {
- EMSG(_(e_invaddr));
+ addr_error(addr_type);
cmd = NULL;
goto error;
}
@@ -3892,7 +3935,7 @@ static linenr_T get_address(exarg_T *eap,
case '\\': /* "\?", "\/" or "\&", repeat search */
++cmd;
if (addr_type != ADDR_LINES) {
- EMSG(_(e_invaddr));
+ addr_error(addr_type);
cmd = NULL;
goto error;
}
@@ -3939,7 +3982,9 @@ static linenr_T get_address(exarg_T *eap,
if (lnum == MAXLNUM) {
switch (addr_type) {
case ADDR_LINES:
- lnum = curwin->w_cursor.lnum; /* "+1" is same as ".+1" */
+ case ADDR_OTHER:
+ // "+1" is same as ".+1"
+ lnum = curwin->w_cursor.lnum;
break;
case ADDR_WINDOWS:
lnum = CURRENT_WIN_NR;
@@ -3958,9 +4003,14 @@ static linenr_T get_address(exarg_T *eap,
lnum = 1;
break;
case ADDR_QUICKFIX:
+ lnum = qf_get_cur_idx(eap);
+ break;
+ case ADDR_QUICKFIX_VALID:
lnum = qf_get_cur_valid_idx(eap);
break;
case ADDR_NONE:
+ case ADDR_UNSIGNED:
+ lnum = 0;
break;
}
}
@@ -4051,12 +4101,11 @@ static char_u *invalid_range(exarg_T *eap)
return (char_u *)_(e_invrange);
}
- if (eap->argt & RANGE) {
- switch(eap->addr_type) {
+ if (eap->argt & EX_RANGE) {
+ switch (eap->addr_type) {
case ADDR_LINES:
- if (!(eap->argt & NOTADR)
- && eap->line2 > curbuf->b_ml.ml_line_count
- + (eap->cmdidx == CMD_diffget)) {
+ if (eap->line2 > (curbuf->b_ml.ml_line_count
+ + (eap->cmdidx == CMD_diffget))) {
return (char_u *)_(e_invrange);
}
break;
@@ -4105,11 +4154,24 @@ static char_u *invalid_range(exarg_T *eap)
}
break;
case ADDR_TABS_RELATIVE:
- // Do nothing
+ case ADDR_OTHER:
+ // Any range is OK.
break;
case ADDR_QUICKFIX:
assert(eap->line2 >= 0);
- if (eap->line2 != 1 && (size_t)eap->line2 > qf_get_size(eap)) {
+ // No error for value that is too big, will use the last entry.
+ if (eap->line2 <= 0) {
+ return (char_u *)_(e_invrange);
+ }
+ break;
+ case ADDR_QUICKFIX_VALID:
+ if ((eap->line2 != 1 && (size_t)eap->line2 > qf_get_valid_size(eap))
+ || eap->line2 < 0) {
+ return (char_u *)_(e_invrange);
+ }
+ break;
+ case ADDR_UNSIGNED:
+ if (eap->line2 < 0) {
return (char_u *)_(e_invrange);
}
break;
@@ -4126,11 +4188,13 @@ static char_u *invalid_range(exarg_T *eap)
*/
static void correct_range(exarg_T *eap)
{
- if (!(eap->argt & ZEROR)) { /* zero in range not allowed */
- if (eap->line1 == 0)
+ if (!(eap->argt & EX_ZEROR)) { // zero in range not allowed
+ if (eap->line1 == 0) {
eap->line1 = 1;
- if (eap->line2 == 0)
+ }
+ if (eap->line2 == 0) {
eap->line2 = 1;
+ }
}
}
@@ -4297,7 +4361,7 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp)
&& eap->cmdidx != CMD_lmake
&& eap->cmdidx != CMD_make
&& eap->cmdidx != CMD_terminal
- && !(eap->argt & NOSPC)
+ && !(eap->argt & EX_NOSPC)
) {
char_u *l;
#ifdef BACKSLASH_IN_FILENAME
@@ -4338,7 +4402,7 @@ int expand_filename(exarg_T *eap, char_u **cmdlinep, char_u **errormsgp)
* One file argument: Expand wildcards.
* Don't do this with ":r !command" or ":w !command".
*/
- if ((eap->argt & NOSPC) && !eap->usefilter) {
+ if ((eap->argt & EX_NOSPC) && !eap->usefilter) {
// Replace environment variables.
if (has_wildcards) {
/*
@@ -4451,38 +4515,39 @@ void separate_nextcmd(exarg_T *eap)
for (; *p; MB_PTR_ADV(p)) {
if (*p == Ctrl_V) {
- if (eap->argt & (USECTRLV | XFILE))
- ++p; /* skip CTRL-V and next char */
- else
- /* remove CTRL-V and skip next char */
+ if (eap->argt & (EX_CTRLV | EX_XFILE)) {
+ p++; // skip CTRL-V and next char
+ } else {
+ // remove CTRL-V and skip next char
STRMOVE(p, p + 1);
- if (*p == NUL) /* stop at NUL after CTRL-V */
+ }
+ if (*p == NUL) { // stop at NUL after CTRL-V
break;
- }
- /* Skip over `=expr` when wildcards are expanded. */
- else if (p[0] == '`' && p[1] == '=' && (eap->argt & XFILE)) {
+ }
+ } else if (p[0] == '`' && p[1] == '=' && (eap->argt & EX_XFILE)) {
+ // Skip over `=expr` when wildcards are expanded.
p += 2;
(void)skip_expr(&p);
if (*p == NUL) { // stop at NUL after CTRL-V
break;
}
- }
- /* Check for '"': start of comment or '|': next command */
- /* :@" does not start a comment!
- * :redir @" doesn't either. */
- else if ((*p == '"' && !(eap->argt & NOTRLCOM)
- && (eap->cmdidx != CMD_at || p != eap->arg)
- && (eap->cmdidx != CMD_redir
- || p != eap->arg + 1 || p[-1] != '@'))
- || *p == '|' || *p == '\n') {
- /*
- * We remove the '\' before the '|', unless USECTRLV is used
- * AND 'b' is present in 'cpoptions'.
- */
+ } else if (
+ // Check for '"': start of comment or '|': next command */
+ // :@" does not start a comment!
+ // :redir @" doesn't either.
+ (*p == '"'
+ && !(eap->argt & EX_NOTRLCOM)
+ && (eap->cmdidx != CMD_at || p != eap->arg)
+ && (eap->cmdidx != CMD_redir
+ || p != eap->arg + 1 || p[-1] != '@'))
+ || *p == '|'
+ || *p == '\n') {
+ // We remove the '\' before the '|', unless EX_CTRLV is used
+ // AND 'b' is present in 'cpoptions'.
if ((vim_strchr(p_cpo, CPO_BAR) == NULL
- || !(eap->argt & USECTRLV)) && *(p - 1) == '\\') {
- STRMOVE(p - 1, p); /* remove the '\' */
- --p;
+ || !(eap->argt & EX_CTRLV)) && *(p - 1) == '\\') {
+ STRMOVE(p - 1, p); // remove the '\'
+ p--;
} else {
eap->nextcmd = check_nextcmd(p);
*p = NUL;
@@ -4491,8 +4556,9 @@ void separate_nextcmd(exarg_T *eap)
}
}
- if (!(eap->argt & NOTRLCOM)) /* remove trailing spaces */
+ if (!(eap->argt & EX_NOTRLCOM)) { // remove trailing spaces
del_trailing_spaces(eap->arg);
+ }
}
/*
@@ -5181,11 +5247,11 @@ static void uc_list(char_u *name, size_t name_len)
// Special cases
int len = 4;
- if (a & BANG) {
+ if (a & EX_BANG) {
msg_putchar('!');
len--;
}
- if (a & REGSTR) {
+ if (a & EX_REGSTR) {
msg_putchar('"');
len--;
}
@@ -5193,7 +5259,7 @@ static void uc_list(char_u *name, size_t name_len)
msg_putchar('b');
len--;
}
- if (a & TRLBAR) {
+ if (a & EX_TRLBAR) {
msg_putchar('|');
len--;
}
@@ -5215,20 +5281,20 @@ static void uc_list(char_u *name, size_t name_len)
len = 0;
// Arguments
- switch (a & (EXTRA|NOSPC|NEEDARG)) {
+ switch (a & (EX_EXTRA | EX_NOSPC | EX_NEEDARG)) {
case 0:
IObuff[len++] = '0';
break;
- case (EXTRA):
+ case (EX_EXTRA):
IObuff[len++] = '*';
break;
- case (EXTRA|NOSPC):
+ case (EX_EXTRA | EX_NOSPC):
IObuff[len++] = '?';
break;
- case (EXTRA|NEEDARG):
+ case (EX_EXTRA | EX_NEEDARG):
IObuff[len++] = '+';
break;
- case (EXTRA|NOSPC|NEEDARG):
+ case (EX_EXTRA | EX_NOSPC | EX_NEEDARG):
IObuff[len++] = '1';
break;
}
@@ -5238,13 +5304,13 @@ static void uc_list(char_u *name, size_t name_len)
} while (len < 5 - over);
// Address / Range
- if (a & (RANGE|COUNT)) {
- if (a & COUNT) {
+ if (a & (EX_RANGE | EX_COUNT)) {
+ if (a & EX_COUNT) {
// -count=N
snprintf((char *)IObuff + len, IOSIZE, "%" PRId64 "c",
(int64_t)cmd->uc_def);
len += (int)STRLEN(IObuff + len);
- } else if (a & DFLALL) {
+ } else if (a & EX_DFLALL) {
IObuff[len++] = '%';
} else if (cmd->uc_def >= 0) {
// -range=N
@@ -5319,16 +5385,16 @@ static int uc_scan_attr(char_u *attr, size_t len, uint32_t *argt, long *def,
return FAIL;
}
- /* First, try the simple attributes (no arguments) */
- if (STRNICMP(attr, "bang", len) == 0)
- *argt |= BANG;
- else if (STRNICMP(attr, "buffer", len) == 0)
+ // First, try the simple attributes (no arguments)
+ if (STRNICMP(attr, "bang", len) == 0) {
+ *argt |= EX_BANG;
+ } else if (STRNICMP(attr, "buffer", len) == 0) {
*flags |= UC_BUFFER;
- else if (STRNICMP(attr, "register", len) == 0)
- *argt |= REGSTR;
- else if (STRNICMP(attr, "bar", len) == 0)
- *argt |= TRLBAR;
- else {
+ } else if (STRNICMP(attr, "register", len) == 0) {
+ *argt |= EX_REGSTR;
+ } else if (STRNICMP(attr, "bar", len) == 0) {
+ *argt |= EX_TRLBAR;
+ } else {
int i;
char_u *val = NULL;
size_t vallen = 0;
@@ -5346,28 +5412,29 @@ static int uc_scan_attr(char_u *attr, size_t len, uint32_t *argt, long *def,
if (STRNICMP(attr, "nargs", attrlen) == 0) {
if (vallen == 1) {
- if (*val == '0')
- /* Do nothing - this is the default */;
- else if (*val == '1')
- *argt |= (EXTRA | NOSPC | NEEDARG);
- else if (*val == '*')
- *argt |= EXTRA;
- else if (*val == '?')
- *argt |= (EXTRA | NOSPC);
- else if (*val == '+')
- *argt |= (EXTRA | NEEDARG);
- else
+ if (*val == '0') {
+ // Do nothing - this is the default;
+ } else if (*val == '1') {
+ *argt |= (EX_EXTRA | EX_NOSPC | EX_NEEDARG);
+ } else if (*val == '*') {
+ *argt |= EX_EXTRA;
+ } else if (*val == '?') {
+ *argt |= (EX_EXTRA | EX_NOSPC);
+ } else if (*val == '+') {
+ *argt |= (EX_EXTRA | EX_NEEDARG);
+ } else {
goto wrong_nargs;
+ }
} else {
wrong_nargs:
EMSG(_("E176: Invalid number of arguments"));
return FAIL;
}
} else if (STRNICMP(attr, "range", attrlen) == 0) {
- *argt |= RANGE;
- if (vallen == 1 && *val == '%')
- *argt |= DFLALL;
- else if (val != NULL) {
+ *argt |= EX_RANGE;
+ if (vallen == 1 && *val == '%') {
+ *argt |= EX_DFLALL;
+ } else if (val != NULL) {
p = val;
if (*def >= 0) {
two_count:
@@ -5376,7 +5443,7 @@ two_count:
}
*def = getdigits_long(&p, true, 0);
- *argt |= (ZEROR | NOTADR);
+ *argt |= EX_ZEROR;
if (p != val + vallen || vallen == 0) {
invalid_count:
@@ -5384,8 +5451,16 @@ invalid_count:
return FAIL;
}
}
+ // default for -range is using buffer lines
+ if (*addr_type_arg == ADDR_NONE) {
+ *addr_type_arg = ADDR_LINES;
+ }
} else if (STRNICMP(attr, "count", attrlen) == 0) {
- *argt |= (COUNT | ZEROR | RANGE | NOTADR);
+ *argt |= (EX_COUNT | EX_ZEROR | EX_RANGE);
+ // default for -count is using any number
+ if (*addr_type_arg == ADDR_NONE) {
+ *addr_type_arg = ADDR_OTHER;
+ }
if (val != NULL) {
p = val;
@@ -5411,16 +5486,16 @@ invalid_count:
return FAIL;
}
} else if (STRNICMP(attr, "addr", attrlen) == 0) {
- *argt |= RANGE;
+ *argt |= EX_RANGE;
if (val == NULL) {
EMSG(_("E179: argument required for -addr"));
return FAIL;
}
- if (parse_addr_type_arg(val, (int)vallen, argt, addr_type_arg) == FAIL) {
+ if (parse_addr_type_arg(val, (int)vallen, addr_type_arg) == FAIL) {
return FAIL;
}
if (*addr_type_arg != ADDR_LINES) {
- *argt |= (ZEROR | NOTADR);
+ *argt |= EX_ZEROR;
}
} else {
char_u ch = attr[len];
@@ -5447,7 +5522,7 @@ static void ex_command(exarg_T *eap)
int flags = 0;
int compl = EXPAND_NOTHING;
char_u *compl_arg = NULL;
- cmd_addr_T addr_type_arg = ADDR_LINES;
+ cmd_addr_T addr_type_arg = ADDR_NONE;
int has_attr = (eap->arg[0] == '-');
int name_len;
@@ -5724,8 +5799,9 @@ uc_check_code(
/* When specified there is a single argument don't split it.
* Works for ":Cmd %" when % is "a b c". */
- if ((eap->argt & NOSPC) && quote == 2)
+ if ((eap->argt & EX_NOSPC) && quote == 2) {
quote = 1;
+ }
switch (quote) {
case 0: /* No quoting, no splitting */
@@ -6105,8 +6181,7 @@ char_u *get_user_cmd_complete(expand_T *xp, int idx)
/*
* Parse address type argument
*/
-int parse_addr_type_arg(char_u *value, int vallen, uint32_t *argt,
- cmd_addr_T *addr_type_arg)
+int parse_addr_type_arg(char_u *value, int vallen, cmd_addr_T *addr_type_arg)
FUNC_ATTR_NONNULL_ALL
{
int i, a, b;
@@ -6129,9 +6204,6 @@ int parse_addr_type_arg(char_u *value, int vallen, uint32_t *argt,
return FAIL;
}
- if (*addr_type_arg != ADDR_LINES)
- *argt |= NOTADR;
-
return OK;
}
@@ -6169,9 +6241,9 @@ int parse_compl_arg(const char_u *value, int vallen, int *complp,
&& STRNCMP(value, command_complete[i], valend) == 0) {
*complp = i;
if (i == EXPAND_BUFFERS) {
- *argt |= BUFNAME;
+ *argt |= EX_BUFNAME;
} else if (i == EXPAND_DIRECTORIES || i == EXPAND_FILES) {
- *argt |= XFILE;
+ *argt |= EX_XFILE;
}
break;
}
@@ -7423,11 +7495,12 @@ static void ex_read(exarg_T *eap)
int empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
linenr_T lnum;
- if (eap->usefilter) /* :r!cmd */
- do_bang(1, eap, FALSE, FALSE, TRUE);
- else {
- if (u_save(eap->line2, (linenr_T)(eap->line2 + 1)) == FAIL)
+ if (eap->usefilter) { // :r!cmd
+ do_bang(1, eap, false, false, true);
+ } else {
+ if (u_save(eap->line2, (linenr_T)(eap->line2 + 1)) == FAIL) {
return;
+ }
if (*eap->arg == NUL) {
if (check_fname() == FAIL) /* check for no file name */
@@ -7799,7 +7872,7 @@ static void ex_copymove(exarg_T *eap)
* move or copy lines from 'eap->line1'-'eap->line2' to below line 'n'
*/
if (n == MAXLNUM || n < 0 || n > curbuf->b_ml.ml_line_count) {
- EMSG(_(e_invaddr));
+ EMSG(_(e_invrange));
return;
}
@@ -7897,7 +7970,7 @@ static void ex_at(exarg_T *eap)
*/
static void ex_bang(exarg_T *eap)
{
- do_bang(eap->addr_count, eap, eap->forceit, TRUE, TRUE);
+ do_bang(eap->addr_count, eap, eap->forceit, true, true);
}
/*
@@ -8647,6 +8720,7 @@ ssize_t find_cmdline_var(const char_u *src, size_t *usedlen)
* '#' to curwin->w_altfile
* '<cword>' to word under the cursor
* '<cWORD>' to WORD under the cursor
+ * '<cexpr>' to C-expression under the cursor
* '<cfile>' to path name under the cursor
* '<sfile>' to sourced file name
* '<slnum>' to sourced file line number
@@ -9475,16 +9549,16 @@ Dictionary commands_array(buf_T *buf)
PUT(d, "name", STRING_OBJ(cstr_to_string((char *)cmd->uc_name)));
PUT(d, "definition", STRING_OBJ(cstr_to_string((char *)cmd->uc_rep)));
PUT(d, "script_id", INTEGER_OBJ(cmd->uc_script_ctx.sc_sid));
- PUT(d, "bang", BOOLEAN_OBJ(!!(cmd->uc_argt & BANG)));
- PUT(d, "bar", BOOLEAN_OBJ(!!(cmd->uc_argt & TRLBAR)));
- PUT(d, "register", BOOLEAN_OBJ(!!(cmd->uc_argt & REGSTR)));
+ PUT(d, "bang", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_BANG)));
+ PUT(d, "bar", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_TRLBAR)));
+ PUT(d, "register", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_REGSTR)));
- switch (cmd->uc_argt & (EXTRA|NOSPC|NEEDARG)) {
- case 0: arg[0] = '0'; break;
- case(EXTRA): arg[0] = '*'; break;
- case(EXTRA|NOSPC): arg[0] = '?'; break;
- case(EXTRA|NEEDARG): arg[0] = '+'; break;
- case(EXTRA|NOSPC|NEEDARG): arg[0] = '1'; break;
+ switch (cmd->uc_argt & (EX_EXTRA | EX_NOSPC | EX_NEEDARG)) {
+ case 0: arg[0] = '0'; break;
+ case(EX_EXTRA): arg[0] = '*'; break;
+ case(EX_EXTRA | EX_NOSPC): arg[0] = '?'; break;
+ case(EX_EXTRA | EX_NEEDARG): arg[0] = '+'; break;
+ case(EX_EXTRA | EX_NOSPC | EX_NEEDARG): arg[0] = '1'; break;
}
PUT(d, "nargs", STRING_OBJ(cstr_to_string(arg)));
@@ -9495,7 +9569,7 @@ Dictionary commands_array(buf_T *buf)
? NIL : STRING_OBJ(cstr_to_string((char *)cmd->uc_compl_arg)));
Object obj = NIL;
- if (cmd->uc_argt & COUNT) {
+ if (cmd->uc_argt & EX_COUNT) {
if (cmd->uc_def >= 0) {
snprintf(str, sizeof(str), "%" PRId64, (int64_t)cmd->uc_def);
obj = STRING_OBJ(cstr_to_string(str)); // -count=N
@@ -9506,8 +9580,8 @@ Dictionary commands_array(buf_T *buf)
PUT(d, "count", obj);
obj = NIL;
- if (cmd->uc_argt & RANGE) {
- if (cmd->uc_argt & DFLALL) {
+ if (cmd->uc_argt & EX_RANGE) {
+ if (cmd->uc_argt & EX_DFLALL) {
obj = STRING_OBJ(cstr_to_string("%")); // -range=%
} else if (cmd->uc_def >= 0) {
snprintf(str, sizeof(str), "%" PRId64, (int64_t)cmd->uc_def);