Patch 8.2.0959
Problem:    Using 'quickfixtextfunc' is a bit slow.
Solution:   Process a list of entries. (Yegappan Lakshmanan, closes #6234)
Files:      runtime/doc/quickfix.txt, src/quickfix.c,
            src/testdir/test_quickfix.vim


*** ../vim-8.2.0958/runtime/doc/quickfix.txt    2020-06-08 19:20:21.703831100 
+0200
--- runtime/doc/quickfix.txt    2020-06-11 19:33:26.097919533 +0200
***************
*** 1948,1956 ****
  common parent directory.
  
  The displayed text can be customized by setting the 'quickfixtextfunc' option
! to a Vim function.  This function will be called with a dict argument for
! every entry in a quickfix or a location list. The dict argument will have the
! following fields:
  
      quickfix  set to 1 when called for a quickfix list and 0 when called for
                a location list.
--- 1947,1955 ----
  common parent directory.
  
  The displayed text can be customized by setting the 'quickfixtextfunc' option
! to a Vim function.  This function will be called with a dict argument and
! should return a List of strings to be displayed in the quickfix or location
! list window. The dict argument will have the following fields:
  
      quickfix  set to 1 when called for a quickfix list and 0 when called for
                a location list.
***************
*** 1958,1969 ****
                location list. For a quickfix list, set to 0. Can be used in
                getloclist() to get the location list entry.
      id                quickfix or location list identifier
!     idx               index of the entry in the quickfix or location list
  
  The function should return a single line of text to display in the quickfix
! window for the entry identified by idx. The function can obtain information
! about the current entry using the |getqflist()| function and specifying the
! quickfix list identifier "id" and the entry index "idx".
  
  If a quickfix or location list specific customization is needed, then the
  'quickfixtextfunc' attribute of the list can be set using the |setqflist()| or
--- 1957,1970 ----
                location list. For a quickfix list, set to 0. Can be used in
                getloclist() to get the location list entry.
      id                quickfix or location list identifier
!     start_idx index of the first entry for which text should be returned
!     end_idx   index of the last entry for which text should be returned
  
  The function should return a single line of text to display in the quickfix
! window for each entry from start_idx to end_idx. The function can obtain
! information about the entries using the |getqflist()| function and specifying
! the quickfix list identifier "id". For a location list, getloclist() function
! can be used with the 'winid' argument.
  
  If a quickfix or location list specific customization is needed, then the
  'quickfixtextfunc' attribute of the list can be set using the |setqflist()| or
***************
*** 1978,1988 ****
      call setqflist([], ' ', {'lines' : v:oldfiles, 'efm' : '%f',
                                        \ 'quickfixtextfunc' : 'QfOldFiles'})
      func QfOldFiles(info)
!       " get information about the specific quickfix entry
!       let e = getqflist({'id' : a:info.id, 'idx' : a:info.idx,
!                                               \ 'items' : 1}).items[0]
!       " return the simplified file name
!       return fnamemodify(bufname(e.bufnr), ':p:.')
      endfunc
  <
  
--- 1979,1992 ----
      call setqflist([], ' ', {'lines' : v:oldfiles, 'efm' : '%f',
                                        \ 'quickfixtextfunc' : 'QfOldFiles'})
      func QfOldFiles(info)
!       " get information about a range of quickfix entries
!       let items = getqflist({'id' : a:info.id, 'items' : 1}).items
!       let l = []
!       for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
!           " use the simplified file name
!         call add(l, fnamemodify(bufname(items[idx].bufnr), ':p:.'))
!       endfor
!       return l
      endfunc
  <
  
*** ../vim-8.2.0958/src/quickfix.c      2020-06-08 19:35:55.781319897 +0200
--- src/quickfix.c      2020-06-11 19:33:26.097919533 +0200
***************
*** 4415,4463 ****
   */
      static int
  qf_buf_add_line(
-       qf_list_T       *qfl,           // quickfix list
        buf_T           *buf,           // quickfix window buffer
        linenr_T        lnum,
        qfline_T        *qfp,
        char_u          *dirname,
!       int             qf_winid)
  {
      int               len;
      buf_T     *errbuf;
-     char_u    *qftf;
  
!     // If 'quickfixtextfunc' is set, then use the user-supplied function to 
get
!     // the text to display
!     qftf = p_qftf;
!     // Use the local value of 'quickfixtextfunc' if it is set.
!     if (qfl->qf_qftf != NULL)
!       qftf = qfl->qf_qftf;
!     if (qftf != NULL && *qftf != NUL)
!     {
!       char_u          *qfbuf_text;
!       typval_T        args[1];
!       dict_T          *d;
! 
!       // create the dict argument
!       if ((d = dict_alloc_lock(VAR_FIXED)) == NULL)
!           return FAIL;
!       dict_add_number(d, "quickfix", (long)IS_QF_LIST(qfl));
!       dict_add_number(d, "winid", (long)qf_winid);
!       dict_add_number(d, "id", (long)qfl->qf_id);
!       dict_add_number(d, "idx", (long)(lnum + 1));
!       ++d->dv_refcount;
!       args[0].v_type = VAR_DICT;
!       args[0].vval.v_dict = d;
! 
!       qfbuf_text = call_func_retstr(qftf, 1, args);
!       --d->dv_refcount;
! 
!       if (qfbuf_text == NULL)
!           return FAIL;
! 
!       vim_strncpy(IObuff, qfbuf_text, IOSIZE - 1);
!       vim_free(qfbuf_text);
!     }
      else
      {
        if (qfp->qf_module != NULL)
--- 4415,4431 ----
   */
      static int
  qf_buf_add_line(
        buf_T           *buf,           // quickfix window buffer
        linenr_T        lnum,
        qfline_T        *qfp,
        char_u          *dirname,
!       char_u          *qftf_str)
  {
      int               len;
      buf_T     *errbuf;
  
!     if (qftf_str != NULL)
!       vim_strncpy(IObuff, qftf_str, IOSIZE - 1);
      else
      {
        if (qfp->qf_module != NULL)
***************
*** 4533,4538 ****
--- 4501,4541 ----
      return OK;
  }
  
+     static list_T *
+ call_qftf_func(qf_list_T *qfl, int qf_winid, long start_idx, long end_idx)
+ {
+     char_u    *qftf = p_qftf;
+     list_T    *qftf_list = NULL;
+ 
+     // If 'quickfixtextfunc' is set, then use the user-supplied function to 
get
+     // the text to display. Use the local value of 'quickfixtextfunc' if it is
+     // set.
+     if (qfl->qf_qftf != NULL)
+       qftf = qfl->qf_qftf;
+     if (qftf != NULL && *qftf != NUL)
+     {
+       typval_T        args[1];
+       dict_T          *d;
+ 
+       // create the dict argument
+       if ((d = dict_alloc_lock(VAR_FIXED)) == NULL)
+           return NULL;
+       dict_add_number(d, "quickfix", (long)IS_QF_LIST(qfl));
+       dict_add_number(d, "winid", (long)qf_winid);
+       dict_add_number(d, "id", (long)qfl->qf_id);
+       dict_add_number(d, "start_idx", start_idx);
+       dict_add_number(d, "end_idx", end_idx);
+       ++d->dv_refcount;
+       args[0].v_type = VAR_DICT;
+       args[0].vval.v_dict = d;
+ 
+       qftf_list = call_func_retlist(qftf, 1, args);
+       --d->dv_refcount;
+     }
+ 
+     return qftf_list;
+ }
+ 
  /*
   * Fill current buffer with quickfix errors, replacing any previous contents.
   * curbuf must be the quickfix buffer!
***************
*** 4546,4551 ****
--- 4549,4556 ----
      linenr_T  lnum;
      qfline_T  *qfp;
      int               old_KeyTyped = KeyTyped;
+     list_T    *qftf_list = NULL;
+     listitem_T        *qftf_li = NULL;
  
      if (old_last == NULL)
      {
***************
*** 4578,4592 ****
            qfp = old_last->qf_next;
            lnum = buf->b_ml.ml_line_count;
        }
        while (lnum < qfl->qf_count)
        {
!           if (qf_buf_add_line(qfl, buf, lnum, qfp, dirname, qf_winid) == FAIL)
                break;
  
            ++lnum;
            qfp = qfp->qf_next;
            if (qfp == NULL)
                break;
        }
  
        if (old_last == NULL)
--- 4583,4612 ----
            qfp = old_last->qf_next;
            lnum = buf->b_ml.ml_line_count;
        }
+ 
+       qftf_list = call_qftf_func(qfl, qf_winid, (long)(lnum + 1),
+                                                       (long)qfl->qf_count);
+       if (qftf_list != NULL)
+           qftf_li = qftf_list->lv_first;
+ 
        while (lnum < qfl->qf_count)
        {
!           char_u      *qftf_str = NULL;
! 
!           if (qftf_li != NULL)
!               // Use the text supplied by the user defined function
!               qftf_str = tv_get_string_chk(&qftf_li->li_tv);
! 
!           if (qf_buf_add_line(buf, lnum, qfp, dirname, qftf_str) == FAIL)
                break;
  
            ++lnum;
            qfp = qfp->qf_next;
            if (qfp == NULL)
                break;
+ 
+           if (qftf_li != NULL)
+               qftf_li = qftf_li->li_next;
        }
  
        if (old_last == NULL)
*** ../vim-8.2.0958/src/testdir/test_quickfix.vim       2020-06-09 
15:57:32.929019414 +0200
--- src/testdir/test_quickfix.vim       2020-06-11 19:33:26.101919513 +0200
***************
*** 4818,4841 ****
  " Test for the 'quickfixtextfunc' setting
  func Tqfexpr(info)
    if a:info.quickfix
!     let qfl = getqflist({'id' : a:info.id, 'idx' : a:info.idx,
!           \ 'items' : 1}).items
    else
!     let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'idx' : a:info.idx,
!           \ 'items' : 1}).items
    endif
  
!   let e = qfl[0]
!   let s = ''
!   if e.bufnr != 0
!     let bname = bufname(e.bufnr)
!     let s ..= fnamemodify(bname, ':.')
!   endif
!   let s ..= '-'
!   let s ..= 'L' .. string(e.lnum) .. 'C' .. string(e.col) .. '-'
!   let s ..= e.text
  
!   return s
  endfunc
  
  func Xtest_qftextfunc(cchar)
--- 4818,4843 ----
  " Test for the 'quickfixtextfunc' setting
  func Tqfexpr(info)
    if a:info.quickfix
!     let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
    else
!     let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
    endif
  
!   let l = []
!   for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
!     let e = qfl[idx]
!     let s = ''
!     if e.bufnr != 0
!       let bname = bufname(e.bufnr)
!       let s ..= fnamemodify(bname, ':.')
!     endif
!     let s ..= '-'
!     let s ..= 'L' .. string(e.lnum) .. 'C' .. string(e.col) .. '-'
!     let s ..= e.text
!     call add(l, s)
!   endfor
  
!   return l
  endfunc
  
  func Xtest_qftextfunc(cchar)
***************
*** 4859,4874 ****
    " Test for per list 'quickfixtextfunc' setting
    func PerQfText(info)
      if a:info.quickfix
!       let qfl = getqflist({'id' : a:info.id, 'idx' : a:info.idx,
!             \ 'items' : 1}).items
      else
!       let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'idx' : 
a:info.idx,
!             \ 'items' : 1}).items
      endif
      if empty(qfl)
!       return ''
      endif
!     return 'Line ' .. qfl[0].lnum .. ', Col ' .. qfl[0].col
    endfunc
    set quickfixtextfunc=Tqfexpr
    call g:Xsetlist([], ' ', {'quickfixtextfunc' : "PerQfText"})
--- 4861,4878 ----
    " Test for per list 'quickfixtextfunc' setting
    func PerQfText(info)
      if a:info.quickfix
!       let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
      else
!       let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 
1}).items
      endif
      if empty(qfl)
!       return []
      endif
!     let l = []
!     for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
!       call add(l, 'Line ' .. qfl[idx].lnum .. ', Col ' .. qfl[idx].col)
!     endfor
!     return l
    endfunc
    set quickfixtextfunc=Tqfexpr
    call g:Xsetlist([], ' ', {'quickfixtextfunc' : "PerQfText"})
***************
*** 4908,4915 ****
--- 4912,4932 ----
    call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
    call assert_fails("Xwindow", 'E119:')
    Xclose
+ 
+   " set option to a function that returns a list with non-strings
+   func Xqftext2(d)
+     return ['one', [], 'two']
+   endfunc
+   set quickfixtextfunc=Xqftext2
+   call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']",
+                                                                   \ 'E730:')
+   call assert_fails('Xwindow', 'E730:')
+   call assert_equal(['one', 'F1|20 col 4| blue', 'two'], getline(1, '$'))
+   Xclose
+ 
    set quickfixtextfunc&
    delfunc Xqftext
+   delfunc Xqftext2
  endfunc
  
  func Test_qftextfunc()
*** ../vim-8.2.0958/src/version.c       2020-06-11 19:22:40.144625523 +0200
--- src/version.c       2020-06-11 19:34:46.625583935 +0200
***************
*** 756,757 ****
--- 756,759 ----
  {   /* Add new patch number below this line */
+ /**/
+     959,
  /**/

-- 
GUARD #2:  It could be carried by an African swallow!
GUARD #1:  Oh, yeah, an African swallow maybe, but not a European swallow,
           that's my point.
GUARD #2:  Oh, yeah, I agree with that...
                                  The Quest for the Holy Grail (Monty Python)

 /// Bram Moolenaar -- [email protected] -- 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    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202006111736.05BHaS9K113592%40masaka.moolenaar.net.

Raspunde prin e-mail lui