diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-05-05 15:02:30 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-05-05 15:02:30 +0200 |
commit | cf6a55c4b0cbf38b0c3fbed5ffd9a3fd0d2ede0e (patch) | |
tree | ba576efdd0c82bd9177a75be2584be5f445a680b /src/quickfix.c | |
parent | ce79353ace9e21238f13655089363cd23cbb6b32 (diff) |
patch 8.1.1275: cannot navigate to errors before/after the cursorv8.1.1275
Problem: Cannot navigate to errors before/after the cursor.
Solution: Add the :cbefore and :cafter commands. (Yegappan Lakshmanan,
closes #4340)
Diffstat (limited to 'src/quickfix.c')
-rw-r--r-- | src/quickfix.c | 201 |
1 files changed, 151 insertions, 50 deletions
diff --git a/src/quickfix.c b/src/quickfix.c index c11436a006..b4497ae754 100644 --- a/src/quickfix.c +++ b/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); |