aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/quickfix.c212
1 files changed, 135 insertions, 77 deletions
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index ddce1e922d..f6798ff692 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -2348,25 +2348,27 @@ static qfline_T *get_prev_valid_entry(qf_list_T *qfl, qfline_T *qf_ptr,
/// dir == FORWARD or FORWARD_FILE: next valid entry
/// dir == BACKWARD or BACKWARD_FILE: previous valid entry
static qfline_T *get_nth_valid_entry(qf_list_T *qfl, int errornr,
- qfline_T *qf_ptr, int *qf_index, int dir)
+ int dir, int *new_qfidx)
{
+ qfline_T *qf_ptr = qfl->qf_ptr;
+ int qf_idx = qfl->qf_index;
qfline_T *prev_qf_ptr;
int prev_index;
char_u *err = e_no_more_items;
while (errornr--) {
prev_qf_ptr = qf_ptr;
- prev_index = *qf_index;
+ prev_index = qf_idx;
if (dir == FORWARD || dir == FORWARD_FILE) {
- qf_ptr = get_next_valid_entry(qfl, qf_ptr, qf_index, dir);
+ qf_ptr = get_next_valid_entry(qfl, qf_ptr, &qf_idx, dir);
} else {
- qf_ptr = get_prev_valid_entry(qfl, qf_ptr, qf_index, dir);
+ qf_ptr = get_prev_valid_entry(qfl, qf_ptr, &qf_idx, dir);
}
if (qf_ptr == NULL) {
qf_ptr = prev_qf_ptr;
- *qf_index = prev_index;
+ qf_idx = prev_index;
if (err != NULL) {
EMSG(_(err));
return NULL;
@@ -2377,14 +2379,16 @@ static qfline_T *get_nth_valid_entry(qf_list_T *qfl, int errornr,
err = NULL;
}
+ *new_qfidx = qf_idx;
return qf_ptr;
}
-/// Get n'th (errornr) quickfix entry
-static qfline_T *get_nth_entry(qf_list_T *qfl, int errornr, qfline_T *qf_ptr,
- int *cur_qfidx)
+/// Get n'th (errornr) quickfix entry from the current entry in the quickfix
+/// list 'qfl'. Returns a pointer to the new entry and the index in 'new_qfidx'
+static qfline_T *get_nth_entry(qf_list_T *qfl, int errornr, int *new_qfidx)
{
- int qf_idx = *cur_qfidx;
+ qfline_T *qf_ptr = qfl->qf_ptr;
+ int qf_idx = qfl->qf_index;;
// New error number is less than the current error number
while (errornr < qf_idx && qf_idx > 1 && qf_ptr->qf_prev != NULL) {
@@ -2400,10 +2404,31 @@ static qfline_T *get_nth_entry(qf_list_T *qfl, int errornr, qfline_T *qf_ptr,
qf_ptr = qf_ptr->qf_next;
}
- *cur_qfidx = qf_idx;
+ *new_qfidx = qf_idx;
return qf_ptr;
}
+/// Get a entry specied by 'errornr' and 'dir' from the current
+/// quickfix/location list. 'errornr' specifies the index of the entry and 'dir'
+/// specifies the direction (FORWARD/BACKWARD/FORWARD_FILE/BACKWARD_FILE).
+/// Returns a pointer to the entry and the index of the new entry is stored in
+/// 'new_qfidx'.
+static qfline_T * qf_get_entry(qf_list_T *qfl, int errornr,
+ int dir, int *new_qfidx)
+{
+ qfline_T *qf_ptr = qfl->qf_ptr;
+ int qfidx = qfl->qf_index;
+
+ if (dir != 0) { // next/prev valid entry
+ qf_ptr = get_nth_valid_entry(qfl, errornr, dir, &qfidx);
+ } else if (errornr != 0) { // go to specified number
+ qf_ptr = get_nth_entry(qfl, errornr, &qfidx);
+ }
+
+ *new_qfidx = qfidx;
+ return qf_ptr;
+}
+
// Find a window displaying a Vim help file.
static win_T *qf_find_help_win(void)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
@@ -2672,7 +2697,7 @@ static int qf_jump_to_usable_window(int qf_fnum, int *opened_window)
/// Edit the selected file or help file.
static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit,
- win_T *oldwin, int *opened_window, int *abort)
+ win_T *oldwin, int *opened_window)
{
qf_list_T *qfl = qf_get_curlist(qi);
qfltype_T qfl_type = qfl->qfl_type;
@@ -2700,11 +2725,11 @@ static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit,
// present and the list is still valid.
if (!win_valid_any_tab(oldwin)) {
EMSG(_("E924: Current window was closed"));
- *abort = true;
*opened_window = false;
+ return NOTDONE;
} else if (!qflist_valid(oldwin, save_qfid)) {
EMSG(_(e_loc_list_changed));
- *abort = true;
+ return NOTDONE;
}
} else if (!is_qf_entry_present(qfl, qf_ptr)) {
if (qfl_type == QFLT_QUICKFIX) {
@@ -2712,11 +2737,7 @@ static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit,
} else {
EMSG(_(e_loc_list_changed));
}
- *abort = true;
- }
-
- if (*abort) {
- retval = FAIL;
+ return NOTDONE;
}
}
@@ -2792,7 +2813,84 @@ static void qf_jump_print_msg(qf_info_T *qi, int qf_index, qfline_T *qf_ptr,
msg_scroll = (int)i;
}
-/// jump to a quickfix line
+/// Find a usable window for opening a file from the quickfix/location list. If
+/// a window is not found then open a new window.
+/// Returns OK if successfully jumped or opened a window. Returns FAIL if not
+/// able to jump/open a window. Returns NOTDONE if a file is not associated
+/// with the entry.
+static int qf_jump_open_window(qf_info_T *qi, qfline_T *qf_ptr,
+ int *opened_window)
+{
+ // For ":helpgrep" find a help window or open one.
+ if (qf_ptr->qf_type == 1 && (!bt_help(curwin->w_buffer) || cmdmod.tab != 0)) {
+ if (jump_to_help_window(qi, opened_window) == FAIL) {
+ return FAIL;
+ }
+ }
+
+ // If currently in the quickfix window, find another window to show the
+ // file in.
+ if (bt_quickfix(curbuf) && !*opened_window) {
+ // If there is no file specified, we don't know where to go.
+ // But do advance, otherwise ":cn" gets stuck.
+ if (qf_ptr->qf_fnum == 0) {
+ return NOTDONE;
+ }
+
+ if (qf_jump_to_usable_window(qf_ptr->qf_fnum, opened_window) == FAIL) {
+ return FAIL;
+ }
+ }
+
+ return OK;
+}
+
+/// Edit a selected file from the quickfix/location list and jump to a
+/// particular line/column, adjust the folds and display a message about the
+/// jump.
+/// Returns OK on success and FAIL on failing to open the file/buffer. Returns
+/// NOTDONE if the quickfix/location list is freed by an autocmd when opening
+/// the file.
+static int qf_jump_to_buffer(qf_info_T *qi, int qf_index, qfline_T *qf_ptr,
+ int forceit, win_T *oldwin, int *opened_window,
+ int openfold, int print_message)
+{
+ buf_T *old_curbuf;
+ linenr_T old_lnum;
+ int retval = OK;
+
+ // If there is a file name, read the wanted file if needed, and check
+ // autowrite etc.
+ old_curbuf = curbuf;
+ old_lnum = curwin->w_cursor.lnum;
+
+ if (qf_ptr->qf_fnum != 0) {
+ retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, oldwin,
+ opened_window);
+ if (retval != OK) {
+ return retval;
+ }
+ }
+
+ // When not switched to another buffer, still need to set pc mark
+ if (curbuf == old_curbuf) {
+ setpcmark();
+ }
+
+ qf_jump_goto_line(qf_ptr->qf_lnum, qf_ptr->qf_col, qf_ptr->qf_viscol,
+ qf_ptr->qf_pattern);
+
+ if ((fdo_flags & FDO_QUICKFIX) && openfold) {
+ foldOpenCursor();
+ }
+ if (print_message) {
+ qf_jump_print_msg(qi, qf_index, qf_ptr, old_curbuf, old_lnum);
+ }
+
+ return retval;
+}
+
+/// jump to a quickfix ltne
/// if dir == FORWARD go "errornr" valid entries forward
/// if dir == BACKWARD go "errornr" valid entries backward
/// if dir == FORWARD_FILE go "errornr" valid entries files backward
@@ -2806,8 +2904,6 @@ void qf_jump(qf_info_T *qi, int dir, int errornr, int forceit)
qfline_T *old_qf_ptr;
int qf_index;
int old_qf_index;
- buf_T *old_curbuf;
- linenr_T old_lnum;
char_u *old_swb = p_swb;
unsigned old_swb_flags = swb_flags;
int opened_window = false;
@@ -2830,15 +2926,12 @@ void qf_jump(qf_info_T *qi, int dir, int errornr, int forceit)
old_qf_ptr = qf_ptr;
qf_index = qfl->qf_index;
old_qf_index = qf_index;
- if (dir != 0) { // next/prev valid entry
- qf_ptr = get_nth_valid_entry(qfl, errornr, qf_ptr, &qf_index, dir);
- if (qf_ptr == NULL) {
- qf_ptr = old_qf_ptr;
- qf_index = old_qf_index;
- goto theend; // The horror... the horror...
- }
- } else if (errornr != 0) { // go to specified number
- qf_ptr = get_nth_entry(qfl, errornr, qf_ptr, &qf_index);
+
+ qf_ptr = qf_get_entry(qfl, errornr, dir, &qf_index);
+ if (qf_ptr == NULL) {
+ qf_ptr = old_qf_ptr;
+ qf_index = old_qf_index;
+ goto theend;
}
qfl->qf_index = qf_index;
@@ -2848,58 +2941,23 @@ void qf_jump(qf_info_T *qi, int dir, int errornr, int forceit)
print_message = false;
}
- // For ":helpgrep" find a help window or open one.
- if (qf_ptr->qf_type == 1 && (!bt_help(curwin->w_buffer) || cmdmod.tab != 0)) {
- if (jump_to_help_window(qi, &opened_window) == FAIL) {
- goto theend;
- }
+ retval = qf_jump_open_window(qi, qf_ptr, &opened_window);
+ if (retval == FAIL) {
+ goto failed;
}
-
- // If currently in the quickfix window, find another window to show the
- // file in.
- if (bt_quickfix(curbuf) && !opened_window) {
- // If there is no file specified, we don't know where to go.
- // But do advance, otherwise ":cn" gets stuck.
- if (qf_ptr->qf_fnum == 0) {
- goto theend;
- }
- if (qf_jump_to_usable_window(qf_ptr->qf_fnum, &opened_window) == FAIL) {
- goto failed;
- }
+ if (retval == NOTDONE) {
+ goto theend;
}
- // If there is a file name,
- // read the wanted file if needed, and check autowrite etc.
- old_curbuf = curbuf;
- old_lnum = curwin->w_cursor.lnum;
-
- if (qf_ptr->qf_fnum != 0) {
- int abort = false;
- retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, oldwin, &opened_window,
- &abort);
- if (abort) {
- qi = NULL;
- qf_ptr = NULL;
- }
+ retval = qf_jump_to_buffer(qi, qf_index, qf_ptr, forceit, oldwin,
+ &opened_window, old_KeyTyped, print_message);
+ if (retval == NOTDONE) {
+ // Quickfix/location list is freed by an autocmd
+ qi = NULL;
+ qf_ptr = NULL;
}
- if (retval == OK) {
- // When not switched to another buffer, still need to set pc mark
- if (curbuf == old_curbuf) {
- setpcmark();
- }
-
- if (qf_ptr != NULL) {
- qf_jump_goto_line(qf_ptr->qf_lnum, qf_ptr->qf_col, qf_ptr->qf_viscol,
- qf_ptr->qf_pattern);
- }
-
- if ((fdo_flags & FDO_QUICKFIX) && old_KeyTyped)
- foldOpenCursor();
- if (print_message) {
- qf_jump_print_msg(qi, qf_index, qf_ptr, old_curbuf, old_lnum);
- }
- } else {
+ if (retval != OK) {
if (opened_window) {
win_close(curwin, true); // Close opened window
}