0
0
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:
Bram Moolenaar
2019-05-05 15:02:30 +02:00
parent ce79353ace
commit cf6a55c4b0
7 changed files with 297 additions and 81 deletions

View File

@@ -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);