To: vim_dev@googlegroups.com Subject: Patch 7.4.1871 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.1871 Problem: Appending to the quickfix list while the quickfix window is open is very slow. Solution: Do not delete all the lines, only append the new ones. Avoid using a window while updating the list. (closes #841) Files: src/quickfix.c *** ../vim-7.4.1870/src/quickfix.c 2016-05-24 19:59:48.203085324 +0200 --- src/quickfix.c 2016-06-02 13:21:44.180717359 +0200 *************** *** 126,134 **** static int is_qf_win(win_T *win, qf_info_T *qi); static win_T *qf_find_win(qf_info_T *qi); static buf_T *qf_find_buf(qf_info_T *qi); ! static void qf_update_buffer(qf_info_T *qi, int update_cursor); static void qf_set_title_var(qf_info_T *qi); ! static void qf_fill_buffer(qf_info_T *qi); #endif static char_u *get_mef_name(void); static void restore_start_dir(char_u *dirname_start); --- 126,134 ---- static int is_qf_win(win_T *win, qf_info_T *qi); static win_T *qf_find_win(qf_info_T *qi); static buf_T *qf_find_buf(qf_info_T *qi); ! static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last); static void qf_set_title_var(qf_info_T *qi); ! static void qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last); #endif static char_u *get_mef_name(void); static void restore_start_dir(char_u *dirname_start); *************** *** 207,213 **** /* * Read the errorfile "efile" into memory, line by line, building the error * list. ! * Alternative: when "efile" is null read errors from buffer "buf". * Always use 'errorformat' from "buf" if there is a local value. * Then "lnumfirst" and "lnumlast" specify the range of lines to use. * Set the title of the list to "qf_title". --- 207,214 ---- /* * Read the errorfile "efile" into memory, line by line, building the error * list. ! * Alternative: when "efile" is NULL read errors from buffer "buf". ! * Alternative: when "tv" is not NULL get errors from the string or list. * Always use 'errorformat' from "buf" if there is a local value. * Then "lnumfirst" and "lnumlast" specify the range of lines to use. * Set the title of the list to "qf_title". *************** *** 245,250 **** --- 246,254 ---- int enr = 0; FILE *fd = NULL; qfline_T *qfprev = NULL; /* init to make SASC shut up */ + #ifdef FEAT_WINDOWS + qfline_T *old_last = NULL; + #endif char_u *efmp; efm_T *fmt_first = NULL; efm_T *fmt_last = NULL; *************** *** 304,313 **** --- 308,320 ---- /* make place for a new list */ qf_new_list(qi, qf_title); else if (qi->qf_lists[qi->qf_curlist].qf_count > 0) + { /* Adding to existing list, find last entry. */ for (qfprev = qi->qf_lists[qi->qf_curlist].qf_start; qfprev->qf_next != qfprev; qfprev = qfprev->qf_next) ; + old_last = qfprev; + } /* * Each part of the format string is copied and modified from errorformat to *************** *** 1051,1057 **** vim_free(growbuf); #ifdef FEAT_WINDOWS ! qf_update_buffer(qi, TRUE); #endif return retval; --- 1058,1064 ---- vim_free(growbuf); #ifdef FEAT_WINDOWS ! qf_update_buffer(qi, old_last); #endif return retval; *************** *** 2347,2353 **** qi->qf_curlist + 1, qi->qf_listcount, qi->qf_lists[qi->qf_curlist].qf_count); #ifdef FEAT_WINDOWS ! qf_update_buffer(qi, TRUE); #endif } --- 2354,2360 ---- qi->qf_curlist + 1, qi->qf_listcount, qi->qf_lists[qi->qf_curlist].qf_count); #ifdef FEAT_WINDOWS ! qf_update_buffer(qi, NULL); #endif } *************** *** 2649,2655 **** /* * Fill the buffer with the quickfix list. */ ! qf_fill_buffer(qi); curwin->w_cursor.lnum = qi->qf_lists[qi->qf_curlist].qf_index; curwin->w_cursor.col = 0; --- 2656,2662 ---- /* * Fill the buffer with the quickfix list. */ ! qf_fill_buffer(qi, curbuf, NULL); curwin->w_cursor.lnum = qi->qf_lists[qi->qf_curlist].qf_index; curwin->w_cursor.col = 0; *************** *** 2777,2783 **** * Find the quickfix buffer. If it exists, update the contents. */ static void ! qf_update_buffer(qf_info_T *qi, int update_cursor) { buf_T *buf; win_T *win; --- 2784,2790 ---- * Find the quickfix buffer. If it exists, update the contents. */ static void ! qf_update_buffer(qf_info_T *qi, qfline_T *old_last) { buf_T *buf; win_T *win; *************** *** 2788,2795 **** buf = qf_find_buf(qi); if (buf != NULL) { ! /* set curwin/curbuf to buf and save a few things */ ! aucmd_prepbuf(&aco, buf); if ((win = qf_find_win(qi)) != NULL) { --- 2795,2805 ---- buf = qf_find_buf(qi); if (buf != NULL) { ! linenr_T old_line_count = buf->b_ml.ml_line_count; ! ! if (old_last == NULL) ! /* set curwin/curbuf to buf and save a few things */ ! aucmd_prepbuf(&aco, buf); if ((win = qf_find_win(qi)) != NULL) { *************** *** 2799,2811 **** curwin = curwin_save; } ! qf_fill_buffer(qi); ! ! /* restore curwin/curbuf and a few other things */ ! aucmd_restbuf(&aco); ! if (update_cursor) (void)qf_win_pos_update(qi, 0); } } --- 2809,2828 ---- curwin = curwin_save; } ! qf_fill_buffer(qi, buf, old_last); ! if (old_last == NULL) ! { (void)qf_win_pos_update(qi, 0); + + /* restore curwin/curbuf and a few other things */ + aucmd_restbuf(&aco); + } + + /* Only redraw when added lines are visible. This avoids flickering + * when the added lines are not visible. */ + if ((win = qf_find_win(qi)) != NULL && old_line_count < win->w_botline) + redraw_buf_later(buf, NOT_VALID); } } *************** *** 2823,2831 **** /* * Fill current buffer with quickfix errors, replacing any previous contents. * curbuf must be the quickfix buffer! */ static void ! qf_fill_buffer(qf_info_T *qi) { linenr_T lnum; qfline_T *qfp; --- 2840,2851 ---- /* * Fill current buffer with quickfix errors, replacing any previous contents. * curbuf must be the quickfix buffer! + * If "old_last" is not NULL append the items after this one. + * When "old_last" is NULL then "buf" must equal "curbuf"! Because + * ml_delete() is used and autocommands will be triggered. */ static void ! qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last) { linenr_T lnum; qfline_T *qfp; *************** *** 2833,2848 **** int len; int old_KeyTyped = KeyTyped; ! /* delete all existing lines */ ! while ((curbuf->b_ml.ml_flags & ML_EMPTY) == 0) ! (void)ml_delete((linenr_T)1, FALSE); /* Check if there is anything to display */ if (qi->qf_curlist < qi->qf_listcount) { /* Add one line for each error */ ! qfp = qi->qf_lists[qi->qf_curlist].qf_start; ! for (lnum = 0; lnum < qi->qf_lists[qi->qf_curlist].qf_count; ++lnum) { if (qfp->qf_fnum != 0 && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL --- 2853,2886 ---- int len; int old_KeyTyped = KeyTyped; ! if (old_last == NULL) ! { ! if (buf != curbuf) ! { ! EMSG2(_(e_intern2), "qf_fill_buffer()"); ! return; ! } ! ! /* delete all existing lines */ ! while ((curbuf->b_ml.ml_flags & ML_EMPTY) == 0) ! (void)ml_delete((linenr_T)1, FALSE); ! } /* Check if there is anything to display */ if (qi->qf_curlist < qi->qf_listcount) { /* Add one line for each error */ ! if (old_last == NULL) ! { ! qfp = qi->qf_lists[qi->qf_curlist].qf_start; ! lnum = 0; ! } ! else ! { ! qfp = old_last->qf_next; ! lnum = buf->b_ml.ml_line_count; ! } ! while (lnum < qi->qf_lists[qi->qf_curlist].qf_count) { if (qfp->qf_fnum != 0 && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL *************** *** 2887,2921 **** qf_fmt_text(len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text, IObuff + len, IOSIZE - len); ! if (ml_append(lnum, IObuff, (colnr_T)STRLEN(IObuff) + 1, FALSE) ! == FAIL) break; qfp = qfp->qf_next; } ! /* Delete the empty line which is now at the end */ ! (void)ml_delete(lnum + 1, FALSE); } /* correct cursor position */ check_lnums(TRUE); ! /* Set the 'filetype' to "qf" each time after filling the buffer. This ! * resembles reading a file into a buffer, it's more logical when using ! * autocommands. */ ! set_option_value((char_u *)"ft", 0L, (char_u *)"qf", OPT_LOCAL); ! curbuf->b_p_ma = FALSE; #ifdef FEAT_AUTOCMD ! keep_filetype = TRUE; /* don't detect 'filetype' */ ! apply_autocmds(EVENT_BUFREADPOST, (char_u *)"quickfix", NULL, FALSE, curbuf); ! apply_autocmds(EVENT_BUFWINENTER, (char_u *)"quickfix", NULL, FALSE, curbuf); ! keep_filetype = FALSE; #endif ! ! /* make sure it will be redrawn */ ! redraw_curbuf_later(NOT_VALID); /* Restore KeyTyped, setting 'filetype' may reset it. */ KeyTyped = old_KeyTyped; --- 2925,2964 ---- qf_fmt_text(len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text, IObuff + len, IOSIZE - len); ! if (ml_append_buf(buf, lnum, IObuff, ! (colnr_T)STRLEN(IObuff) + 1, FALSE) == FAIL) break; + ++lnum; qfp = qfp->qf_next; } ! ! if (old_last == NULL) ! /* Delete the empty line which is now at the end */ ! (void)ml_delete(lnum + 1, FALSE); } /* correct cursor position */ check_lnums(TRUE); ! if (old_last == NULL) ! { ! /* Set the 'filetype' to "qf" each time after filling the buffer. ! * This resembles reading a file into a buffer, it's more logical when ! * using autocommands. */ ! set_option_value((char_u *)"ft", 0L, (char_u *)"qf", OPT_LOCAL); ! curbuf->b_p_ma = FALSE; #ifdef FEAT_AUTOCMD ! keep_filetype = TRUE; /* don't detect 'filetype' */ ! apply_autocmds(EVENT_BUFREADPOST, (char_u *)"quickfix", NULL, FALSE, curbuf); ! apply_autocmds(EVENT_BUFWINENTER, (char_u *)"quickfix", NULL, FALSE, curbuf); ! keep_filetype = FALSE; #endif ! /* make sure it will be redrawn */ ! redraw_curbuf_later(NOT_VALID); ! } /* Restore KeyTyped, setting 'filetype' may reset it. */ KeyTyped = old_KeyTyped; *************** *** 3847,3853 **** qi->qf_lists[qi->qf_curlist].qf_index = 1; #ifdef FEAT_WINDOWS ! qf_update_buffer(qi, TRUE); #endif #ifdef FEAT_AUTOCMD --- 3890,3896 ---- qi->qf_lists[qi->qf_curlist].qf_index = 1; #ifdef FEAT_WINDOWS ! qf_update_buffer(qi, NULL); #endif #ifdef FEAT_AUTOCMD *************** *** 4176,4182 **** /* * Populate the quickfix list with the items supplied in the list ! * of dictionaries. "title" will be copied to w:quickfix_title */ int set_errorlist( --- 4219,4226 ---- /* * Populate the quickfix list with the items supplied in the list ! * of dictionaries. "title" will be copied to w:quickfix_title. ! * "action" is 'a' for add, 'r' for replace. Otherwise create a new list. */ int set_errorlist( *************** *** 4193,4198 **** --- 4237,4245 ---- int col, nr; int vcol; qfline_T *prevp = NULL; + #ifdef FEAT_WINDOWS + qfline_T *old_last = NULL; + #endif int valid, status; int retval = OK; qf_info_T *qi = &ql_info; *************** *** 4209,4218 **** --- 4256,4270 ---- /* make place for a new list */ qf_new_list(qi, title); else if (action == 'a' && qi->qf_lists[qi->qf_curlist].qf_count > 0) + { /* Adding to existing list, find last entry. */ for (prevp = qi->qf_lists[qi->qf_curlist].qf_start; prevp->qf_next != prevp; prevp = prevp->qf_next) ; + #ifdef FEAT_WINDOWS + old_last = prevp; + #endif + } else if (action == 'r') { qf_free(qi, qi->qf_curlist); *************** *** 4296,4302 **** #ifdef FEAT_WINDOWS /* Don't update the cursor in quickfix window when appending entries */ ! qf_update_buffer(qi, (action != 'a')); #endif return retval; --- 4348,4354 ---- #ifdef FEAT_WINDOWS /* Don't update the cursor in quickfix window when appending entries */ ! qf_update_buffer(qi, old_last); #endif return retval; *************** *** 4603,4609 **** free_string_option(save_cpo); #ifdef FEAT_WINDOWS ! qf_update_buffer(qi, TRUE); #endif #ifdef FEAT_AUTOCMD --- 4655,4661 ---- free_string_option(save_cpo); #ifdef FEAT_WINDOWS ! qf_update_buffer(qi, NULL); #endif #ifdef FEAT_AUTOCMD *** ../vim-7.4.1870/src/version.c 2016-06-02 11:57:33.856786831 +0200 --- src/version.c 2016-06-02 13:24:13.044715312 +0200 *************** *** 755,756 **** --- 755,758 ---- { /* Add new patch number below this line */ + /**/ + 1871, /**/ -- To define recursion, we must first define recursion. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///