diff options
author | Jan Edmund Lazo <jan.lazo@mail.utoronto.ca> | 2021-01-01 03:32:43 -0500 |
---|---|---|
committer | Jan Edmund Lazo <jan.lazo@mail.utoronto.ca> | 2021-01-01 04:58:05 -0500 |
commit | d1608f7503512b37650522cf5c8a3dce7add5e3b (patch) | |
tree | 6335c75138828f46154879139b1c61eee82a190e | |
parent | 5cf94effeefead893de782ddf3f3914107de824f (diff) | |
download | rneovim-d1608f7503512b37650522cf5c8a3dce7add5e3b.tar.gz rneovim-d1608f7503512b37650522cf5c8a3dce7add5e3b.tar.bz2 rneovim-d1608f7503512b37650522cf5c8a3dce7add5e3b.zip |
vim-patch:8.1.1275: cannot navigate to errors before/after the cursor
Problem: Cannot navigate to errors before/after the cursor.
Solution: Add the :cbefore and :cafter commands. (Yegappan Lakshmanan,
closes vim/vim#4340)
https://github.com/vim/vim/commit/cf6a55c4b0cbf38b0c3fbed5ffd9a3fd0d2ede0e
-rw-r--r-- | runtime/doc/index.txt | 8 | ||||
-rw-r--r-- | runtime/doc/quickfix.txt | 36 | ||||
-rw-r--r-- | src/nvim/ex_cmds.lua | 24 | ||||
-rw-r--r-- | src/nvim/quickfix.c | 243 | ||||
-rw-r--r-- | src/nvim/testdir/test_quickfix.vim | 71 |
5 files changed, 306 insertions, 76 deletions
diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt index afcacad460..17de1d8533 100644 --- a/runtime/doc/index.txt +++ b/runtime/doc/index.txt @@ -1173,9 +1173,11 @@ tag command action ~ |:caddbuffer| :cad[dbuffer] add errors from buffer |:caddexpr| :cadde[xpr] add errors from expr |:caddfile| :caddf[ile] add error message to current quickfix list +|:cafter| :caf[ter] go to error after current cursor |:call| :cal[l] call a function |:catch| :cat[ch] part of a :try command -|:cbelow| :cbe[low] go to error below current line +|:cbefore| :cbef[ore] go to error before current cursor +|:cbelow| :cbel[ow] go to error below current line |:cbottom| :cbo[ttom] scroll to the bottom of the quickfix window |:cbuffer| :cb[uffer] parse error messages and jump to first error |:cc| :cc go to specific error @@ -1336,10 +1338,12 @@ tag command action ~ |:laddexpr| :lad[dexpr] add locations from expr |:laddbuffer| :laddb[uffer] add locations from buffer |:laddfile| :laddf[ile] add locations to current location list +|:lafter| :laf[ter] go to location after current cursor |:last| :la[st] go to the last file in the argument list |:language| :lan[guage] set the language (locale) |:later| :lat[er] go to newer change, redo -|:lbelow| :lbe[low] go to location below current line +|:lbefore| :lbef[ore] go to location before current cursor +|:lbelow| :lbel[ow] go to location below current line |:lbottom| :lbo[ttom] scroll to the bottom of the location window |:lbuffer| :lb[uffer] parse locations and jump to first location |:lcd| :lc[d] change directory locally diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt index 948b00c7c0..6ed79debf4 100644 --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -128,8 +128,8 @@ processing a quickfix or location list command, it will be aborted. :[count]lab[ove] Same as ":cabove", except the location list for the current window is used instead of the quickfix list. - *:cbe* *:cbelow* -:[count]cbe[low] Go to the [count] error below the current line in the + *:cbel* *:cbelow* +:[count]cbel[ow] Go to the [count] error below the current line in the current buffer. If [count] is omitted, then 1 is used. If there are no errors, then an error message is displayed. Assumes that the entries in a quickfix @@ -139,8 +139,36 @@ processing a quickfix or location list command, it will be aborted. exceeds the number of entries below the current line, then the last error in the file is selected. - *:lbe* *:lbelow* -:[count]lbe[low] Same as ":cbelow", except the location list for the + *:lbel* *:lbelow* +:[count]lbel[ow] Same as ":cbelow", except the location list for the + current window is used instead of the quickfix list. + + *:cbe* *:cbefore* +:[count]cbe[fore] Go to the [count] error before the current cursor + position in the current buffer. If [count] is + omitted, then 1 is used. If there are no errors, then + an error message is displayed. Assumes that the + entries in a quickfix list are sorted by their buffer, + line and column numbers. If [count] exceeds the + number of entries before the current position, then + the first error in the file is selected. + + *:lbe* *:lbefore* +:[count]lbe[fore] Same as ":cbefore", except the location list for the + current window is used instead of the quickfix list. + + *:caf* *:cafter* +:[count]caf[ter] Go to the [count] error after the current cursor + position in the current buffer. If [count] is + omitted, then 1 is used. If there are no errors, then + an error message is displayed. Assumes that the + entries in a quickfix list are sorted by their buffer, + line and column numbers. If [count] exceeds the + number of entries after the current position, then + the last error in the file is selected. + + *:laf* *:lafter* +:[count]laf[ter] Same as ":cafter", except the location list for the current window is used instead of the quickfix list. *:cnf* *:cnfile* diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index 60faae3268..872f32d874 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -343,6 +343,12 @@ module.cmds = { func='ex_cfile', }, { + command='cafter', + flags=bit.bor(RANGE, COUNT, TRLBAR), + addr_type='ADDR_UNSIGNED', + func='ex_cbelow', + }, + { command='call', flags=bit.bor(RANGE, NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN), addr_type='ADDR_LINES', @@ -361,6 +367,12 @@ module.cmds = { func='ex_cbuffer', }, { + command='cbefore', + flags=bit.bor(RANGE, COUNT, TRLBAR), + addr_type='ADDR_UNSIGNED', + func='ex_cbelow', + }, + { command='cbelow', flags=bit.bor(RANGE, COUNT, TRLBAR), addr_type='ADDR_UNSIGNED', @@ -1311,6 +1323,12 @@ module.cmds = { func='ex_cfile', }, { + command='lafter', + flags=bit.bor(RANGE, COUNT, TRLBAR), + addr_type='ADDR_UNSIGNED', + func='ex_cbelow', + }, + { command='later', flags=bit.bor(TRLBAR, EXTRA, NOSPC, CMDWIN), addr_type='ADDR_NONE', @@ -1323,6 +1341,12 @@ module.cmds = { func='ex_cbuffer', }, { + command='lbefore', + flags=bit.bor(RANGE, COUNT, TRLBAR), + addr_type='ADDR_UNSIGNED', + func='ex_cbelow', + }, + { command='lbelow', flags=bit.bor(RANGE, COUNT, TRLBAR), addr_type='ADDR_UNSIGNED', diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index f72a5e0020..eaa0117d93 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -4573,74 +4573,150 @@ static qfline_T * qf_find_last_entry_on_line(qfline_T *entry, int *errornr) return entry; } -/// Find the first quickfix entry below line 'lnum' in buffer 'bnr'. +// Returns true if the specified quickfix entry is +// after the given line (linewise is true) +// or after the line and column. +static bool qf_entry_after_pos(const qfline_T *qfp, const pos_T *pos, + bool linewise) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (linewise) { + return qfp->qf_lnum > pos->lnum; + } + return qfp->qf_lnum > pos->lnum + || (qfp->qf_lnum == pos->lnum && qfp->qf_col > pos->col); +} + +// Returns true if the specified quickfix entry is +// before the given line (linewise is true) +// or before the line and column. +static bool qf_entry_before_pos(const qfline_T *qfp, const pos_T *pos, + bool linewise) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (linewise) { + return qfp->qf_lnum < pos->lnum; + } + return qfp->qf_lnum < pos->lnum + || (qfp->qf_lnum == pos->lnum && qfp->qf_col < pos->col); +} + +// Returns true if the specified quickfix entry is +// on or after the given line (linewise is true) +// or on or after the line and column. +static bool qf_entry_on_or_after_pos(const qfline_T *qfp, const pos_T *pos, + bool linewise) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (linewise) { + return qfp->qf_lnum >= pos->lnum; + } + return qfp->qf_lnum > pos->lnum + || (qfp->qf_lnum == pos->lnum && qfp->qf_col >= pos->col); +} + +// Returns true if the specified quickfix entry is +// on or before the given line (linewise is true) +// or on or before the line and column. +static bool qf_entry_on_or_before_pos(const qfline_T *qfp, const pos_T *pos, + bool linewise) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (linewise) { + return qfp->qf_lnum <= pos->lnum; + } + return qfp->qf_lnum < pos->lnum + || (qfp->qf_lnum == pos->lnum && qfp->qf_col <= pos->col); +} + +/// Find the first quickfix entry after position 'pos' in buffer 'bnr'. +/// If 'linewise' is true, returns the entry after the specified line and treats +/// multiple entries on a single line as one. Otherwise returns the entry after +/// the specified line and column. /// 'qfp' points to the very first entry in the buffer and 'errornr' is the /// index of the very first entry in the quickfix list. -/// Returns NULL if an entry is not found after 'lnum'. -static qfline_T *qf_find_entry_on_next_line(int bnr, - linenr_T lnum, - qfline_T *qfp, - int *errornr) +/// Returns NULL if an entry is not found after 'pos'. +static qfline_T *qf_find_entry_after_pos( + int bnr, + const pos_T *pos, + bool linewise, + qfline_T *qfp, + int *errornr +) + FUNC_ATTR_NONNULL_ALL { - if (qfp->qf_lnum > lnum) { - // First entry is after line 'lnum' + if (qf_entry_after_pos(qfp, pos, linewise)) { + // First entry is after postion 'pos' return qfp; } - // Find the entry just before or at the line 'lnum' + // Find the entry just before or at the position 'pos' while (qfp->qf_next != NULL && qfp->qf_next->qf_fnum == bnr - && qfp->qf_next->qf_lnum <= lnum) { + && qf_entry_on_or_before_pos(qfp->qf_next, pos, linewise)) { qfp = qfp->qf_next; (*errornr)++; } if (qfp->qf_next == NULL || qfp->qf_next->qf_fnum != bnr) { - // No entries found after 'lnum' + // No entries found after position 'pos' return NULL; } - // Use the entry just after line 'lnum' + // Use the entry just after position 'pos' qfp = qfp->qf_next; (*errornr)++; return qfp; } -/// Find the first quickfix entry before line 'lnum' in buffer 'bnr'. +/// Find the first quickfix entry before position 'pos' in buffer 'bnr'. +/// If 'linewise' is true, returns the entry before the specified line and +/// treats multiple entries on a single line as one. Otherwise returns the entry +/// before the specified line and column. /// 'qfp' points to the very first entry in the buffer and 'errornr' is the /// index of the very first entry in the quickfix list. -/// Returns NULL if an entry is not found before 'lnum'. -static qfline_T *qf_find_entry_on_prev_line(int bnr, - linenr_T lnum, - qfline_T *qfp, - int *errornr) +/// Returns NULL if an entry is not found before 'pos'. +static qfline_T *qf_find_entry_before_pos( + int bnr, + const pos_T *pos, + bool linewise, + qfline_T *qfp, + int *errornr +) + FUNC_ATTR_NONNULL_ALL { - // Find the entry just before the line 'lnum' + // Find the entry just before the position 'pos' while (qfp->qf_next != NULL && qfp->qf_next->qf_fnum == bnr - && qfp->qf_next->qf_lnum < lnum) { + && qf_entry_before_pos(qfp->qf_next, pos, linewise)) { qfp = qfp->qf_next; (*errornr)++; } - if (qfp->qf_lnum >= lnum) { // entry is after 'lnum' + if (qf_entry_on_or_after_pos(qfp, pos, linewise)) { return NULL; } - // If multiple entries are on the same line, then use the first entry - qfp = qf_find_first_entry_on_line(qfp, errornr); + if (linewise) { + // If multiple entries are on the same line, then use the first entry + qfp = qf_find_first_entry_on_line(qfp, errornr); + } return qfp; } -/// Find a quickfix entry in 'qfl' closest to line 'lnum' in buffer 'bnr' in +/// Find a quickfix entry in 'qfl' closest to position 'pos' in buffer 'bnr' in /// the direction 'dir'. -static qfline_T *qf_find_closest_entry(qf_list_T *qfl, - int bnr, - linenr_T lnum, - int dir, - int *errornr) +static qfline_T *qf_find_closest_entry( + qf_list_T *qfl, + int bnr, + const pos_T *pos, + Direction dir, + bool linewise, + int *errornr +) + FUNC_ATTR_NONNULL_ALL { qfline_T *qfp; @@ -4653,33 +4729,38 @@ static qfline_T *qf_find_closest_entry(qf_list_T *qfl, } if (dir == FORWARD) { - qfp = qf_find_entry_on_next_line(bnr, lnum, qfp, errornr); + qfp = qf_find_entry_after_pos(bnr, pos, linewise, qfp, errornr); } else { - qfp = qf_find_entry_on_prev_line(bnr, lnum, qfp, errornr); + qfp = qf_find_entry_before_pos(bnr, pos, linewise, qfp, errornr); } return qfp; } -/// Get the nth quickfix entry below the specified entry treating multiple -/// entries on a single line as one. Searches forward in the list. -static void qf_get_nth_below_entry(qfline_T *entry, - int *errornr, - linenr_T n) +/// Get the nth quickfix entry below the specified entry. Searches forward in +/// the list. If linewise is true, then treat multiple entries on a single line +/// as one. +static void qf_get_nth_below_entry(qfline_T *entry, linenr_T n, + bool linewise, int *errornr) + FUNC_ATTR_NONNULL_ALL { while (n-- > 0 && !got_int) { // qfline_T *first_entry = entry; int first_errornr = *errornr; - // Treat all the entries on the same line in this file as one - entry = qf_find_last_entry_on_line(entry, errornr); + if (linewise) { + // Treat all the entries on the same line in this file as one + entry = qf_find_last_entry_on_line(entry, errornr); + } if (entry->qf_next == NULL || entry->qf_next->qf_fnum != entry->qf_fnum) { - // If multiple entries are on the same line, then use the first - // entry - // entry = first_entry; - *errornr = first_errornr; + if (linewise) { + // If multiple entries are on the same line, then use the first + // entry + // entry = first_entry; + *errornr = first_errornr; + } break; } @@ -4688,11 +4769,12 @@ static void qf_get_nth_below_entry(qfline_T *entry, } } -/// Get the nth quickfix entry above the specified entry treating multiple -/// entries on a single line as one. Searches backwards in the list. -static void qf_get_nth_above_entry(qfline_T *entry, - int *errornr, - linenr_T n) +/// Get the nth quickfix entry above the specified entry. Searches backwards in +/// the list. If linewise is TRUE, then treat multiple entries on a single line +/// as one. +static void qf_get_nth_above_entry(qfline_T *entry, linenr_T n, + bool linewise, int *errornr) + FUNC_ATTR_NONNULL_ALL { while (n-- > 0 && !got_int) { if (entry->qf_prev == NULL @@ -4703,25 +4785,30 @@ static void qf_get_nth_above_entry(qfline_T *entry, entry = entry->qf_prev; (*errornr)--; - // If multiple entries are on the same line, then use the first entry - entry = qf_find_first_entry_on_line(entry, errornr); + if (linewise) { + entry = qf_find_first_entry_on_line(entry, errornr); + } } } -/// Find the n'th quickfix entry adjacent to line 'lnum' in buffer 'bnr' in the -/// specified direction. -/// Returns the error number in the quickfix list or 0 if an entry is not found. -static int qf_find_nth_adj_entry(qf_list_T *qfl, - int bnr, - linenr_T lnum, - linenr_T n, - int dir) +/// Find the n'th quickfix entry adjacent to position 'pos' in buffer 'bnr' in +/// the specified direction. Returns the error number in the quickfix list or 0 +/// if an entry is not found. +static int qf_find_nth_adj_entry( + qf_list_T *qfl, + int bnr, + pos_T *pos, + linenr_T n, + Direction dir, + bool linewise +) + FUNC_ATTR_NONNULL_ALL { - qfline_T *adj_entry; int errornr; - // Find an entry closest to the specified line - adj_entry = qf_find_closest_entry(qfl, bnr, lnum, dir, &errornr); + // Find an entry closest to the specified position + qfline_T *const adj_entry = qf_find_closest_entry(qfl, bnr, pos, dir, + linewise, &errornr); if (adj_entry == NULL) { return 0; } @@ -4729,24 +4816,25 @@ static int qf_find_nth_adj_entry(qf_list_T *qfl, if (--n > 0) { // Go to the n'th entry in the current buffer if (dir == FORWARD) { - qf_get_nth_below_entry(adj_entry, &errornr, n); + qf_get_nth_below_entry(adj_entry, n, linewise, &errornr); } else { - qf_get_nth_above_entry(adj_entry, &errornr, n); + qf_get_nth_above_entry(adj_entry, n, linewise, &errornr); } } return errornr; } -/// Jump to a quickfix entry in the current file nearest to the current line. -/// ":cabove", ":cbelow", ":labove" and ":lbelow" commands +/// Jump to a quickfix entry in the current file nearest to the current line or +/// current line/col. +/// ":cabove", ":cbelow", ":labove", ":lbelow", ":cafter", ":cbefore", +/// ":lafter" and ":lbefore" commands void ex_cbelow(exarg_T *eap) { qf_info_T *qi; qf_list_T *qfl; int dir; int buf_has_flag; - int errornr = 0; if (eap->addr_count > 0 && eap->line2 <= 0) { EMSG(_(e_invrange)); @@ -4754,7 +4842,8 @@ void ex_cbelow(exarg_T *eap) } // Check whether the current buffer has any quickfix entries - if (eap->cmdidx == CMD_cabove || eap->cmdidx == CMD_cbelow) { + if (eap->cmdidx == CMD_cabove || eap->cmdidx == CMD_cbelow + || eap->cmdidx == CMD_cbefore || eap->cmdidx == CMD_cafter) { buf_has_flag = BUF_HAS_QF_ENTRY; } else { buf_has_flag = BUF_HAS_LL_ENTRY; @@ -4775,14 +4864,30 @@ void ex_cbelow(exarg_T *eap) return; } - if (eap->cmdidx == CMD_cbelow || eap->cmdidx == CMD_lbelow) { + if (eap->cmdidx == CMD_cbelow + || eap->cmdidx == CMD_lbelow + || eap->cmdidx == CMD_cafter + || eap->cmdidx == CMD_lafter) { + // Forward motion commands dir = FORWARD; } else { dir = BACKWARD; } - errornr = qf_find_nth_adj_entry(qfl, curbuf->b_fnum, curwin->w_cursor.lnum, - eap->addr_count > 0 ? eap->line2 : 0, dir); + pos_T pos = curwin->w_cursor; + // A quickfix entry column number is 1 based whereas cursor column + // number is 0 based. Adjust the column number. + pos.col++; + const int errornr = qf_find_nth_adj_entry( + qfl, + curbuf->b_fnum, + &pos, + eap->addr_count > 0 ? eap->line2 : 0, + dir, + eap->cmdidx == CMD_cbelow + || eap->cmdidx == CMD_lbelow + || eap->cmdidx == CMD_cabove + || eap->cmdidx == CMD_labove); if (errornr > 0) { qf_jump(qi, 0, errornr, false); diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 49d66d8c1f..f9d1abeaec 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -40,6 +40,8 @@ func s:setup_commands(cchar) command! -nargs=0 -count Xcc <count>cc command! -count=1 -nargs=0 Xbelow <mods><count>cbelow command! -count=1 -nargs=0 Xabove <mods><count>cabove + command! -count=1 -nargs=0 Xbefore <mods><count>cbefore + command! -count=1 -nargs=0 Xafter <mods><count>cafter let g:Xgetlist = function('getqflist') let g:Xsetlist = function('setqflist') call setqflist([], 'f') @@ -75,6 +77,8 @@ func s:setup_commands(cchar) command! -nargs=0 -count Xcc <count>ll command! -count=1 -nargs=0 Xbelow <mods><count>lbelow command! -count=1 -nargs=0 Xabove <mods><count>labove + command! -count=1 -nargs=0 Xbefore <mods><count>lbefore + command! -count=1 -nargs=0 Xafter <mods><count>lafter let g:Xgetlist = function('getloclist', [0]) let g:Xsetlist = function('setloclist', [0]) call setloclist(0, [], 'f') @@ -4201,17 +4205,22 @@ func Test_empty_qfbuf() endfunc " Test for the :cbelow, :cabove, :lbelow and :labove commands. +" And for the :cafter, :cbefore, :lafter and :lbefore commands. func Xtest_below(cchar) call s:setup_commands(a:cchar) " No quickfix/location list call assert_fails('Xbelow', 'E42:') call assert_fails('Xabove', 'E42:') + call assert_fails('Xbefore', 'E42:') + call assert_fails('Xafter', 'E42:') " Empty quickfix/location list call g:Xsetlist([]) call assert_fails('Xbelow', 'E42:') call assert_fails('Xabove', 'E42:') + call assert_fails('Xbefore', 'E42:') + call assert_fails('Xafter', 'E42:') call s:create_test_file('X1') call s:create_test_file('X2') @@ -4225,39 +4234,74 @@ func Xtest_below(cchar) call assert_fails('Xabove', 'E42:') call assert_fails('3Xbelow', 'E42:') call assert_fails('4Xabove', 'E42:') + call assert_fails('Xbefore', 'E42:') + call assert_fails('Xafter', 'E42:') + call assert_fails('3Xbefore', 'E42:') + call assert_fails('4Xafter', 'E42:') " Test the commands with various arguments - Xexpr ["X1:5:L5", "X2:5:L5", "X2:10:L10", "X2:15:L15", "X3:3:L3"] + Xexpr ["X1:5:3:L5", "X2:5:2:L5", "X2:10:3:L10", "X2:15:4:L15", "X3:3:5:L3"] edit +7 X2 Xabove call assert_equal(['X2', 5], [bufname(''), line('.')]) call assert_fails('Xabove', 'E553:') + normal 7G + Xbefore + call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')]) + call assert_fails('Xbefore', 'E553:') + normal 2j Xbelow call assert_equal(['X2', 10], [bufname(''), line('.')]) + normal 7G + Xafter + call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')]) + " Last error in this file Xbelow 99 call assert_equal(['X2', 15], [bufname(''), line('.')]) call assert_fails('Xbelow', 'E553:') + normal gg + Xafter 99 + call assert_equal(['X2', 15, 4], [bufname(''), line('.'), col('.')]) + call assert_fails('Xafter', 'E553:') + " First error in this file Xabove 99 call assert_equal(['X2', 5], [bufname(''), line('.')]) call assert_fails('Xabove', 'E553:') + normal G + Xbefore 99 + call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')]) + call assert_fails('Xbefore', 'E553:') + normal gg Xbelow 2 call assert_equal(['X2', 10], [bufname(''), line('.')]) + normal gg + Xafter 2 + call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')]) + normal G Xabove 2 call assert_equal(['X2', 10], [bufname(''), line('.')]) + normal G + Xbefore 2 + call assert_equal(['X2', 10, 3], [bufname(''), line('.'), col('.')]) + edit X4 call assert_fails('Xabove', 'E42:') call assert_fails('Xbelow', 'E42:') + call assert_fails('Xbefore', 'E42:') + call assert_fails('Xafter', 'E42:') if a:cchar == 'l' " If a buffer has location list entries from some other window but not " from the current window, then the commands should fail. edit X1 | split | call setloclist(0, [], 'f') call assert_fails('Xabove', 'E776:') call assert_fails('Xbelow', 'E776:') + call assert_fails('Xbefore', 'E776:') + call assert_fails('Xafter', 'E776:') close endif @@ -4268,27 +4312,52 @@ func Xtest_below(cchar) edit +1 X2 Xbelow 2 call assert_equal(['X2', 10, 1], [bufname(''), line('.'), col('.')]) + normal 1G + Xafter 2 + call assert_equal(['X2', 5, 2], [bufname(''), line('.'), col('.')]) + normal gg Xbelow 99 call assert_equal(['X2', 15, 1], [bufname(''), line('.'), col('.')]) + normal gg + Xafter 99 + call assert_equal(['X2', 15, 3], [bufname(''), line('.'), col('.')]) + normal G Xabove 2 call assert_equal(['X2', 10, 1], [bufname(''), line('.'), col('.')]) normal G + Xbefore 2 + call assert_equal(['X2', 15, 2], [bufname(''), line('.'), col('.')]) + + normal G Xabove 99 call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')]) + normal G + Xbefore 99 + call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')]) + normal 10G Xabove call assert_equal(['X2', 5, 1], [bufname(''), line('.'), col('.')]) + normal 10G$ + 2Xbefore + call assert_equal(['X2', 10, 2], [bufname(''), line('.'), col('.')]) + normal 10G Xbelow call assert_equal(['X2', 15, 1], [bufname(''), line('.'), col('.')]) + normal 9G + 5Xafter + call assert_equal(['X2', 15, 2], [bufname(''), line('.'), col('.')]) " Invalid range if a:cchar == 'c' call assert_fails('-2cbelow', 'E16:') + call assert_fails('-2cafter', 'E16:') else call assert_fails('-2lbelow', 'E16:') + call assert_fails('-2lafter', 'E16:') endif call delete('X1') |