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 -- Br...@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 ///