comparison src/quickfix.c @ 14838:6040d93396de v8.1.0431

patch 8.1.0431: the qf_jump() function is too long commit https://github.com/vim/vim/commit/6dae96ef7ad56191c13c4993f04cbfd450d91ad2 Author: Bram Moolenaar <Bram@vim.org> Date: Mon Sep 24 21:50:12 2018 +0200 patch 8.1.0431: the qf_jump() function is too long Problem: The qf_jump() function is too long. Solution: Refactor to split it into several functions. (Yegappan Lakshmanan)
author Christian Brabandt <cb@256bit.org>
date Mon, 24 Sep 2018 22:00:06 +0200
parents 74fd69162d50
children a74786d0370c
comparison
equal deleted inserted replaced
14837:e6a685b2c5b2 14838:6040d93396de
2519 */ 2519 */
2520 static qfline_T * 2520 static qfline_T *
2521 get_nth_valid_entry( 2521 get_nth_valid_entry(
2522 qf_list_T *qfl, 2522 qf_list_T *qfl,
2523 int errornr, 2523 int errornr,
2524 qfline_T *qf_ptr, 2524 int dir,
2525 int *qf_index, 2525 int *new_qfidx)
2526 int dir) 2526 {
2527 { 2527 qfline_T *qf_ptr = qfl->qf_ptr;
2528 int qf_idx = qfl->qf_index;
2528 qfline_T *prev_qf_ptr; 2529 qfline_T *prev_qf_ptr;
2529 int prev_index; 2530 int prev_index;
2530 static char_u *e_no_more_items = (char_u *)N_("E553: No more items"); 2531 static char_u *e_no_more_items = (char_u *)N_("E553: No more items");
2531 char_u *err = e_no_more_items; 2532 char_u *err = e_no_more_items;
2532 2533
2533 while (errornr--) 2534 while (errornr--)
2534 { 2535 {
2535 prev_qf_ptr = qf_ptr; 2536 prev_qf_ptr = qf_ptr;
2536 prev_index = *qf_index; 2537 prev_index = qf_idx;
2537 2538
2538 if (dir == FORWARD || dir == FORWARD_FILE) 2539 if (dir == FORWARD || dir == FORWARD_FILE)
2539 qf_ptr = get_next_valid_entry(qfl, qf_ptr, qf_index, dir); 2540 qf_ptr = get_next_valid_entry(qfl, qf_ptr, &qf_idx, dir);
2540 else 2541 else
2541 qf_ptr = get_prev_valid_entry(qfl, qf_ptr, qf_index, dir); 2542 qf_ptr = get_prev_valid_entry(qfl, qf_ptr, &qf_idx, dir);
2542 if (qf_ptr == NULL) 2543 if (qf_ptr == NULL)
2543 { 2544 {
2544 qf_ptr = prev_qf_ptr; 2545 qf_ptr = prev_qf_ptr;
2545 *qf_index = prev_index; 2546 qf_idx = prev_index;
2546 if (err != NULL) 2547 if (err != NULL)
2547 { 2548 {
2548 EMSG(_(err)); 2549 EMSG(_(err));
2549 return NULL; 2550 return NULL;
2550 } 2551 }
2552 } 2553 }
2553 2554
2554 err = NULL; 2555 err = NULL;
2555 } 2556 }
2556 2557
2558 *new_qfidx = qf_idx;
2557 return qf_ptr; 2559 return qf_ptr;
2558 } 2560 }
2559 2561
2560 /* 2562 /*
2561 * Get n'th (errornr) quickfix entry 2563 * Get n'th (errornr) quickfix entry from the current entry in the quickfix
2564 * list 'qfl'. Returns a pointer to the new entry and the index in 'new_qfidx'
2562 */ 2565 */
2563 static qfline_T * 2566 static qfline_T *
2564 get_nth_entry( 2567 get_nth_entry(qf_list_T *qfl, int errornr, int *new_qfidx)
2568 {
2569 qfline_T *qf_ptr = qfl->qf_ptr;
2570 int qf_idx = qfl->qf_index;
2571
2572 // New error number is less than the current error number
2573 while (errornr < qf_idx && qf_idx > 1 && qf_ptr->qf_prev != NULL)
2574 {
2575 --qf_idx;
2576 qf_ptr = qf_ptr->qf_prev;
2577 }
2578 // New error number is greater than the current error number
2579 while (errornr > qf_idx && qf_idx < qfl->qf_count &&
2580 qf_ptr->qf_next != NULL)
2581 {
2582 ++qf_idx;
2583 qf_ptr = qf_ptr->qf_next;
2584 }
2585
2586 *new_qfidx = qf_idx;
2587 return qf_ptr;
2588 }
2589
2590 /*
2591 * Get a entry specied by 'errornr' and 'dir' from the current
2592 * quickfix/location list. 'errornr' specifies the index of the entry and 'dir'
2593 * specifies the direction (FORWARD/BACKWARD/FORWARD_FILE/BACKWARD_FILE).
2594 * Returns a pointer to the entry and the index of the new entry is stored in
2595 * 'new_qfidx'.
2596 */
2597 static qfline_T *
2598 qf_get_entry(
2565 qf_list_T *qfl, 2599 qf_list_T *qfl,
2566 int errornr, 2600 int errornr,
2567 qfline_T *qf_ptr, 2601 int dir,
2568 int *cur_qfidx) 2602 int *new_qfidx)
2569 { 2603 {
2570 int qf_idx = *cur_qfidx; 2604 qfline_T *qf_ptr = qfl->qf_ptr;
2571 2605 int qfidx = qfl->qf_index;
2572 /* New error number is less than the current error number */ 2606
2573 while (errornr < qf_idx && qf_idx > 1 && qf_ptr->qf_prev != NULL) 2607 if (dir != 0) // next/prev valid entry
2574 { 2608 qf_ptr = get_nth_valid_entry(qfl, errornr, dir, &qfidx);
2575 --qf_idx; 2609 else if (errornr != 0) // go to specified number
2576 qf_ptr = qf_ptr->qf_prev; 2610 qf_ptr = get_nth_entry(qfl, errornr, &qfidx);
2577 } 2611
2578 /* New error number is greater than the current error number */ 2612 *new_qfidx = qfidx;
2579 while (errornr > qf_idx && qf_idx < qfl->qf_count &&
2580 qf_ptr->qf_next != NULL)
2581 {
2582 ++qf_idx;
2583 qf_ptr = qf_ptr->qf_next;
2584 }
2585
2586 *cur_qfidx = qf_idx;
2587 return qf_ptr; 2613 return qf_ptr;
2588 } 2614 }
2589 2615
2590 /* 2616 /*
2591 * Find a window displaying a Vim help file. 2617 * Find a window displaying a Vim help file.
2879 return OK; 2905 return OK;
2880 } 2906 }
2881 2907
2882 /* 2908 /*
2883 * Edit the selected file or help file. 2909 * Edit the selected file or help file.
2910 * Returns OK if successfully edited the file, FAIL on failing to open the
2911 * buffer and NOTDONE if the quickfix/location list was freed by an autocmd
2912 * when opening the buffer.
2884 */ 2913 */
2885 static int 2914 static int
2886 qf_jump_edit_buffer( 2915 qf_jump_edit_buffer(
2887 qf_info_T *qi, 2916 qf_info_T *qi,
2888 qfline_T *qf_ptr, 2917 qfline_T *qf_ptr,
2889 int forceit, 2918 int forceit,
2890 win_T *oldwin, 2919 win_T *oldwin,
2891 int *opened_window, 2920 int *opened_window)
2892 int *abort)
2893 { 2921 {
2894 qf_list_T *qfl = &qi->qf_lists[qi->qf_curlist]; 2922 qf_list_T *qfl = &qi->qf_lists[qi->qf_curlist];
2895 int retval = OK; 2923 int retval = OK;
2896 2924
2897 if (qf_ptr->qf_type == 1) 2925 if (qf_ptr->qf_type == 1)
2923 * present and the list is still valid. 2951 * present and the list is still valid.
2924 */ 2952 */
2925 if (!win_valid_any_tab(oldwin)) 2953 if (!win_valid_any_tab(oldwin))
2926 { 2954 {
2927 EMSG(_("E924: Current window was closed")); 2955 EMSG(_("E924: Current window was closed"));
2928 *abort = TRUE;
2929 *opened_window = FALSE; 2956 *opened_window = FALSE;
2957 return NOTDONE;
2930 } 2958 }
2931 else if (!qflist_valid(oldwin, save_qfid)) 2959 else if (!qflist_valid(oldwin, save_qfid))
2932 { 2960 {
2933 EMSG(_(e_loc_list_changed)); 2961 EMSG(_(e_loc_list_changed));
2934 *abort = TRUE; 2962 return NOTDONE;
2935 } 2963 }
2936 } 2964 }
2937 else if (old_qf_curlist != qi->qf_curlist 2965 else if (old_qf_curlist != qi->qf_curlist
2938 || !is_qf_entry_present(qfl, qf_ptr)) 2966 || !is_qf_entry_present(qfl, qf_ptr))
2939 { 2967 {
2940 if (IS_QF_STACK(qi)) 2968 if (IS_QF_STACK(qi))
2941 EMSG(_("E925: Current quickfix was changed")); 2969 EMSG(_("E925: Current quickfix was changed"));
2942 else 2970 else
2943 EMSG(_(e_loc_list_changed)); 2971 EMSG(_(e_loc_list_changed));
2944 *abort = TRUE; 2972 return NOTDONE;
2945 } 2973 }
2946
2947 if (*abort)
2948 retval = FAIL;
2949 } 2974 }
2950 2975
2951 return retval; 2976 return retval;
2952 } 2977 }
2953 2978
3064 msg_attr_keep(IObuff, 0, TRUE); 3089 msg_attr_keep(IObuff, 0, TRUE);
3065 msg_scroll = i; 3090 msg_scroll = i;
3066 } 3091 }
3067 3092
3068 /* 3093 /*
3094 * Find a usable window for opening a file from the quickfix/location list. If
3095 * a window is not found then open a new window.
3096 * Returns OK if successfully jumped or opened a window. Returns FAIL if not
3097 * able to jump/open a window. Returns NOTDONE if a file is not associated
3098 * with the entry.
3099 */
3100 static int
3101 qf_jump_open_window(qf_info_T *qi, qfline_T *qf_ptr, int *opened_window)
3102 {
3103 // For ":helpgrep" find a help window or open one.
3104 if (qf_ptr->qf_type == 1 && (!bt_help(curwin->w_buffer) || cmdmod.tab != 0))
3105 if (jump_to_help_window(qi, opened_window) == FAIL)
3106 return FAIL;
3107
3108 // If currently in the quickfix window, find another window to show the
3109 // file in.
3110 if (bt_quickfix(curbuf) && !*opened_window)
3111 {
3112 // If there is no file specified, we don't know where to go.
3113 // But do advance, otherwise ":cn" gets stuck.
3114 if (qf_ptr->qf_fnum == 0)
3115 return NOTDONE;
3116
3117 if (qf_jump_to_usable_window(qf_ptr->qf_fnum, opened_window) == FAIL)
3118 return FAIL;
3119 }
3120
3121 return OK;
3122 }
3123
3124 /*
3125 * Edit a selected file from the quickfix/location list and jump to a
3126 * particular line/column, adjust the folds and display a message about the
3127 * jump.
3128 * Returns OK on success and FAIL on failing to open the file/buffer. Returns
3129 * NOTDONE if the quickfix/location list is freed by an autocmd when opening
3130 * the file.
3131 */
3132 static int
3133 qf_jump_to_buffer(
3134 qf_info_T *qi,
3135 int qf_index,
3136 qfline_T *qf_ptr,
3137 int forceit,
3138 win_T *oldwin,
3139 int *opened_window,
3140 int openfold,
3141 int print_message)
3142 {
3143 buf_T *old_curbuf;
3144 linenr_T old_lnum;
3145 int retval = OK;
3146
3147 // If there is a file name, read the wanted file if needed, and check
3148 // autowrite etc.
3149 old_curbuf = curbuf;
3150 old_lnum = curwin->w_cursor.lnum;
3151
3152 if (qf_ptr->qf_fnum != 0)
3153 {
3154 retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, oldwin,
3155 opened_window);
3156 if (retval != OK)
3157 return retval;
3158 }
3159
3160 // When not switched to another buffer, still need to set pc mark
3161 if (curbuf == old_curbuf)
3162 setpcmark();
3163
3164 qf_jump_goto_line(qf_ptr->qf_lnum, qf_ptr->qf_col, qf_ptr->qf_viscol,
3165 qf_ptr->qf_pattern);
3166
3167 #ifdef FEAT_FOLDING
3168 if ((fdo_flags & FDO_QUICKFIX) && openfold)
3169 foldOpenCursor();
3170 #endif
3171 if (print_message)
3172 qf_jump_print_msg(qi, qf_index, qf_ptr, old_curbuf, old_lnum);
3173
3174 return retval;
3175 }
3176
3177 /*
3069 * jump to a quickfix line 3178 * jump to a quickfix line
3070 * if dir == FORWARD go "errornr" valid entries forward 3179 * if dir == FORWARD go "errornr" valid entries forward
3071 * if dir == BACKWARD go "errornr" valid entries backward 3180 * if dir == BACKWARD go "errornr" valid entries backward
3072 * if dir == FORWARD_FILE go "errornr" valid entries files backward 3181 * if dir == FORWARD_FILE go "errornr" valid entries files backward
3073 * if dir == BACKWARD_FILE go "errornr" valid entries files backward 3182 * if dir == BACKWARD_FILE go "errornr" valid entries files backward
3083 qf_list_T *qfl; 3192 qf_list_T *qfl;
3084 qfline_T *qf_ptr; 3193 qfline_T *qf_ptr;
3085 qfline_T *old_qf_ptr; 3194 qfline_T *old_qf_ptr;
3086 int qf_index; 3195 int qf_index;
3087 int old_qf_index; 3196 int old_qf_index;
3088 buf_T *old_curbuf;
3089 linenr_T old_lnum;
3090 char_u *old_swb = p_swb; 3197 char_u *old_swb = p_swb;
3091 unsigned old_swb_flags = swb_flags; 3198 unsigned old_swb_flags = swb_flags;
3092 int opened_window = FALSE; 3199 int opened_window = FALSE;
3093 win_T *oldwin = curwin; 3200 win_T *oldwin = curwin;
3094 int print_message = TRUE; 3201 int print_message = TRUE;
3095 #ifdef FEAT_FOLDING 3202 #ifdef FEAT_FOLDING
3096 int old_KeyTyped = KeyTyped; /* getting file may reset it */ 3203 int old_KeyTyped = KeyTyped; // getting file may reset it
3097 #endif 3204 #endif
3098 int retval = OK; 3205 int retval = OK;
3099 3206
3100 if (qi == NULL) 3207 if (qi == NULL)
3101 qi = &ql_info; 3208 qi = &ql_info;
3111 3218
3112 qf_ptr = qfl->qf_ptr; 3219 qf_ptr = qfl->qf_ptr;
3113 old_qf_ptr = qf_ptr; 3220 old_qf_ptr = qf_ptr;
3114 qf_index = qfl->qf_index; 3221 qf_index = qfl->qf_index;
3115 old_qf_index = qf_index; 3222 old_qf_index = qf_index;
3116 if (dir != 0) /* next/prev valid entry */ 3223
3117 { 3224 qf_ptr = qf_get_entry(qfl, errornr, dir, &qf_index);
3118 qf_ptr = get_nth_valid_entry(qfl, errornr, qf_ptr, &qf_index, dir); 3225 if (qf_ptr == NULL)
3119 if (qf_ptr == NULL) 3226 {
3120 { 3227 qf_ptr = old_qf_ptr;
3121 qf_ptr = old_qf_ptr; 3228 qf_index = old_qf_index;
3122 qf_index = old_qf_index; 3229 goto theend;
3123 goto theend; 3230 }
3124 }
3125 }
3126 else if (errornr != 0) /* go to specified number */
3127 qf_ptr = get_nth_entry(qfl, errornr, qf_ptr, &qf_index);
3128 3231
3129 qfl->qf_index = qf_index; 3232 qfl->qf_index = qf_index;
3130 if (qf_win_pos_update(qi, old_qf_index)) 3233 if (qf_win_pos_update(qi, old_qf_index))
3131 /* No need to print the error message if it's visible in the error 3234 // No need to print the error message if it's visible in the error
3132 * window */ 3235 // window
3133 print_message = FALSE; 3236 print_message = FALSE;
3134 3237
3135 /* 3238 retval = qf_jump_open_window(qi, qf_ptr, &opened_window);
3136 * For ":helpgrep" find a help window or open one. 3239 if (retval == FAIL)
3137 */ 3240 goto failed;
3138 if (qf_ptr->qf_type == 1 && (!bt_help(curwin->w_buffer) || cmdmod.tab != 0)) 3241 if (retval == NOTDONE)
3139 if (jump_to_help_window(qi, &opened_window) == FAIL) 3242 goto theend;
3140 goto theend; 3243
3141 3244 retval = qf_jump_to_buffer(qi, qf_index, qf_ptr, forceit, oldwin,
3142 /* 3245 &opened_window, old_KeyTyped, print_message);
3143 * If currently in the quickfix window, find another window to show the 3246 if (retval == NOTDONE)
3144 * file in. 3247 {
3145 */ 3248 // Quickfix/location list is freed by an autocmd
3146 if (bt_quickfix(curbuf) && !opened_window) 3249 qi = NULL;
3147 { 3250 qf_ptr = NULL;
3148 /* 3251 }
3149 * If there is no file specified, we don't know where to go. 3252
3150 * But do advance, otherwise ":cn" gets stuck. 3253 if (retval != OK)
3151 */
3152 if (qf_ptr->qf_fnum == 0)
3153 goto theend;
3154
3155 if (qf_jump_to_usable_window(qf_ptr->qf_fnum, &opened_window) == FAIL)
3156 goto failed;
3157 }
3158
3159 /*
3160 * If there is a file name,
3161 * read the wanted file if needed, and check autowrite etc.
3162 */
3163 old_curbuf = curbuf;
3164 old_lnum = curwin->w_cursor.lnum;
3165
3166 if (qf_ptr->qf_fnum != 0)
3167 {
3168 int abort = FALSE;
3169
3170 retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, oldwin,
3171 &opened_window, &abort);
3172 if (abort)
3173 {
3174 qi = NULL;
3175 qf_ptr = NULL;
3176 }
3177 }
3178
3179 if (retval == OK)
3180 {
3181 /* When not switched to another buffer, still need to set pc mark */
3182 if (curbuf == old_curbuf)
3183 setpcmark();
3184
3185 if (qf_ptr != NULL)
3186 qf_jump_goto_line(qf_ptr->qf_lnum, qf_ptr->qf_col,
3187 qf_ptr->qf_viscol, qf_ptr->qf_pattern);
3188
3189 #ifdef FEAT_FOLDING
3190 if ((fdo_flags & FDO_QUICKFIX) && old_KeyTyped)
3191 foldOpenCursor();
3192 #endif
3193 if (print_message)
3194 qf_jump_print_msg(qi, qf_index, qf_ptr, old_curbuf, old_lnum);
3195 }
3196 else
3197 { 3254 {
3198 if (opened_window) 3255 if (opened_window)
3199 win_close(curwin, TRUE); /* Close opened window */ 3256 win_close(curwin, TRUE); // Close opened window
3200 if (qf_ptr != NULL && qf_ptr->qf_fnum != 0) 3257 if (qf_ptr != NULL && qf_ptr->qf_fnum != 0)
3201 { 3258 {
3202 /* 3259 // Couldn't open file, so put index back where it was. This could
3203 * Couldn't open file, so put index back where it was. This could 3260 // happen if the file was readonly and we changed something.
3204 * happen if the file was readonly and we changed something.
3205 */
3206 failed: 3261 failed:
3207 qf_ptr = old_qf_ptr; 3262 qf_ptr = old_qf_ptr;
3208 qf_index = old_qf_index; 3263 qf_index = old_qf_index;
3209 } 3264 }
3210 } 3265 }
3214 qfl->qf_ptr = qf_ptr; 3269 qfl->qf_ptr = qf_ptr;
3215 qfl->qf_index = qf_index; 3270 qfl->qf_index = qf_index;
3216 } 3271 }
3217 if (p_swb != old_swb && opened_window) 3272 if (p_swb != old_swb && opened_window)
3218 { 3273 {
3219 /* Restore old 'switchbuf' value, but not when an autocommand or 3274 // Restore old 'switchbuf' value, but not when an autocommand or
3220 * modeline has changed the value. */ 3275 // modeline has changed the value.
3221 if (p_swb == empty_option) 3276 if (p_swb == empty_option)
3222 { 3277 {
3223 p_swb = old_swb; 3278 p_swb = old_swb;
3224 swb_flags = old_swb_flags; 3279 swb_flags = old_swb_flags;
3225 } 3280 }