return ret;
}
+ static void
+assert_append_cmd_or_arg(garray_T *gap, typval_T *argvars, char_u *cmd)
+{
+ char_u *tofree;
+ char_u numbuf[NUMBUFLEN];
+
+ if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN)
+ {
+ ga_concat(gap, echo_string(&argvars[2], &tofree, numbuf, 0));
+ vim_free(tofree);
+ }
+ else
+ ga_concat(gap, cmd);
+}
+
int
assert_fails(typval_T *argvars)
{
char_u *cmd = tv_get_string_chk(&argvars[0]);
garray_T ga;
int ret = 0;
- char_u numbuf[NUMBUFLEN];
- char_u *tofree;
called_emsg = FALSE;
suppress_errthrow = TRUE;
{
prepare_assert_error(&ga);
ga_concat(&ga, (char_u *)"command did not fail: ");
- if (argvars[1].v_type != VAR_UNKNOWN
- && argvars[2].v_type != VAR_UNKNOWN)
- {
- ga_concat(&ga, echo_string(&argvars[2], &tofree, numbuf, 0));
- vim_free(tofree);
- }
- else
- ga_concat(&ga, cmd);
+ assert_append_cmd_or_arg(&ga, argvars, cmd);
assert_error(&ga);
ga_clear(&ga);
ret = 1;
prepare_assert_error(&ga);
fill_assert_error(&ga, &argvars[2], NULL, &argvars[1],
&vimvars[VV_ERRMSG].vv_tv, ASSERT_OTHER);
+ ga_concat(&ga, (char_u *)": ");
+ assert_append_cmd_or_arg(&ga, argvars, cmd);
assert_error(&ga);
ga_clear(&ga);
ret = 1;
ADDR_BUFFERS, // buffer number
ADDR_TABS, // tab page number
ADDR_TABS_RELATIVE, // Tab page that only relative
+ ADDR_QUICKFIX_VALID, // quickfix list valid entry number
ADDR_QUICKFIX, // quickfix list entry number
- ADDR_OTHER, // something else
+ ADDR_UNSIGNED, // positive count or zero, defaults to 1
+ ADDR_OTHER, // something else, use line number for '$', '%', etc.
ADDR_NONE // no range used
} cmd_addr_T;
#endif
* Not supported commands are included to avoid ambiguities.
*/
#ifdef EX
-# undef EX /* just in case */
+# undef EX // just in case
#endif
#ifdef DO_DECLARE_EXCMD
# define EX(a, b, c, d, e) {(char_u *)b, c, (long_u)(d), e}
ADDR_LINES),
EX(CMD_cNext, "cNext", ex_cnext,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_cNfile, "cNfile", ex_cnext,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_cabbrev, "cabbrev", ex_abbreviate,
EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN,
ADDR_NONE),
EXTRA|TRLBAR|CMDWIN,
ADDR_NONE),
EX(CMD_cabove, "cabove", ex_cbelow,
- RANGE|TRLBAR,
- ADDR_OTHER),
+ RANGE|COUNT|TRLBAR,
+ ADDR_UNSIGNED),
EX(CMD_caddbuffer, "caddbuffer", ex_cbuffer,
RANGE|WORD1|TRLBAR,
ADDR_OTHER),
BANG|RANGE|WORD1|TRLBAR,
ADDR_OTHER),
EX(CMD_cbelow, "cbelow", ex_cbelow,
- RANGE|TRLBAR,
- ADDR_OTHER),
+ RANGE|COUNT|TRLBAR,
+ ADDR_UNSIGNED),
EX(CMD_cbottom, "cbottom", ex_cbottom,
TRLBAR,
ADDR_NONE),
EX(CMD_cc, "cc", ex_cc,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_QUICKFIX),
EX(CMD_cclose, "cclose", ex_cclose,
TRLBAR,
ADDR_NONE),
ADDR_NONE),
EX(CMD_cdo, "cdo", ex_listdo,
BANG|NEEDARG|EXTRA|NOTRLCOM|RANGE|DFLALL,
- ADDR_QUICKFIX),
+ ADDR_QUICKFIX_VALID),
EX(CMD_center, "center", ex_align,
TRLBAR|RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY,
ADDR_LINES),
ADDR_NONE),
EX(CMD_cfdo, "cfdo", ex_listdo,
BANG|NEEDARG|EXTRA|NOTRLCOM|RANGE|DFLALL,
- ADDR_QUICKFIX),
+ ADDR_QUICKFIX_VALID),
EX(CMD_cfirst, "cfirst", ex_cc,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_cgetfile, "cgetfile", ex_cfile,
TRLBAR|FILE1,
ADDR_NONE),
ADDR_NONE),
EX(CMD_clast, "clast", ex_cc,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_close, "close", ex_close,
BANG|RANGE|COUNT|TRLBAR|CMDWIN,
ADDR_WINDOWS),
ADDR_OTHER),
EX(CMD_cnext, "cnext", ex_cnext,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_cnewer, "cnewer", qf_age,
RANGE|COUNT|TRLBAR,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_cnfile, "cnfile", ex_cnext,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_cnoremap, "cnoremap", ex_map,
EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN,
ADDR_NONE),
ADDR_LINES),
EX(CMD_colder, "colder", qf_age,
RANGE|COUNT|TRLBAR,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_colorscheme, "colorscheme", ex_colorscheme,
WORD1|TRLBAR|CMDWIN,
ADDR_NONE),
ADDR_OTHER),
EX(CMD_cprevious, "cprevious", ex_cnext,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_cpfile, "cpfile", ex_cnext,
RANGE|COUNT|TRLBAR|BANG,
ADDR_OTHER),
ADDR_NONE),
EX(CMD_crewind, "crewind", ex_cc,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_cscope, "cscope", ex_cscope,
EXTRA|NOTRLCOM|XFILE,
ADDR_NONE),
ADDR_LINES),
EX(CMD_lNext, "lNext", ex_cnext,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_lNfile, "lNfile", ex_cnext,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_last, "last", ex_last,
EXTRA|BANG|EDITCMD|ARGOPT|TRLBAR,
ADDR_NONE),
EX(CMD_labove, "labove", ex_cbelow,
- RANGE|TRLBAR,
- ADDR_OTHER),
+ RANGE|COUNT|TRLBAR,
+ ADDR_UNSIGNED),
EX(CMD_language, "language", ex_language,
EXTRA|TRLBAR|CMDWIN,
ADDR_NONE),
BANG|RANGE|WORD1|TRLBAR,
ADDR_OTHER),
EX(CMD_lbelow, "lbelow", ex_cbelow,
- RANGE|TRLBAR,
- ADDR_OTHER),
+ RANGE|COUNT|TRLBAR,
+ ADDR_UNSIGNED),
EX(CMD_lbottom, "lbottom", ex_cbottom,
TRLBAR,
ADDR_NONE),
ADDR_NONE),
EX(CMD_ldo, "ldo", ex_listdo,
BANG|NEEDARG|EXTRA|NOTRLCOM|RANGE|DFLALL,
- ADDR_QUICKFIX),
+ ADDR_QUICKFIX_VALID),
EX(CMD_left, "left", ex_align,
TRLBAR|RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY,
ADDR_LINES),
ADDR_NONE),
EX(CMD_lfdo, "lfdo", ex_listdo,
BANG|NEEDARG|EXTRA|NOTRLCOM|RANGE|DFLALL,
- ADDR_QUICKFIX),
+ ADDR_QUICKFIX_VALID),
EX(CMD_lfirst, "lfirst", ex_cc,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_lgetfile, "lgetfile", ex_cfile,
TRLBAR|FILE1,
ADDR_NONE),
ADDR_NONE),
EX(CMD_ll, "ll", ex_cc,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_QUICKFIX),
EX(CMD_llast, "llast", ex_cc,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_llist, "llist", qf_list,
BANG|EXTRA|TRLBAR|CMDWIN,
ADDR_NONE),
ADDR_NONE),
EX(CMD_lnext, "lnext", ex_cnext,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_lnewer, "lnewer", qf_age,
RANGE|COUNT|TRLBAR,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_lnfile, "lnfile", ex_cnext,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_loadview, "loadview", ex_loadview,
FILE1|TRLBAR,
ADDR_NONE),
ADDR_NONE),
EX(CMD_lolder, "lolder", qf_age,
RANGE|COUNT|TRLBAR,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_lopen, "lopen", ex_copen,
RANGE|COUNT|TRLBAR,
ADDR_OTHER),
EX(CMD_lprevious, "lprevious", ex_cnext,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_lpfile, "lpfile", ex_cnext,
RANGE|COUNT|TRLBAR|BANG,
ADDR_OTHER),
EX(CMD_lrewind, "lrewind", ex_cc,
RANGE|COUNT|TRLBAR|BANG,
- ADDR_OTHER),
+ ADDR_UNSIGNED),
EX(CMD_ltag, "ltag", ex_tag,
TRLBAR|BANG|WORD1,
ADDR_NONE),
* is equal to the lower.
*/
- /* ea.addr_type for user commands is set by find_ucmd */
+ // ea.addr_type for user commands is set by find_ucmd
if (!IS_USER_CMDIDX(ea.cmdidx))
{
if (ea.cmdidx != CMD_SIZE)
else
ea.addr_type = ADDR_LINES;
- /* :wincmd range depends on the argument. */
+ // :wincmd range depends on the argument.
if (ea.cmdidx == CMD_wincmd && p != NULL)
get_wincmd_addr_type(skipwhite(p), &ea);
+#ifdef FEAT_QUICKFIX
+ // :.cc in quickfix window uses line number
+ if ((ea.cmdidx == CMD_cc || ea.cmdidx == CMD_ll) && bt_quickfix(curbuf))
+ ea.addr_type = ADDR_OTHER;
+#endif
}
ea.cmd = cmd;
else
ea.line2 = ARGCOUNT;
break;
- case ADDR_QUICKFIX:
+ case ADDR_QUICKFIX_VALID:
#ifdef FEAT_QUICKFIX
- ea.line2 = qf_get_size(&ea);
+ ea.line2 = qf_get_valid_size(&ea);
if (ea.line2 == 0)
ea.line2 = 1;
#endif
break;
case ADDR_NONE:
- iemsg(_("INTERNAL: Cannot use DFLALL with ADDR_NONE"));
+ case ADDR_UNSIGNED:
+ case ADDR_QUICKFIX:
+ iemsg(_("INTERNAL: Cannot use DFLALL with ADDR_NONE, ADDR_UNSIGNED or ADDR_QUICKFIX"));
break;
}
}
eap->line2 = CURRENT_TAB_NR;
break;
case ADDR_TABS_RELATIVE:
+ case ADDR_UNSIGNED:
eap->line2 = 1;
break;
case ADDR_QUICKFIX:
+#ifdef FEAT_QUICKFIX
+ eap->line2 = qf_get_cur_idx(eap);
+#endif
+ break;
+ case ADDR_QUICKFIX_VALID:
#ifdef FEAT_QUICKFIX
eap->line2 = qf_get_cur_valid_idx(eap);
#endif
}
break;
case ADDR_TABS_RELATIVE:
+ case ADDR_UNSIGNED:
+ case ADDR_QUICKFIX:
*errormsg = _(e_invrange);
return FAIL;
case ADDR_ARGUMENTS:
eap->line2 = ARGCOUNT;
}
break;
- case ADDR_QUICKFIX:
+ case ADDR_QUICKFIX_VALID:
#ifdef FEAT_QUICKFIX
eap->line1 = 1;
- eap->line2 = qf_get_size(eap);
+ eap->line2 = qf_get_valid_size(eap);
if (eap->line2 == 0)
eap->line2 = 1;
#endif
/*
* 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.
+ * 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.
*/
break;
case ADDR_TABS_RELATIVE:
case ADDR_NONE:
+ case ADDR_UNSIGNED:
emsg(_(e_invrange));
cmd = NULL;
goto error;
break;
case ADDR_QUICKFIX:
+#ifdef FEAT_QUICKFIX
+ lnum = qf_get_cur_idx(eap);
+#endif
+ break;
+ case ADDR_QUICKFIX_VALID:
#ifdef FEAT_QUICKFIX
lnum = qf_get_cur_valid_idx(eap);
#endif
break;
case ADDR_TABS_RELATIVE:
case ADDR_NONE:
+ case ADDR_UNSIGNED:
emsg(_(e_invrange));
cmd = NULL;
goto error;
lnum = qf_get_size(eap);
if (lnum == 0)
lnum = 1;
+#endif
+ break;
+ case ADDR_QUICKFIX_VALID:
+#ifdef FEAT_QUICKFIX
+ lnum = qf_get_valid_size(eap);
+ if (lnum == 0)
+ lnum = 1;
#endif
break;
}
lnum = 1;
break;
case ADDR_QUICKFIX:
+#ifdef FEAT_QUICKFIX
+ lnum = qf_get_cur_idx(eap);
+#endif
+ break;
+ case ADDR_QUICKFIX_VALID:
#ifdef FEAT_QUICKFIX
lnum = qf_get_cur_valid_idx(eap);
#endif
break;
case ADDR_NONE:
+ case ADDR_UNSIGNED:
+ lnum = 0;
break;
}
}
invalid_range(exarg_T *eap)
{
buf_T *buf;
+
if ( eap->line1 < 0
|| eap->line2 < 0
|| eap->line1 > eap->line2)
break;
case ADDR_QUICKFIX:
#ifdef FEAT_QUICKFIX
- if (eap->line2 != 1 && eap->line2 > qf_get_size(eap))
+ // No error for value that is too big, will use the last entry.
+ if (eap->line2 <= 0)
return _(e_invrange);
#endif
break;
+ case ADDR_QUICKFIX_VALID:
+#ifdef FEAT_QUICKFIX
+ if ((eap->line2 != 1 && eap->line2 > qf_get_valid_size(eap))
+ || eap->line2 < 0)
+ return _(e_invrange);
+#endif
+ break;
+ case ADDR_UNSIGNED:
+ if (eap->line2 < 0)
+ return _(e_invrange);
+ break;
case ADDR_NONE:
// Will give an error elsewhere.
break;
command! -count -nargs=* -bang Xprev <mods><count>cprev<bang> <args>
command! -nargs=* -bang Xfirst <mods>cfirst<bang> <args>
command! -nargs=* -bang Xlast <mods>clast<bang> <args>
- command! -nargs=* -bang -range Xnfile <mods><count>cnfile<bang> <args>
+ command! -count -nargs=* -bang Xnfile <mods><count>cnfile<bang> <args>
command! -nargs=* -bang Xpfile <mods>cpfile<bang> <args>
command! -nargs=* Xexpr <mods>cexpr <args>
command! -range -nargs=* Xvimgrep <mods><count>vimgrep <args>
command! -count -nargs=* -bang Xprev <mods><count>lprev<bang> <args>
command! -nargs=* -bang Xfirst <mods>lfirst<bang> <args>
command! -nargs=* -bang Xlast <mods>llast<bang> <args>
- command! -nargs=* -bang -range Xnfile <mods><count>lnfile<bang> <args>
+ command! -count -nargs=* -bang Xnfile <mods><count>lnfile<bang> <args>
command! -nargs=* -bang Xpfile <mods>lpfile<bang> <args>
command! -nargs=* Xexpr <mods>lexpr <args>
command! -range -nargs=* Xvimgrep <mods><count>lvimgrep <args>
" Invalid range
if a:cchar == 'c'
- call assert_fails('-2cbelow', 'E553:')
- " TODO: should go to first error in the current line?
- 0cabove
+ call assert_fails('-2cbelow', 'E16:')
else
- call assert_fails('-2lbelow', 'E553:')
- " TODO: should go to first error in the current line?
- 0labove
+ call assert_fails('-2lbelow', 'E16:')
endif
call delete('X1')
call Xtest_below('c')
call Xtest_below('l')
endfunc
+
+func Test_quickfix_count()
+ let commands = [
+ \ 'cNext',
+ \ 'cNfile',
+ \ 'cabove',
+ \ 'cbelow',
+ \ 'cfirst',
+ \ 'clast',
+ \ 'cnewer',
+ \ 'cnext',
+ \ 'cnfile',
+ \ 'colder',
+ \ 'cprevious',
+ \ 'crewind',
+ \
+ \ 'lNext',
+ \ 'lNfile',
+ \ 'labove',
+ \ 'lbelow',
+ \ 'lfirst',
+ \ 'llast',
+ \ 'lnewer',
+ \ 'lnext',
+ \ 'lnfile',
+ \ 'lolder',
+ \ 'lprevious',
+ \ 'lrewind',
+ \ ]
+ for cmd in commands
+ call assert_fails('-1' .. cmd, 'E16:')
+ call assert_fails('.' .. cmd, 'E16:')
+ call assert_fails('%' .. cmd, 'E16:')
+ call assert_fails('$' .. cmd, 'E16:')
+ endfor
+endfunc