mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
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 vim/vim#6234)
00e260bb6c
This commit is contained in:
parent
00246d7be5
commit
19d4926f5a
@ -1909,9 +1909,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.
|
||||||
@ -1919,12 +1919,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
|
||||||
@ -1939,11 +1941,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
|
||||||
<
|
<
|
||||||
|
|
||||||
|
@ -3924,44 +3924,15 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
|
|||||||
|
|
||||||
// Add an error line to the quickfix buffer.
|
// Add an error line to the quickfix buffer.
|
||||||
static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum,
|
static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum,
|
||||||
const qfline_T *qfp,
|
const qfline_T *qfp, char_u *dirname,
|
||||||
char_u *dirname, int qf_winid, bool first_bufline)
|
char_u *qftf_str, bool first_bufline)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ARG(1, 2, 4, 5)
|
||||||
{
|
{
|
||||||
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
|
STRLCPY(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];
|
|
||||||
|
|
||||||
// create the dict argument
|
|
||||||
dict_T *const dict = tv_dict_alloc_lock(VAR_FIXED);
|
|
||||||
|
|
||||||
tv_dict_add_nr(dict, S_LEN("quickfix"), IS_QF_LIST(qfl));
|
|
||||||
tv_dict_add_nr(dict, S_LEN("winid"), qf_winid);
|
|
||||||
tv_dict_add_nr(dict, S_LEN("id"), qfl->qf_id);
|
|
||||||
tv_dict_add_nr(dict, S_LEN("idx"), lnum + 1);
|
|
||||||
dict->dv_refcount++;
|
|
||||||
args[0].v_type = VAR_DICT;
|
|
||||||
args[0].vval.v_dict = dict;
|
|
||||||
|
|
||||||
qfbuf_text = (char_u *)call_func_retstr((const char *const)qftf, 1, args);
|
|
||||||
dict->dv_refcount--;
|
|
||||||
|
|
||||||
if (qfbuf_text == NULL) {
|
|
||||||
return FAIL;
|
|
||||||
}
|
|
||||||
STRLCPY(IObuff, qfbuf_text, IOSIZE - 1);
|
|
||||||
xfree(qfbuf_text);
|
|
||||||
} else {
|
} else {
|
||||||
if (qfp->qf_module != NULL) {
|
if (qfp->qf_module != NULL) {
|
||||||
STRLCPY(IObuff, qfp->qf_module, IOSIZE - 1);
|
STRLCPY(IObuff, qfp->qf_module, IOSIZE - 1);
|
||||||
@ -4029,6 +4000,42 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum,
|
|||||||
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];
|
||||||
|
|
||||||
|
// create the dict argument
|
||||||
|
dict_T *const dict = tv_dict_alloc_lock(VAR_FIXED);
|
||||||
|
|
||||||
|
tv_dict_add_nr(dict, S_LEN("quickfix"), IS_QF_LIST(qfl));
|
||||||
|
tv_dict_add_nr(dict, S_LEN("winid"), qf_winid);
|
||||||
|
tv_dict_add_nr(dict, S_LEN("id"), qfl->qf_id);
|
||||||
|
tv_dict_add_nr(dict, S_LEN("start_idx"), start_idx);
|
||||||
|
tv_dict_add_nr(dict, S_LEN("end_idx"), end_idx);
|
||||||
|
dict->dv_refcount++;
|
||||||
|
args[0].v_type = VAR_DICT;
|
||||||
|
args[0].vval.v_dict = dict;
|
||||||
|
|
||||||
|
qftf_list = call_func_retlist(qftf, 1, args);
|
||||||
|
dict->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!
|
||||||
/// If "old_last" is not NULL append the items after this one.
|
/// If "old_last" is not NULL append the items after this one.
|
||||||
@ -4041,6 +4048,8 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last,
|
|||||||
linenr_T lnum;
|
linenr_T lnum;
|
||||||
qfline_T *qfp;
|
qfline_T *qfp;
|
||||||
const bool old_KeyTyped = KeyTyped;
|
const bool old_KeyTyped = KeyTyped;
|
||||||
|
list_T *qftf_list = NULL;
|
||||||
|
listitem_T *qftf_li = NULL;
|
||||||
|
|
||||||
if (old_last == NULL) {
|
if (old_last == NULL) {
|
||||||
if (buf != curbuf) {
|
if (buf != curbuf) {
|
||||||
@ -4073,8 +4082,19 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last,
|
|||||||
}
|
}
|
||||||
lnum = buf->b_ml.ml_line_count;
|
lnum = buf->b_ml.ml_line_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qftf_list = call_qftf_func(qfl, qf_winid, lnum + 1, (long)qfl->qf_count);
|
||||||
|
qftf_li = tv_list_first(qftf_list);
|
||||||
|
|
||||||
while (lnum < qfl->qf_count) {
|
while (lnum < qfl->qf_count) {
|
||||||
if (qf_buf_add_line(qfl, buf, lnum, qfp, dirname, qf_winid,
|
char_u *qftf_str = NULL;
|
||||||
|
|
||||||
|
if (qftf_li != NULL) {
|
||||||
|
// Use the text supplied by the user defined function
|
||||||
|
qftf_str = (char_u *)tv_get_string_chk(TV_LIST_ITEM_TV(qftf_li));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qf_buf_add_line(qfl, buf, lnum, qfp, dirname, qftf_str,
|
||||||
prev_bufnr != qfp->qf_fnum) == FAIL) {
|
prev_bufnr != qfp->qf_fnum) == FAIL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -4084,6 +4104,10 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last,
|
|||||||
if (qfp == NULL) {
|
if (qfp == NULL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qftf_li != NULL) {
|
||||||
|
qftf_li = TV_LIST_ITEM_NEXT(qftf_list, qftf_li);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (old_last == NULL) {
|
if (old_last == NULL) {
|
||||||
// Delete the empty line which is now at the end
|
// Delete the empty line which is now at the end
|
||||||
|
@ -4809,24 +4809,27 @@ 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 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
|
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
|
endfunc
|
||||||
|
|
||||||
func Xtest_qftextfunc(cchar)
|
func Xtest_qftextfunc(cchar)
|
||||||
@ -4850,16 +4853,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"})
|
||||||
@ -4902,8 +4907,22 @@ func Xtest_qftextfunc(cchar)
|
|||||||
Xexpr ['F1:10:2:green', 'F1:20:4:blue']"
|
Xexpr ['F1:10:2:green', 'F1:20:4:blue']"
|
||||||
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:')
|
||||||
|
Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']
|
||||||
|
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()
|
||||||
|
Loading…
Reference in New Issue
Block a user