mirror of
https://github.com/vim/vim.git
synced 2025-09-26 04:04:07 -04:00
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 #4340)
This commit is contained in:
201
src/quickfix.c
201
src/quickfix.c
@@ -5128,36 +5128,100 @@ qf_find_last_entry_on_line(qfline_T *entry, int *errornr)
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 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 'lnum'.
|
||||
* Returns NULL if an entry is not found after 'pos'.
|
||||
*/
|
||||
static qfline_T *
|
||||
qf_find_entry_on_next_line(
|
||||
qf_find_entry_after_pos(
|
||||
int bnr,
|
||||
linenr_T lnum,
|
||||
pos_T *pos,
|
||||
int linewise,
|
||||
qfline_T *qfp,
|
||||
int *errornr)
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -5165,46 +5229,52 @@ qf_find_entry_on_next_line(
|
||||
}
|
||||
|
||||
/*
|
||||
* 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'.
|
||||
* Returns NULL if an entry is not found before 'pos'.
|
||||
*/
|
||||
static qfline_T *
|
||||
qf_find_entry_on_prev_line(
|
||||
qf_find_entry_before_pos(
|
||||
int bnr,
|
||||
linenr_T lnum,
|
||||
pos_T *pos,
|
||||
int linewise,
|
||||
qfline_T *qfp,
|
||||
int *errornr)
|
||||
{
|
||||
// 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,
|
||||
pos_T *pos,
|
||||
int dir,
|
||||
int linewise,
|
||||
int *errornr)
|
||||
{
|
||||
qfline_T *qfp;
|
||||
@@ -5217,35 +5287,40 @@ qf_find_closest_entry(
|
||||
return NULL; // no entry in this file
|
||||
|
||||
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.
|
||||
* 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 *errornr, int n)
|
||||
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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -5257,11 +5332,12 @@ qf_get_nth_below_entry(qfline_T *entry, int *errornr, int n)
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the nth quickfix entry above the specified entry treating multiple
|
||||
* entries on a single line as one. Searches backwards in the list.
|
||||
* 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 *errornr, int n)
|
||||
qf_get_nth_above_entry(qfline_T *entry, int n, int linewise, int *errornr)
|
||||
{
|
||||
while (n-- > 0 && !got_int)
|
||||
{
|
||||
@@ -5273,25 +5349,32 @@ qf_get_nth_above_entry(qfline_T *entry, int *errornr, int n)
|
||||
--*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);
|
||||
}
|
||||
|
||||
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.
|
||||
* 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, linenr_T lnum, int n, int dir)
|
||||
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 line
|
||||
adj_entry = qf_find_closest_entry(qfl, bnr, lnum, dir, &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,17 +5382,21 @@ qf_find_nth_adj_entry(qf_list_T *qfl, int bnr, linenr_T lnum, int n, int dir)
|
||||
{
|
||||
// Go to the n'th entry in the current buffer
|
||||
if (dir == FORWARD)
|
||||
adj_entry = qf_get_nth_below_entry(adj_entry, &errornr, n);
|
||||
adj_entry = qf_get_nth_below_entry(adj_entry, n, linewise,
|
||||
&errornr);
|
||||
else
|
||||
adj_entry = qf_get_nth_above_entry(adj_entry, &errornr, n);
|
||||
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.
|
||||
* ":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)
|
||||
@@ -5319,6 +5406,7 @@ ex_cbelow(exarg_T *eap)
|
||||
int dir;
|
||||
int buf_has_flag;
|
||||
int errornr = 0;
|
||||
pos_T pos;
|
||||
|
||||
if (eap->addr_count > 0 && eap->line2 <= 0)
|
||||
{
|
||||
@@ -5327,7 +5415,8 @@ 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;
|
||||
@@ -5348,13 +5437,25 @@ 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 = 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);
|
||||
|
Reference in New Issue
Block a user