]> granicus.if.org Git - vim/commitdiff
patch 7.4.1871 v7.4.1871
authorBram Moolenaar <Bram@vim.org>
Thu, 2 Jun 2016 11:40:04 +0000 (13:40 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 2 Jun 2016 11:40:04 +0000 (13:40 +0200)
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)

src/quickfix.c
src/version.c

index a719e4fe0a75b446ed6f5e4c5de1ae8146817dba..905173d5cd2123e82cf8e75e7d3f4fc56fd2c3a5 100644 (file)
@@ -126,9 +126,9 @@ static int  qf_win_pos_update(qf_info_T *qi, int old_qf_index);
 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_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);
+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,7 +207,8 @@ qf_grow_linebuf(char_u **growbuf, int *growbufsiz, int newsz, int *allocsz)
 /*
  * 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 "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,6 +246,9 @@ qf_init_ext(
     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,10 +308,13 @@ qf_init_ext(
        /* 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,7 +1058,7 @@ qf_init_end:
     vim_free(growbuf);
 
 #ifdef FEAT_WINDOWS
-    qf_update_buffer(qi, TRUE);
+    qf_update_buffer(qi, old_last);
 #endif
 
     return retval;
@@ -2347,7 +2354,7 @@ qf_msg(qf_info_T *qi)
            qi->qf_curlist + 1, qi->qf_listcount,
            qi->qf_lists[qi->qf_curlist].qf_count);
 #ifdef FEAT_WINDOWS
-    qf_update_buffer(qi, TRUE);
+    qf_update_buffer(qi, NULL);
 #endif
 }
 
@@ -2649,7 +2656,7 @@ ex_copen(exarg_T *eap)
     /*
      * Fill the buffer with the quickfix list.
      */
-    qf_fill_buffer(qi);
+    qf_fill_buffer(qi, curbuf, NULL);
 
     curwin->w_cursor.lnum = qi->qf_lists[qi->qf_curlist].qf_index;
     curwin->w_cursor.col = 0;
@@ -2777,7 +2784,7 @@ qf_find_buf(qf_info_T *qi)
  * Find the quickfix buffer.  If it exists, update the contents.
  */
     static void
-qf_update_buffer(qf_info_T *qi, int update_cursor)
+qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
 {
     buf_T      *buf;
     win_T      *win;
@@ -2788,8 +2795,11 @@ qf_update_buffer(qf_info_T *qi, int update_cursor)
     buf = qf_find_buf(qi);
     if (buf != NULL)
     {
-       /* set curwin/curbuf to buf and save a few things */
-       aucmd_prepbuf(&aco, buf);
+       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,13 +2809,20 @@ qf_update_buffer(qf_info_T *qi, int update_cursor)
            curwin = curwin_save;
        }
 
-       qf_fill_buffer(qi);
-
-       /* restore curwin/curbuf and a few other things */
-       aucmd_restbuf(&aco);
+       qf_fill_buffer(qi, buf, old_last);
 
-       if (update_cursor)
+       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,9 +2840,12 @@ qf_set_title_var(qf_info_T *qi)
 /*
  * 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)
+qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last)
 {
     linenr_T   lnum;
     qfline_T   *qfp;
@@ -2833,16 +2853,34 @@ qf_fill_buffer(qf_info_T *qi)
     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);
+    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 */
-       qfp = qi->qf_lists[qi->qf_curlist].qf_start;
-       for (lnum = 0; lnum < qi->qf_lists[qi->qf_curlist].qf_count; ++lnum)
+       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,35 +2925,40 @@ qf_fill_buffer(qf_info_T *qi)
            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)
+           if (ml_append_buf(buf, lnum, IObuff,
+                                 (colnr_T)STRLEN(IObuff) + 1, FALSE) == FAIL)
                break;
+           ++lnum;
            qfp = qfp->qf_next;
        }
-       /* Delete the empty line which is now at the end */
-       (void)ml_delete(lnum + 1, FALSE);
+
+       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);
 
-    /* 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;
+    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,
+       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,
+       apply_autocmds(EVENT_BUFWINENTER, (char_u *)"quickfix", NULL,
                                                               FALSE, curbuf);
-    keep_filetype = FALSE;
+       keep_filetype = FALSE;
 #endif
-
-    /* make sure it will be redrawn */
-    redraw_curbuf_later(NOT_VALID);
+       /* make sure it will be redrawn */
+       redraw_curbuf_later(NOT_VALID);
+    }
 
     /* Restore KeyTyped, setting 'filetype' may reset it. */
     KeyTyped = old_KeyTyped;
@@ -3847,7 +3890,7 @@ ex_vimgrep(exarg_T *eap)
     qi->qf_lists[qi->qf_curlist].qf_index = 1;
 
 #ifdef FEAT_WINDOWS
-    qf_update_buffer(qi, TRUE);
+    qf_update_buffer(qi, NULL);
 #endif
 
 #ifdef FEAT_AUTOCMD
@@ -4176,7 +4219,8 @@ get_errorlist(win_T *wp, list_T *list)
 
 /*
  * Populate the quickfix list with the items supplied in the list
- * of dictionaries. "title" will be copied to w:quickfix_title
+ * 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,6 +4237,9 @@ set_errorlist(
     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,10 +4256,15 @@ set_errorlist(
        /* 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,7 +4348,7 @@ set_errorlist(
 
 #ifdef FEAT_WINDOWS
     /* Don't update the cursor in quickfix window when appending entries */
-    qf_update_buffer(qi, (action != 'a'));
+    qf_update_buffer(qi, old_last);
 #endif
 
     return retval;
@@ -4603,7 +4655,7 @@ ex_helpgrep(exarg_T *eap)
        free_string_option(save_cpo);
 
 #ifdef FEAT_WINDOWS
-    qf_update_buffer(qi, TRUE);
+    qf_update_buffer(qi, NULL);
 #endif
 
 #ifdef FEAT_AUTOCMD
index a7af56616208accc45e81c41d37d22db2eaa4f72..3340537ba5e2190df935c28d69b401bf97ba7aba 100644 (file)
@@ -753,6 +753,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1871,
 /**/
     1870,
 /**/