Patch 8.1.1275
Problem: Cannot navigate to errors before/after the cursor.
Solution: Add the :cbefore and :cafter commands. (Yegappan Lakshmanan,
closes #4340)
Files: runtime/doc/index.txt, runtime/doc/quickfix.txt, src/ex_cmdidxs.h,
src/ex_cmds.h, src/quickfix.c, src/testdir/test_quickfix.vim
*** ../vim-8.1.1274/runtime/doc/index.txt 2019-05-03 21:56:31.363540578
+0200
--- runtime/doc/index.txt 2019-05-05 14:56:42.134251046 +0200
***************
*** 1144,1152 ****
|:caddbuffer| :cad[dbuffer] add errors from buffer
|:caddexpr| :cadde[xpr] add errors from expr
|:caddfile| :caddf[ile] add error message to current quickfix list
|:call| :cal[l] call a function
|:catch| :cat[ch] part of a :try command
! |:cbelow| :cbe[low] got 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
--- 1196,1206 ----
|: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
! |: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
***************
*** 1308,1317 ****
|:laddexpr| :lad[dexpr] add locations from expr
|:laddbuffer| :laddb[uffer] add locations from buffer
|:laddfile| :laddf[ile] add locations to current location list
|: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
|: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
--- 1362,1373 ----
|: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
! |: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
--- 1707,1712 ----
*** ../vim-8.1.1274/runtime/doc/quickfix.txt 2019-05-04 15:05:24.927269310
+0200
--- runtime/doc/quickfix.txt 2019-05-05 14:56:42.134251046 +0200
***************
*** 152,159 ****
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
current window is used instead of the quickfix list.
*:cnf* *:cnfile*
--- 152,187 ----
exceeds the number of entries below the current line,
then the last error in the file is selected.
! *: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.
!
! *:lbef* *:lbefore*
! :[count]lbef[ore] 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*
*** ../vim-8.1.1274/src/ex_cmdidxs.h 2019-05-03 21:56:31.363540578 +0200
--- src/ex_cmdidxs.h 2019-05-05 14:56:42.134251046 +0200
***************
*** 8,36 ****
/* a */ 0,
/* b */ 19,
/* c */ 42,
! /* d */ 105,
! /* e */ 127,
! /* f */ 147,
! /* g */ 163,
! /* h */ 169,
! /* i */ 178,
! /* j */ 196,
! /* k */ 198,
! /* l */ 203,
! /* m */ 263,
! /* n */ 281,
! /* o */ 301,
! /* p */ 313,
! /* q */ 352,
! /* r */ 355,
! /* s */ 375,
! /* t */ 443,
! /* u */ 488,
! /* v */ 499,
! /* w */ 517,
! /* x */ 531,
! /* y */ 540,
! /* z */ 541
};
/*
--- 8,36 ----
/* a */ 0,
/* b */ 19,
/* c */ 42,
! /* d */ 107,
! /* e */ 129,
! /* f */ 149,
! /* g */ 165,
! /* h */ 171,
! /* i */ 180,
! /* j */ 198,
! /* k */ 200,
! /* l */ 205,
! /* m */ 267,
! /* n */ 285,
! /* o */ 305,
! /* p */ 317,
! /* q */ 356,
! /* r */ 359,
! /* s */ 379,
! /* t */ 447,
! /* u */ 492,
! /* v */ 503,
! /* w */ 521,
! /* x */ 535,
! /* y */ 544,
! /* z */ 545
};
/*
***************
*** 43,49 ****
{ /* a b c d e f g h i j k l m n o p
q r s t u v w x y z */
/* a */ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 0, 0,
0, 7, 15, 0, 16, 0, 0, 0, 0, 0 },
/* b */ { 2, 0, 0, 4, 5, 7, 0, 0, 0, 0, 0, 8, 9, 10, 11, 12,
0, 13, 0, 0, 0, 0, 22, 0, 0, 0 },
! /* c */ { 3, 11, 14, 16, 18, 20, 23, 0, 0, 0, 0, 31, 35, 38, 44, 53,
55, 56, 57, 0, 59, 0, 62, 0, 0, 0 },
/* d */ { 0, 0, 0, 0, 0, 0, 0, 0, 6, 15, 0, 16, 0, 0, 17, 0,
0, 19, 20, 0, 0, 0, 0, 0, 0, 0 },
/* e */ { 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 10, 0, 0,
0, 0, 0, 0, 0, 0, 0, 16, 0, 0 },
/* f */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
0, 0, 0, 0, 15, 0, 0, 0, 0, 0 },
--- 43,49 ----
{ /* a b c d e f g h i j k l m n o p
q r s t u v w x y z */
/* a */ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 0, 0,
0, 7, 15, 0, 16, 0, 0, 0, 0, 0 },
/* b */ { 2, 0, 0, 4, 5, 7, 0, 0, 0, 0, 0, 8, 9, 10, 11, 12,
0, 13, 0, 0, 0, 0, 22, 0, 0, 0 },
! /* c */ { 3, 12, 16, 18, 20, 22, 25, 0, 0, 0, 0, 33, 37, 40, 46, 55,
57, 58, 59, 0, 61, 0, 64, 0, 0, 0 },
/* d */ { 0, 0, 0, 0, 0, 0, 0, 0, 6, 15, 0, 16, 0, 0, 17, 0,
0, 19, 20, 0, 0, 0, 0, 0, 0, 0 },
/* e */ { 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 10, 0, 0,
0, 0, 0, 0, 0, 0, 0, 16, 0, 0 },
/* f */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
0, 0, 0, 0, 15, 0, 0, 0, 0, 0 },
***************
*** 52,58 ****
/* i */ { 1, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 5, 6, 0, 0, 0,
0, 0, 13, 0, 15, 0, 0, 0, 0, 0 },
/* j */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
/* k */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
! /* l */ { 3, 10, 13, 17, 18, 22, 25, 30, 0, 0, 0, 32, 35, 38, 42, 48,
0, 50, 59, 51, 52, 56, 58, 0, 0, 0 },
/* m */ { 1, 0, 0, 0, 7, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 16 },
/* n */ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 8, 10, 0,
0, 0, 0, 0, 17, 0, 0, 0, 0, 0 },
/* o */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 5, 0, 0,
0, 0, 0, 0, 9, 0, 11, 0, 0, 0 },
--- 52,58 ----
/* i */ { 1, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 5, 6, 0, 0, 0,
0, 0, 13, 0, 15, 0, 0, 0, 0, 0 },
/* j */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
/* k */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
! /* l */ { 3, 11, 15, 19, 20, 24, 27, 32, 0, 0, 0, 34, 37, 40, 44, 50,
0, 52, 61, 53, 54, 58, 60, 0, 0, 0 },
/* m */ { 1, 0, 0, 0, 7, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 16 },
/* n */ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 8, 10, 0,
0, 0, 0, 0, 17, 0, 0, 0, 0, 0 },
/* o */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 5, 0, 0,
0, 0, 0, 0, 9, 0, 11, 0, 0, 0 },
***************
*** 69,72 ****
/* z */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
! static const int command_count = 554;
--- 69,72 ----
/* z */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
! static const int command_count = 558;
*** ../vim-8.1.1274/src/ex_cmds.h 2019-05-04 15:05:24.927269310 +0200
--- src/ex_cmds.h 2019-05-05 14:56:42.134251046 +0200
***************
*** 266,271 ****
--- 266,274 ----
EX(CMD_caddfile, "caddfile", ex_cfile,
TRLBAR|FILE1,
ADDR_NONE),
+ EX(CMD_cafter, "cafter", ex_cbelow,
+ RANGE|COUNT|TRLBAR,
+ ADDR_UNSIGNED),
EX(CMD_call, "call", ex_call,
RANGE|NEEDARG|EXTRA|NOTRLCOM|SBOXOK|CMDWIN,
ADDR_LINES),
***************
*** 275,280 ****
--- 278,286 ----
EX(CMD_cbuffer, "cbuffer", ex_cbuffer,
BANG|RANGE|WORD1|TRLBAR,
ADDR_OTHER),
+ EX(CMD_cbefore, "cbefore", ex_cbelow,
+ RANGE|COUNT|TRLBAR,
+ ADDR_UNSIGNED),
EX(CMD_cbelow, "cbelow", ex_cbelow,
RANGE|COUNT|TRLBAR,
ADDR_UNSIGNED),
***************
*** 749,760 ****
--- 755,772 ----
EX(CMD_laddfile, "laddfile", ex_cfile,
TRLBAR|FILE1,
ADDR_NONE),
+ EX(CMD_lafter, "lafter", ex_cbelow,
+ RANGE|COUNT|TRLBAR,
+ ADDR_UNSIGNED),
EX(CMD_later, "later", ex_later,
TRLBAR|EXTRA|NOSPC|CMDWIN,
ADDR_NONE),
EX(CMD_lbuffer, "lbuffer", ex_cbuffer,
BANG|RANGE|WORD1|TRLBAR,
ADDR_OTHER),
+ EX(CMD_lbefore, "lbefore", ex_cbelow,
+ RANGE|COUNT|TRLBAR,
+ ADDR_UNSIGNED),
EX(CMD_lbelow, "lbelow", ex_cbelow,
RANGE|COUNT|TRLBAR,
ADDR_UNSIGNED),
*** ../vim-8.1.1274/src/quickfix.c 2019-05-04 15:05:24.927269310 +0200
--- src/quickfix.c 2019-05-05 14:56:42.138251022 +0200
***************
*** 5128,5163 ****
}
/*
! * Find the first quickfix entry below line 'lnum' in buffer 'bnr'.
* '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)
{
! if (qfp->qf_lnum > lnum)
! // First entry is after line 'lnum'
return qfp;
! // Find the entry just before or at the line 'lnum'
while (qfp->qf_next != NULL
&& qfp->qf_next->qf_fnum == bnr
! && qfp->qf_next->qf_lnum <= lnum)
{
qfp = qfp->qf_next;
++*errornr;
}
if (qfp->qf_next == NULL || qfp->qf_next->qf_fnum != bnr)
! // No entries found after 'lnum'
return NULL;
! // Use the entry just after line 'lnum'
qfp = qfp->qf_next;
++*errornr;
--- 5128,5227 ----
}
/*
! * Returns TRUE if the specified quickfix entry is
! * after the given line (linewise is TRUE)
! * or after the line and column.
! */
! static int
! qf_entry_after_pos(qfline_T *qfp, pos_T *pos, int linewise)
! {
! if (linewise)
! return qfp->qf_lnum > pos->lnum;
! else
! 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 int
! qf_entry_before_pos(qfline_T *qfp, pos_T *pos, int linewise)
! {
! if (linewise)
! return qfp->qf_lnum < pos->lnum;
! else
! 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 int
! qf_entry_on_or_after_pos(qfline_T *qfp, pos_T *pos, int linewise)
! {
! if (linewise)
! return qfp->qf_lnum >= pos->lnum;
! else
! 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 int
! qf_entry_on_or_before_pos(qfline_T *qfp, pos_T *pos, int linewise)
! {
! if (linewise)
! return qfp->qf_lnum <= pos->lnum;
! else
! 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 'pos'.
*/
static qfline_T *
! qf_find_entry_after_pos(
int bnr,
! pos_T *pos,
! int linewise,
qfline_T *qfp,
int *errornr)
{
! if (qf_entry_after_pos(qfp, pos, linewise))
! // First entry is after postion 'pos'
return qfp;
! // Find the entry just before or at the position 'pos'
while (qfp->qf_next != NULL
&& qfp->qf_next->qf_fnum == bnr
! && 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 position 'pos'
return NULL;
! // Use the entry just after position 'pos'
qfp = qfp->qf_next;
++*errornr;
***************
*** 5165,5210 ****
}
/*
! * Find the first quickfix entry before line 'lnum' in buffer 'bnr'.
* '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)
{
! // Find the entry just before the line 'lnum'
while (qfp->qf_next != NULL
&& qfp->qf_next->qf_fnum == bnr
! && qfp->qf_next->qf_lnum < lnum)
{
qfp = qfp->qf_next;
++*errornr;
}
! if (qfp->qf_lnum >= lnum) // entry is after 'lnum'
return NULL;
! // 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
* the direction 'dir'.
*/
static qfline_T *
qf_find_closest_entry(
qf_list_T *qfl,
int bnr,
! linenr_T lnum,
int dir,
int *errornr)
{
qfline_T *qfp;
--- 5229,5280 ----
}
/*
! * 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 'pos'.
*/
static qfline_T *
! qf_find_entry_before_pos(
int bnr,
! pos_T *pos,
! int linewise,
qfline_T *qfp,
int *errornr)
{
! // Find the entry just before the position 'pos'
while (qfp->qf_next != NULL
&& qfp->qf_next->qf_fnum == bnr
! && qf_entry_before_pos(qfp->qf_next, pos, linewise))
{
qfp = qfp->qf_next;
++*errornr;
}
! if (qf_entry_on_or_after_pos(qfp, pos, linewise))
return NULL;
! 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 position 'pos' in buffer 'bnr' in
* the direction 'dir'.
*/
static qfline_T *
qf_find_closest_entry(
qf_list_T *qfl,
int bnr,
! pos_T *pos,
int dir,
+ int linewise,
int *errornr)
{
qfline_T *qfp;
***************
*** 5217,5251 ****
return NULL; // no entry in this file
if (dir == FORWARD)
! qfp = qf_find_entry_on_next_line(bnr, lnum, qfp, errornr);
else
! qfp = qf_find_entry_on_prev_line(bnr, lnum, 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 qfline_T *
! qf_get_nth_below_entry(qfline_T *entry, int *errornr, int n)
{
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 (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;
break;
}
--- 5287,5326 ----
return NULL; // no entry in this file
if (dir == FORWARD)
! qfp = qf_find_entry_after_pos(bnr, pos, linewise, qfp, errornr);
else
! qfp = qf_find_entry_before_pos(bnr, pos, linewise, qfp, errornr);
return qfp;
}
/*
! * 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 qfline_T *
! qf_get_nth_below_entry(qfline_T *entry, int n, int linewise, int *errornr)
{
while (n-- > 0 && !got_int)
{
qfline_T *first_entry = entry;
int first_errornr = *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 (linewise)
! {
! // If multiple entries are on the same line, then use the first
! // entry
! entry = first_entry;
! *errornr = first_errornr;
! }
break;
}
***************
*** 5257,5267 ****
}
/*
! * Get the nth quickfix entry above the specified entry treating multiple
! * entries on a single line as one. Searches backwards in the list.
*/
static qfline_T *
! qf_get_nth_above_entry(qfline_T *entry, int *errornr, int n)
{
while (n-- > 0 && !got_int)
{
--- 5332,5343 ----
}
/*
! * 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 qfline_T *
! qf_get_nth_above_entry(qfline_T *entry, int n, int linewise, int *errornr)
{
while (n-- > 0 && !got_int)
{
***************
*** 5273,5297 ****
--*errornr;
// If multiple entries are on the same line, then use the first entry
! entry = qf_find_first_entry_on_line(entry, errornr);
}
return entry;
}
/*
! * 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, int n, int dir)
{
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);
if (adj_entry == NULL)
return 0;
--- 5349,5380 ----
--*errornr;
// If multiple entries are on the same line, then use the first entry
! if (linewise)
! entry = qf_find_first_entry_on_line(entry, errornr);
}
return entry;
}
/*
! * 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,
! int n,
! int dir,
! int linewise)
{
qfline_T *adj_entry;
int errornr;
! // Find an entry closest to the specified position
! adj_entry = qf_find_closest_entry(qfl, bnr, pos, dir, linewise, &errornr);
if (adj_entry == NULL)
return 0;
***************
*** 5299,5315 ****
{
// Go to the n'th entry in the current buffer
if (dir == FORWARD)
! adj_entry = qf_get_nth_below_entry(adj_entry, &errornr, n);
else
! adj_entry = qf_get_nth_above_entry(adj_entry, &errornr, n);
}
return errornr;
}
/*
! * Jump to a quickfix entry in the current file nearest to the current line.
! * ":cabove", ":cbelow", ":labove" and ":lbelow" commands
*/
void
ex_cbelow(exarg_T *eap)
--- 5382,5402 ----
{
// Go to the n'th entry in the current buffer
if (dir == FORWARD)
! adj_entry = qf_get_nth_below_entry(adj_entry, n, linewise,
! &errornr);
else
! adj_entry = 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 or
! * current line/col.
! * ":cabove", ":cbelow", ":labove", ":lbelow", ":cafter", ":cbefore",
! * ":lafter" and ":lbefore" commands
*/
void
ex_cbelow(exarg_T *eap)
***************
*** 5319,5324 ****
--- 5406,5412 ----
int dir;
int buf_has_flag;
int errornr = 0;
+ pos_T pos;
if (eap->addr_count > 0 && eap->line2 <= 0)
{
***************
*** 5327,5333 ****
}
// Check whether the current buffer has any quickfix entries
! if (eap->cmdidx == CMD_cabove || eap->cmdidx == CMD_cbelow)
buf_has_flag = BUF_HAS_QF_ENTRY;
else
buf_has_flag = BUF_HAS_LL_ENTRY;
--- 5415,5422 ----
}
// Check whether the current buffer has any quickfix entries
! 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;
***************
*** 5348,5360 ****
return;
}
! if (eap->cmdidx == CMD_cbelow || eap->cmdidx == CMD_lbelow)
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);
if (errornr > 0)
qf_jump(qi, 0, errornr, FALSE);
--- 5437,5461 ----
return;
}
! 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;
! 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++;
! 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);
*** ../vim-8.1.1274/src/testdir/test_quickfix.vim 2019-05-04
15:05:24.927269310 +0200
--- src/testdir/test_quickfix.vim 2019-05-05 14:56:42.138251022 +0200
***************
*** 39,44 ****
--- 39,46 ----
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')
***************
*** 74,79 ****
--- 76,83 ----
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')
***************
*** 4041,4057 ****
--- 4045,4066 ----
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')
***************
*** 4065,4103 ****
call assert_fails('Xabove', 'E42:')
call assert_fails('3Xbelow', 'E42:')
call assert_fails('4Xabove', 'E42:')
" Test the commands with various arguments
! Xexpr ["X1:5:L5", "X2:5:L5", "X2:10:L10", "X2:15:L15", "X3:3:L3"]
edit +7 X2
Xabove
call assert_equal(['X2', 5], [bufname(''), line('.')])
call assert_fails('Xabove', 'E553:')
normal 2j
Xbelow
call assert_equal(['X2', 10], [bufname(''), line('.')])
" Last error in this file
Xbelow 99
call assert_equal(['X2', 15], [bufname(''), line('.')])
call assert_fails('Xbelow', 'E553:')
" First error in this file
Xabove 99
call assert_equal(['X2', 5], [bufname(''), line('.')])
call assert_fails('Xabove', 'E553:')
normal gg
Xbelow 2
call assert_equal(['X2', 10], [bufname(''), line('.')])
normal G
Xabove 2
call assert_equal(['X2', 10], [bufname(''), line('.')])
edit X4
call assert_fails('Xabove', 'E42:')
call assert_fails('Xbelow', '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:')
close
endif
--- 4074,4147 ----
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: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
***************
*** 4108,4134 ****
--- 4152,4203 ----
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')
*** ../vim-8.1.1274/src/version.c 2019-05-05 14:19:17.594303166 +0200
--- src/version.c 2019-05-05 14:58:18.513708487 +0200
***************
*** 769,770 ****
--- 769,772 ----
{ /* Add new patch number below this line */
+ /**/
+ 1275,
/**/
--
Permission is granted to read this message out aloud on Kings Cross Road,
London, under the condition that the orator is properly dressed.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.