0
0
mirror of https://github.com/vim/vim.git synced 2025-08-25 19:53:53 -04:00

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. common parent directory.
The displayed text can be customized by setting the 'quickfixtextfunc' option 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 to a Vim function. This function will be called with a dict argument and
every entry in a quickfix or a location list. The dict argument will have the should return a List of strings to be displayed in the quickfix or location
following fields: 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 quickfix set to 1 when called for a quickfix list and 0 when called for
a location list. a location list.
@ -1957,12 +1957,14 @@ following fields:
location list. For a quickfix list, set to 0. Can be used in location list. For a quickfix list, set to 0. Can be used in
getloclist() to get the location list entry. getloclist() to get the location list entry.
id quickfix or location list identifier 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 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 window for each entry from start_idx to end_idx. The function can obtain
about the current entry using the |getqflist()| function and specifying the information about the entries using the |getqflist()| function and specifying
quickfix list identifier "id" and the entry index "idx". 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 If a quickfix or location list specific customization is needed, then the
'quickfixtextfunc' attribute of the list can be set using the |setqflist()| or 'quickfixtextfunc' attribute of the list can be set using the |setqflist()| or
@ -1977,11 +1979,14 @@ Example: >
call setqflist([], ' ', {'lines' : v:oldfiles, 'efm' : '%f', call setqflist([], ' ', {'lines' : v:oldfiles, 'efm' : '%f',
\ 'quickfixtextfunc' : 'QfOldFiles'}) \ 'quickfixtextfunc' : 'QfOldFiles'})
func QfOldFiles(info) func QfOldFiles(info)
" get information about the specific quickfix entry " get information about a range of quickfix entries
let e = getqflist({'id' : a:info.id, 'idx' : a:info.idx, let items = getqflist({'id' : a:info.id, 'items' : 1}).items
\ 'items' : 1}).items[0] let l = []
" return the simplified file name for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
return fnamemodify(bufname(e.bufnr), ':p:.') " use the simplified file name
call add(l, fnamemodify(bufname(items[idx].bufnr), ':p:.'))
endfor
return l
endfunc endfunc
< <

View File

@ -4415,49 +4415,17 @@ qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
*/ */
static int static int
qf_buf_add_line( qf_buf_add_line(
qf_list_T *qfl, // quickfix list
buf_T *buf, // quickfix window buffer buf_T *buf, // quickfix window buffer
linenr_T lnum, linenr_T lnum,
qfline_T *qfp, qfline_T *qfp,
char_u *dirname, char_u *dirname,
int qf_winid) char_u *qftf_str)
{ {
int len; int len;
buf_T *errbuf; buf_T *errbuf;
char_u *qftf;
// If 'quickfixtextfunc' is set, then use the user-supplied function to get if (qftf_str != NULL)
// the text to display vim_strncpy(IObuff, qftf_str, IOSIZE - 1);
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 else
{ {
if (qfp->qf_module != NULL) if (qfp->qf_module != NULL)
@ -4533,6 +4501,41 @@ qf_buf_add_line(
return OK; 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. * Fill current buffer with quickfix errors, replacing any previous contents.
* curbuf must be the quickfix buffer! * 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; linenr_T lnum;
qfline_T *qfp; qfline_T *qfp;
int old_KeyTyped = KeyTyped; int old_KeyTyped = KeyTyped;
list_T *qftf_list = NULL;
listitem_T *qftf_li = NULL;
if (old_last == 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; qfp = old_last->qf_next;
lnum = buf->b_ml.ml_line_count; 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) 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; break;
++lnum; ++lnum;
qfp = qfp->qf_next; qfp = qfp->qf_next;
if (qfp == NULL) if (qfp == NULL)
break; break;
if (qftf_li != NULL)
qftf_li = qftf_li->li_next;
} }
if (old_last == NULL) if (old_last == NULL)

View File

@ -4818,24 +4818,26 @@ endfunc
" Test for the 'quickfixtextfunc' setting " Test for the 'quickfixtextfunc' setting
func Tqfexpr(info) func Tqfexpr(info)
if a:info.quickfix if a:info.quickfix
let qfl = getqflist({'id' : a:info.id, 'idx' : a:info.idx, let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
\ 'items' : 1}).items
else else
let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'idx' : a:info.idx, let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
\ 'items' : 1}).items
endif endif
let e = qfl[0] let l = []
let s = '' for idx in range(a:info.start_idx - 1, a:info.end_idx - 1)
if e.bufnr != 0 let e = qfl[idx]
let bname = bufname(e.bufnr) let s = ''
let s ..= fnamemodify(bname, ':.') if e.bufnr != 0
endif let bname = bufname(e.bufnr)
let s ..= '-' let s ..= fnamemodify(bname, ':.')
let s ..= 'L' .. string(e.lnum) .. 'C' .. string(e.col) .. '-' endif
let s ..= e.text 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 endfunc
func Xtest_qftextfunc(cchar) func Xtest_qftextfunc(cchar)
@ -4859,16 +4861,18 @@ func Xtest_qftextfunc(cchar)
" Test for per list 'quickfixtextfunc' setting " Test for per list 'quickfixtextfunc' setting
func PerQfText(info) func PerQfText(info)
if a:info.quickfix if a:info.quickfix
let qfl = getqflist({'id' : a:info.id, 'idx' : a:info.idx, let qfl = getqflist({'id' : a:info.id, 'items' : 1}).items
\ 'items' : 1}).items
else else
let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'idx' : a:info.idx, let qfl = getloclist(a:info.winid, {'id' : a:info.id, 'items' : 1}).items
\ 'items' : 1}).items
endif endif
if empty(qfl) if empty(qfl)
return '' return []
endif 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 endfunc
set quickfixtextfunc=Tqfexpr set quickfixtextfunc=Tqfexpr
call g:Xsetlist([], ' ', {'quickfixtextfunc' : "PerQfText"}) 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("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
call assert_fails("Xwindow", 'E119:') call assert_fails("Xwindow", 'E119:')
Xclose 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& set quickfixtextfunc&
delfunc Xqftext delfunc Xqftext
delfunc Xqftext2
endfunc endfunc
func Test_qftextfunc() func Test_qftextfunc()

View File

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