1
0
forked from aniani/vim

patch 8.2.0959: using 'quickfixtextfunc' is a bit slow

Problem:    Using 'quickfixtextfunc' is a bit slow.
Solution:   Process a list of entries. (Yegappan Lakshmanan, closes #6234)
This commit is contained in:
Bram Moolenaar 2020-06-11 19:35:52 +02:00
parent 1de5f7c81d
commit 00e260bb6c
4 changed files with 112 additions and 68 deletions

View File

@ -1947,9 +1947,9 @@ under the current directory tree. The file path may need to be simplified to a
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:
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.
@ -1957,12 +1957,14 @@ following fields:
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
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 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".
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
@ -1977,11 +1979,14 @@ Example: >
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:.')
" 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
<

View File

@ -4415,49 +4415,17 @@ qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
*/
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)
char_u *qftf_str)
{
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);
}
if (qftf_str != NULL)
vim_strncpy(IObuff, qftf_str, IOSIZE - 1);
else
{
if (qfp->qf_module != NULL)
@ -4533,6 +4501,41 @@ qf_buf_add_line(
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,6 +4549,8 @@ qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int qf_winid)
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,15 +4583,30 @@ qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int qf_winid)
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)
{
if (qf_buf_add_line(qfl, buf, lnum, qfp, dirname, qf_winid) == FAIL)
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)

View File

@ -4818,24 +4818,26 @@ endfunc
" 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
let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
else
let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'idx' : a:info.idx,
\ 'items' : 1}).items
let qfl = getloclist(a:info.winid, {'id' : a:info.id, '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
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 s
return l
endfunc
func Xtest_qftextfunc(cchar)
@ -4859,16 +4861,18 @@ func Xtest_qftextfunc(cchar)
" 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
let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
else
let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'idx' : a:info.idx,
\ 'items' : 1}).items
let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
endif
if empty(qfl)
return ''
return []
endif
return 'Line ' .. qfl[0].lnum .. ', Col ' .. qfl[0].col
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,8 +4912,21 @@ func Xtest_qftextfunc(cchar)
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()

View File

@ -754,6 +754,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
959,
/**/
958,
/**/