aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJan Edmund Lazo <jan.lazo@mail.utoronto.ca>2021-01-01 03:32:43 -0500
committerJan Edmund Lazo <jan.lazo@mail.utoronto.ca>2021-01-01 04:58:05 -0500
commitd1608f7503512b37650522cf5c8a3dce7add5e3b (patch)
tree6335c75138828f46154879139b1c61eee82a190e /src
parent5cf94effeefead893de782ddf3f3914107de824f (diff)
downloadrneovim-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
Diffstat (limited to 'src')
-rw-r--r--src/nvim/ex_cmds.lua24
-rw-r--r--src/nvim/quickfix.c243
-rw-r--r--src/nvim/testdir/test_quickfix.vim71
3 files changed, 268 insertions, 70 deletions
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')