diff options
author | erw7 <erw7.github@gmail.com> | 2020-10-13 10:02:36 +0900 |
---|---|---|
committer | Jan Edmund Lazo <jan.lazo@mail.utoronto.ca> | 2021-01-01 04:57:50 -0500 |
commit | 35dc6d6e876c6726089338ed0a61191315deb537 (patch) | |
tree | c329cf4100c9120b984cc276a0f537f2bb0668ee | |
parent | a66d63f36e76ba882ccf9c7c5f5d94691449b81e (diff) | |
download | rneovim-35dc6d6e876c6726089338ed0a61191315deb537.tar.gz rneovim-35dc6d6e876c6726089338ed0a61191315deb537.tar.bz2 rneovim-35dc6d6e876c6726089338ed0a61191315deb537.zip |
vim-patch:8.1.1261: no error for quickfix commands with negative range
Problem: No error for quickfix commands with negative range.
Solution: Add ADDR_UNSIGNED and use it for quickfix commands. Make
assert_fails() show the command if the error doesn't match.
https://github.com/vim/vim/commit/25190db225d63e185e77e043e694ef455b3cf304
N/A patches for version.c:
vim-patch:8.2.0113: "make cmdidxs" fails
Problem: "make cmdidxs" fails.
Solution: Allow address for ":cquit". Add --not-a-term to avoid a delay.
https://github.com/vim/vim/commit/9b24dfcb9f676e7f7a09a9062f0d05b2104a87eb
-rw-r--r-- | runtime/doc/quickfix.txt | 7 | ||||
-rw-r--r-- | src/nvim/eval.c | 24 | ||||
-rw-r--r-- | src/nvim/ex_cmds.lua | 70 | ||||
-rw-r--r-- | src/nvim/ex_cmds2.c | 2 | ||||
-rw-r--r-- | src/nvim/ex_cmds_defs.h | 4 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 66 | ||||
-rw-r--r-- | src/nvim/quickfix.c | 13 | ||||
-rw-r--r-- | src/nvim/testdir/test_quickfix.vim | 48 |
8 files changed, 165 insertions, 69 deletions
diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt index d6ff3ea9ea..948b00c7c0 100644 --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -74,7 +74,7 @@ processing a quickfix or location list command, it will be aborted. *:cc* :cc[!] [nr] Display error [nr]. If [nr] is omitted, the same - error is displayed again. Without [!] this doesn't +:[nr]cc[!] error is displayed again. Without [!] this doesn't work when jumping to another buffer, the current buffer has been changed, there is the only window for the buffer and both 'hidden' and 'autowrite' are off. @@ -83,10 +83,13 @@ processing a quickfix or location list command, it will be aborted. there is another window for this buffer. The 'switchbuf' settings are respected when jumping to a buffer. + When used in the quickfix window the line number can + be used, including "." for the current line and "$" + for the last line. *:ll* :ll[!] [nr] Same as ":cc", except the location list for the - current window is used instead of the quickfix list. +:[nr]ll[!] current window is used instead of the quickfix list. *:cn* *:cne* *:cnext* *E553* :[count]cn[ext][!] Display the [count] next error in the list that diff --git a/src/nvim/eval.c b/src/nvim/eval.c index f60504de5e..8a1556320c 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -5948,6 +5948,19 @@ int assert_exception(typval_T *argvars) return 0; } +static void assert_append_cmd_or_arg(garray_T *gap, typval_T *argvars, + const char *cmd) + FUNC_ATTR_NONNULL_ALL +{ + if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) { + char *const tofree = encode_tv2echo(&argvars[2], NULL); + ga_concat(gap, (char_u *)tofree); + xfree(tofree); + } else { + ga_concat(gap, (char_u *)cmd); + } +} + int assert_fails(typval_T *argvars) FUNC_ATTR_NONNULL_ALL { @@ -5966,14 +5979,7 @@ int assert_fails(typval_T *argvars) if (!called_emsg) { prepare_assert_error(&ga); ga_concat(&ga, (const char_u *)"command did not fail: "); - if (argvars[1].v_type != VAR_UNKNOWN - && argvars[2].v_type != VAR_UNKNOWN) { - char *const tofree = encode_tv2echo(&argvars[2], NULL); - ga_concat(&ga, (char_u *)tofree); - xfree(tofree); - } else { - ga_concat(&ga, (const char_u *)cmd); - } + assert_append_cmd_or_arg(&ga, argvars, cmd); assert_error(&ga); ga_clear(&ga); ret = 1; @@ -5986,6 +5992,8 @@ int assert_fails(typval_T *argvars) 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; diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index 1c2a66a0b9..60faae3268 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -297,13 +297,13 @@ module.cmds = { { command='cNext', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='ex_cnext', }, { command='cNfile', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='ex_cnext', }, { @@ -320,8 +320,8 @@ module.cmds = { }, { command='cabove', - flags=bit.bor(RANGE, TRLBAR), - addr_type='ADDR_OTHER', + flags=bit.bor(RANGE, COUNT, TRLBAR), + addr_type='ADDR_UNSIGNED', func='ex_cbelow', }, { @@ -362,8 +362,8 @@ module.cmds = { }, { command='cbelow', - flags=bit.bor(RANGE, TRLBAR), - addr_type='ADDR_OTHER', + flags=bit.bor(RANGE, COUNT, TRLBAR), + addr_type='ADDR_UNSIGNED', func='ex_cbelow', }, { @@ -375,7 +375,7 @@ module.cmds = { { command='cc', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_QUICKFIX', func='ex_cc', }, { @@ -393,7 +393,7 @@ module.cmds = { { command='cdo', flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL), - addr_type='ADDR_QUICKFIX', + addr_type='ADDR_QUICKFIX_VALID', func='ex_listdo', }, { @@ -419,13 +419,13 @@ module.cmds = { { command='cfdo', flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL), - addr_type='ADDR_QUICKFIX', + addr_type='ADDR_QUICKFIX_VALID', func='ex_listdo', }, { command='cfirst', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='ex_cc', }, { @@ -491,7 +491,7 @@ module.cmds = { { command='clast', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='ex_cc', }, { @@ -527,19 +527,19 @@ module.cmds = { { command='cnext', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='ex_cnext', }, { command='cnewer', flags=bit.bor(RANGE, COUNT, TRLBAR), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='qf_age', }, { command='cnfile', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='ex_cnext', }, { @@ -569,7 +569,7 @@ module.cmds = { { command='colder', flags=bit.bor(RANGE, COUNT, TRLBAR), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='qf_age', }, { @@ -623,7 +623,7 @@ module.cmds = { { command='cprevious', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='ex_cnext', }, { @@ -635,13 +635,13 @@ module.cmds = { { command='cquit', flags=bit.bor(RANGE, COUNT, ZEROR, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='ex_cquit', }, { command='crewind', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='ex_cc', }, { @@ -1265,13 +1265,13 @@ module.cmds = { { command='lNext', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='ex_cnext', }, { command='lNfile', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='ex_cnext', }, { @@ -1282,8 +1282,8 @@ module.cmds = { }, { command='labove', - flags=bit.bor(RANGE, TRLBAR), - addr_type='ADDR_OTHER', + flags=bit.bor(RANGE, COUNT, TRLBAR), + addr_type='ADDR_UNSIGNED', func='ex_cbelow', }, { @@ -1324,8 +1324,8 @@ module.cmds = { }, { command='lbelow', - flags=bit.bor(RANGE, TRLBAR), - addr_type='ADDR_OTHER', + flags=bit.bor(RANGE, COUNT, TRLBAR), + addr_type='ADDR_UNSIGNED', func='ex_cbelow', }, { @@ -1361,7 +1361,7 @@ module.cmds = { { command='ldo', flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL), - addr_type='ADDR_QUICKFIX', + addr_type='ADDR_QUICKFIX_VALID', func='ex_listdo', }, { @@ -1399,13 +1399,13 @@ module.cmds = { { command='lfdo', flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL), - addr_type='ADDR_QUICKFIX', + addr_type='ADDR_QUICKFIX_VALID', func='ex_listdo', }, { command='lfirst', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='ex_cc', }, { @@ -1453,13 +1453,13 @@ module.cmds = { { command='ll', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_QUICKFIX', func='ex_cc', }, { command='llast', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='ex_cc', }, { @@ -1495,19 +1495,19 @@ module.cmds = { { command='lnext', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='ex_cnext', }, { command='lnewer', flags=bit.bor(RANGE, COUNT, TRLBAR), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='qf_age', }, { command='lnfile', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='ex_cnext', }, { @@ -1537,7 +1537,7 @@ module.cmds = { { command='lolder', flags=bit.bor(RANGE, COUNT, TRLBAR), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='qf_age', }, { @@ -1549,7 +1549,7 @@ module.cmds = { { command='lprevious', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='ex_cnext', }, { @@ -1561,7 +1561,7 @@ module.cmds = { { command='lrewind', flags=bit.bor(RANGE, COUNT, TRLBAR, BANG), - addr_type='ADDR_OTHER', + addr_type='ADDR_UNSIGNED', func='ex_cc', }, { diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index bde584d27e..c400975108 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -2113,7 +2113,7 @@ void ex_listdo(exarg_T *eap) } } else if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) { - qf_size = qf_get_size(eap); + qf_size = qf_get_valid_size(eap); assert(eap->line1 >= 0); if (qf_size == 0 || (size_t)eap->line1 > qf_size) { buf = NULL; diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h index 07a09e3a2e..4a16b914fd 100644 --- a/src/nvim/ex_cmds_defs.h +++ b/src/nvim/ex_cmds_defs.h @@ -74,8 +74,10 @@ typedef enum { 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; diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index d4764aa504..c5d64d2e25 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -1383,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; @@ -1730,14 +1734,17 @@ 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 DFLALL " + "with ADDR_NONE, ADDR_UNSIGNED or ADDR_QUICKFIX")); break; } } @@ -2347,9 +2354,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: @@ -2403,6 +2414,8 @@ int parse_cmd_address(exarg_T *eap, char_u **errormsg, bool silent) } break; case ADDR_TABS_RELATIVE: + case ADDR_UNSIGNED: + case ADDR_QUICKFIX: *errormsg = (char_u *)_(e_invrange); return FAIL; case ADDR_ARGUMENTS: @@ -2413,9 +2426,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; } @@ -2524,14 +2537,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; @@ -3761,11 +3773,15 @@ static linenr_T get_address(exarg_T *eap, break; case ADDR_TABS_RELATIVE: case ADDR_NONE: + case ADDR_UNSIGNED: EMSG(_(e_invrange)); 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; } @@ -3802,6 +3818,7 @@ static linenr_T get_address(exarg_T *eap, break; case ADDR_TABS_RELATIVE: case ADDR_NONE: + case ADDR_UNSIGNED: EMSG(_(e_invrange)); cmd = NULL; goto error; @@ -3812,6 +3829,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; @@ -3964,9 +3987,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; } } @@ -4115,7 +4143,19 @@ static char_u *invalid_range(exarg_T *eap) 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; diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 2780553bdc..f72a5e0020 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -4269,11 +4269,22 @@ static char_u *get_mef_name(void) return name; } -/// Returns the number of valid entries in the current quickfix/location list. +/// Returns the number of entries in the current quickfix/location list. size_t qf_get_size(exarg_T *eap) FUNC_ATTR_NONNULL_ALL { qf_info_T *qi; + + if ((qi = qf_cmd_get_stack(eap, false)) == NULL) { + return 0; + } + return (size_t)qf_get_curlist(qi)->qf_count; +} + +/// Returns the number of valid entries in the current quickfix/location list. +size_t qf_get_valid_size(exarg_T *eap) +{ + qf_info_T *qi; qf_list_T *qfl; if ((qi = qf_cmd_get_stack(eap, false)) == NULL) { diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 563dbd90d9..49d66d8c1f 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -29,7 +29,7 @@ func s:setup_commands(cchar) 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> @@ -64,7 +64,7 @@ func s:setup_commands(cchar) 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> @@ -4286,13 +4286,9 @@ func Xtest_below(cchar) " 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') @@ -4306,6 +4302,42 @@ func Test_cbelow() 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 + " Test for aborting quickfix commands using QuickFixCmdPre func Xtest_qfcmd_abort(cchar) call s:setup_commands(a:cchar) |