mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #14490 from kevinhwang91/qftf
vim-patch: 8.2.{0869,0933,0959} - port quickfixtextfunc
This commit is contained in:
commit
713eaaed06
@ -4773,8 +4773,9 @@ getqflist([{what}]) *getqflist()*
|
|||||||
id get information for the quickfix list with
|
id get information for the quickfix list with
|
||||||
|quickfix-ID|; zero means the id for the
|
|quickfix-ID|; zero means the id for the
|
||||||
current list or the list specified by "nr"
|
current list or the list specified by "nr"
|
||||||
idx index of the current entry in the quickfix
|
idx get information for the quickfix entry at this
|
||||||
list specified by 'id' or 'nr'.
|
index in the list specified by 'id' or 'nr'.
|
||||||
|
If set to zero, then uses the current entry.
|
||||||
See |quickfix-index|
|
See |quickfix-index|
|
||||||
items quickfix list entries
|
items quickfix list entries
|
||||||
lines parse a list of lines using 'efm' and return
|
lines parse a list of lines using 'efm' and return
|
||||||
@ -4807,7 +4808,7 @@ getqflist([{what}]) *getqflist()*
|
|||||||
If not present, set to "".
|
If not present, set to "".
|
||||||
id quickfix list ID |quickfix-ID|. If not
|
id quickfix list ID |quickfix-ID|. If not
|
||||||
present, set to 0.
|
present, set to 0.
|
||||||
idx index of the current entry in the list. If not
|
idx index of the quickfix entry in the list. If not
|
||||||
present, set to 0.
|
present, set to 0.
|
||||||
items quickfix list entries. If not present, set to
|
items quickfix list entries. If not present, set to
|
||||||
an empty list.
|
an empty list.
|
||||||
@ -7874,6 +7875,11 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()*
|
|||||||
nr list number in the quickfix stack; zero
|
nr list number in the quickfix stack; zero
|
||||||
means the current quickfix list and "$" means
|
means the current quickfix list and "$" means
|
||||||
the last quickfix list.
|
the last quickfix list.
|
||||||
|
quickfixtextfunc
|
||||||
|
function to get the text to display in the
|
||||||
|
quickfix window. Refer to
|
||||||
|
|quickfix-window-function| for an explanation
|
||||||
|
of how to write the function and an example.
|
||||||
title quickfix list title text. See |quickfix-title|
|
title quickfix list title text. See |quickfix-title|
|
||||||
Unsupported keys in {what} are ignored.
|
Unsupported keys in {what} are ignored.
|
||||||
If the "nr" item is not present, then the current quickfix list
|
If the "nr" item is not present, then the current quickfix list
|
||||||
|
@ -4600,6 +4600,19 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
'pyxversion' has no effect. The pyx* functions and commands are
|
'pyxversion' has no effect. The pyx* functions and commands are
|
||||||
always the same as the installed version.
|
always the same as the installed version.
|
||||||
|
|
||||||
|
This option cannot be set from a |modeline| or in the |sandbox|, for
|
||||||
|
security reasons.
|
||||||
|
|
||||||
|
*'quickfixtextfunc'* *'qftf'*
|
||||||
|
'quickfixtextfunc' 'qftf' string (default "")
|
||||||
|
global
|
||||||
|
This option specifies a function to be used to get the text to display
|
||||||
|
in the quickfix and location list windows. This can be used to
|
||||||
|
customize the information displayed in the quickfix or location window
|
||||||
|
for each entry in the corresponding quickfix or location list. See
|
||||||
|
|quickfix-window-function| for an explanation of how to write the
|
||||||
|
function and an example.
|
||||||
|
|
||||||
This option cannot be set from a |modeline| or in the |sandbox|, for
|
This option cannot be set from a |modeline| or in the |sandbox|, for
|
||||||
security reasons.
|
security reasons.
|
||||||
|
|
||||||
|
@ -1889,5 +1889,67 @@ be used. See the description further above how to make such a filter known
|
|||||||
by Vim.
|
by Vim.
|
||||||
|
|
||||||
|
|
||||||
|
=============================================================================
|
||||||
|
10. Customizing the quickfix window *quickfix-window-function*
|
||||||
|
|
||||||
|
The default format for the lines displayed in the quickfix window and location
|
||||||
|
list window is:
|
||||||
|
|
||||||
|
<filename>|<lnum> col <col>|<text>
|
||||||
|
|
||||||
|
The values displayed in each line correspond to the "bufnr", "lnum", "col" and
|
||||||
|
"text" fields returned by the |getqflist()| function.
|
||||||
|
|
||||||
|
For some quickfix/location lists, the displayed text need to be customized.
|
||||||
|
For example, if only the filename is present for a quickfix entry, then the
|
||||||
|
two "|" field separator characters after the filename are not needed. Another
|
||||||
|
use case is to customize the path displayed for a filename. By default, the
|
||||||
|
complete path (which may be too long) is displayed for files which are not
|
||||||
|
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 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.
|
||||||
|
winid for a location list, set to the id of the window with the
|
||||||
|
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
|
||||||
|
|setloclist()| function. This overrides the global 'quickfixtextfunc' option.
|
||||||
|
|
||||||
|
The example below displays the list of old files (|v:oldfiles|) in a quickfix
|
||||||
|
window. As there is no line, column number and error text information
|
||||||
|
associated with each entry, the 'quickfixtextfunc' function returns only the
|
||||||
|
filename.
|
||||||
|
Example: >
|
||||||
|
" create a quickfix list from v:oldfiles
|
||||||
|
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:tw=78:ts=8:noet:ft=help:norl:
|
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||||
|
@ -6326,7 +6326,7 @@ void get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg,
|
|||||||
if (what_arg->v_type == VAR_UNKNOWN) {
|
if (what_arg->v_type == VAR_UNKNOWN) {
|
||||||
tv_list_alloc_ret(rettv, kListLenMayKnow);
|
tv_list_alloc_ret(rettv, kListLenMayKnow);
|
||||||
if (is_qf || wp != NULL) {
|
if (is_qf || wp != NULL) {
|
||||||
(void)get_errorlist(NULL, wp, -1, rettv->vval.v_list);
|
(void)get_errorlist(NULL, wp, -1, 0, rettv->vval.v_list);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tv_dict_alloc_ret(rettv);
|
tv_dict_alloc_ret(rettv);
|
||||||
|
@ -559,6 +559,7 @@ EXTERN int p_ri; // 'revins'
|
|||||||
EXTERN int p_ru; // 'ruler'
|
EXTERN int p_ru; // 'ruler'
|
||||||
EXTERN char_u *p_ruf; // 'rulerformat'
|
EXTERN char_u *p_ruf; // 'rulerformat'
|
||||||
EXTERN char_u *p_pp; // 'packpath'
|
EXTERN char_u *p_pp; // 'packpath'
|
||||||
|
EXTERN char_u *p_qftf; // 'quickfixtextfunc'
|
||||||
EXTERN char_u *p_rtp; // 'runtimepath'
|
EXTERN char_u *p_rtp; // 'runtimepath'
|
||||||
EXTERN long p_scbk; // 'scrollback'
|
EXTERN long p_scbk; // 'scrollback'
|
||||||
EXTERN long p_sj; // 'scrolljump'
|
EXTERN long p_sj; // 'scrolljump'
|
||||||
|
@ -2073,6 +2073,14 @@ return {
|
|||||||
varname='p_pyx',
|
varname='p_pyx',
|
||||||
defaults={if_true={vi=0}}
|
defaults={if_true={vi=0}}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
full_name='quickfixtextfunc', abbreviation='qftf',
|
||||||
|
short_desc=N_("customize the quickfix window"),
|
||||||
|
type='string', scope={'global'},
|
||||||
|
vi_def=true,
|
||||||
|
varname='p_qftf',
|
||||||
|
defaults={if_true={vi=""}}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
full_name='quoteescape', abbreviation='qe',
|
full_name='quoteescape', abbreviation='qe',
|
||||||
short_desc=N_("escape characters used in a string"),
|
short_desc=N_("escape characters used in a string"),
|
||||||
|
@ -100,6 +100,7 @@ typedef struct qf_list_S {
|
|||||||
char_u *qf_title; ///< title derived from the command that created
|
char_u *qf_title; ///< title derived from the command that created
|
||||||
///< the error list or set by setqflist
|
///< the error list or set by setqflist
|
||||||
typval_T *qf_ctx; ///< context set by setqflist/setloclist
|
typval_T *qf_ctx; ///< context set by setqflist/setloclist
|
||||||
|
char_u *qf_qftf; ///< 'quickfixtextfunc' setting for this list
|
||||||
|
|
||||||
struct dir_stack_T *qf_dir_stack;
|
struct dir_stack_T *qf_dir_stack;
|
||||||
char_u *qf_directory;
|
char_u *qf_directory;
|
||||||
@ -1999,6 +2000,11 @@ static int copy_loclist(const qf_list_T *from_qfl, qf_list_T *to_qfl)
|
|||||||
} else {
|
} else {
|
||||||
to_qfl->qf_ctx = NULL;
|
to_qfl->qf_ctx = NULL;
|
||||||
}
|
}
|
||||||
|
if (from_qfl->qf_qftf != NULL) {
|
||||||
|
to_qfl->qf_qftf = vim_strsave(from_qfl->qf_qftf);
|
||||||
|
} else {
|
||||||
|
to_qfl->qf_qftf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (from_qfl->qf_count) {
|
if (from_qfl->qf_count) {
|
||||||
if (copy_loclist_entries(from_qfl, to_qfl) == FAIL) {
|
if (copy_loclist_entries(from_qfl, to_qfl) == FAIL) {
|
||||||
@ -3382,6 +3388,7 @@ static void qf_free(qf_list_T *qfl)
|
|||||||
XFREE_CLEAR(qfl->qf_title);
|
XFREE_CLEAR(qfl->qf_title);
|
||||||
tv_free(qfl->qf_ctx);
|
tv_free(qfl->qf_ctx);
|
||||||
qfl->qf_ctx = NULL;
|
qfl->qf_ctx = NULL;
|
||||||
|
XFREE_CLEAR(qfl->qf_qftf);
|
||||||
qfl->qf_id = 0;
|
qfl->qf_id = 0;
|
||||||
qfl->qf_changedtick = 0L;
|
qfl->qf_changedtick = 0L;
|
||||||
}
|
}
|
||||||
@ -3721,7 +3728,7 @@ void ex_copen(exarg_T *eap)
|
|||||||
lnum = qfl->qf_index;
|
lnum = qfl->qf_index;
|
||||||
|
|
||||||
// Fill the buffer with the quickfix list.
|
// Fill the buffer with the quickfix list.
|
||||||
qf_fill_buffer(qfl, curbuf, NULL);
|
qf_fill_buffer(qfl, curbuf, NULL, curwin->handle);
|
||||||
|
|
||||||
decr_quickfix_busy();
|
decr_quickfix_busy();
|
||||||
|
|
||||||
@ -3884,6 +3891,11 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
|
|||||||
buf = qf_find_buf(qi);
|
buf = qf_find_buf(qi);
|
||||||
if (buf != NULL) {
|
if (buf != NULL) {
|
||||||
linenr_T old_line_count = buf->b_ml.ml_line_count;
|
linenr_T old_line_count = buf->b_ml.ml_line_count;
|
||||||
|
int qf_winid = 0;
|
||||||
|
|
||||||
|
if (IS_LL_STACK(qi)) {
|
||||||
|
qf_winid = curwin->handle;
|
||||||
|
}
|
||||||
|
|
||||||
if (old_last == NULL) {
|
if (old_last == NULL) {
|
||||||
// set curwin/curbuf to buf and save a few things
|
// set curwin/curbuf to buf and save a few things
|
||||||
@ -3892,7 +3904,7 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
|
|||||||
|
|
||||||
qf_update_win_titlevar(qi);
|
qf_update_win_titlevar(qi);
|
||||||
|
|
||||||
qf_fill_buffer(qf_get_curlist(qi), buf, old_last);
|
qf_fill_buffer(qf_get_curlist(qi), buf, old_last, qf_winid);
|
||||||
buf_inc_changedtick(buf);
|
buf_inc_changedtick(buf);
|
||||||
|
|
||||||
if (old_last == NULL) {
|
if (old_last == NULL) {
|
||||||
@ -3911,70 +3923,75 @@ 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(buf_T *buf, linenr_T lnum, const qfline_T *qfp,
|
static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum,
|
||||||
char_u *dirname, bool first_bufline)
|
const qfline_T *qfp, char_u *dirname,
|
||||||
FUNC_ATTR_NONNULL_ALL
|
char_u *qftf_str, bool first_bufline)
|
||||||
|
FUNC_ATTR_NONNULL_ARG(1, 2, 4, 5)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
buf_T *errbuf;
|
buf_T *errbuf;
|
||||||
|
|
||||||
if (qfp->qf_module != NULL) {
|
if (qftf_str != NULL) {
|
||||||
STRLCPY(IObuff, qfp->qf_module, IOSIZE);
|
STRLCPY(IObuff, qftf_str, IOSIZE);
|
||||||
len = (int)STRLEN(IObuff);
|
|
||||||
} else if (qfp->qf_fnum != 0
|
|
||||||
&& (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL
|
|
||||||
&& errbuf->b_fname != NULL) {
|
|
||||||
if (qfp->qf_type == 1) { // :helpgrep
|
|
||||||
STRLCPY(IObuff, path_tail(errbuf->b_fname), IOSIZE);
|
|
||||||
} else {
|
|
||||||
// Shorten the file name if not done already.
|
|
||||||
// For optimization, do this only for the first entry in a
|
|
||||||
// buffer.
|
|
||||||
if (first_bufline
|
|
||||||
&& (errbuf->b_sfname == NULL
|
|
||||||
|| path_is_absolute(errbuf->b_sfname))) {
|
|
||||||
if (*dirname == NUL) {
|
|
||||||
os_dirname(dirname, MAXPATHL);
|
|
||||||
}
|
|
||||||
shorten_buf_fname(errbuf, dirname, false);
|
|
||||||
}
|
|
||||||
STRLCPY(IObuff, errbuf->b_fname, IOSIZE);
|
|
||||||
}
|
|
||||||
len = (int)STRLEN(IObuff);
|
|
||||||
} else {
|
} else {
|
||||||
len = 0;
|
if (qfp->qf_module != NULL) {
|
||||||
}
|
STRLCPY(IObuff, qfp->qf_module, IOSIZE);
|
||||||
if (len < IOSIZE - 1) {
|
len = (int)STRLEN(IObuff);
|
||||||
IObuff[len++] = '|';
|
} else if (qfp->qf_fnum != 0
|
||||||
}
|
&& (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL
|
||||||
if (qfp->qf_lnum > 0) {
|
&& errbuf->b_fname != NULL) {
|
||||||
snprintf((char *)IObuff + len, (size_t)(IOSIZE - len), "%" PRId64,
|
if (qfp->qf_type == 1) { // :helpgrep
|
||||||
(int64_t)qfp->qf_lnum);
|
STRLCPY(IObuff, path_tail(errbuf->b_fname), IOSIZE);
|
||||||
len += (int)STRLEN(IObuff + len);
|
} else {
|
||||||
|
// Shorten the file name if not done already.
|
||||||
|
// For optimization, do this only for the first entry in a
|
||||||
|
// buffer.
|
||||||
|
if (first_bufline
|
||||||
|
&& (errbuf->b_sfname == NULL
|
||||||
|
|| path_is_absolute(errbuf->b_sfname))) {
|
||||||
|
if (*dirname == NUL) {
|
||||||
|
os_dirname(dirname, MAXPATHL);
|
||||||
|
}
|
||||||
|
shorten_buf_fname(errbuf, dirname, false);
|
||||||
|
}
|
||||||
|
STRLCPY(IObuff, errbuf->b_fname, IOSIZE);
|
||||||
|
}
|
||||||
|
len = (int)STRLEN(IObuff);
|
||||||
|
} else {
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
if (len < IOSIZE - 1) {
|
||||||
|
IObuff[len++] = '|';
|
||||||
|
}
|
||||||
|
if (qfp->qf_lnum > 0) {
|
||||||
|
snprintf((char *)IObuff + len, (size_t)(IOSIZE - len), "%" PRId64,
|
||||||
|
(int64_t)qfp->qf_lnum);
|
||||||
|
len += (int)STRLEN(IObuff + len);
|
||||||
|
|
||||||
if (qfp->qf_col > 0) {
|
if (qfp->qf_col > 0) {
|
||||||
snprintf((char *)IObuff + len, (size_t)(IOSIZE - len), " col %d",
|
snprintf((char *)IObuff + len, (size_t)(IOSIZE - len), " col %d",
|
||||||
qfp->qf_col);
|
qfp->qf_col);
|
||||||
|
len += (int)STRLEN(IObuff + len);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf((char *)IObuff + len, (size_t)(IOSIZE - len), "%s",
|
||||||
|
(char *)qf_types(qfp->qf_type, qfp->qf_nr));
|
||||||
|
len += (int)STRLEN(IObuff + len);
|
||||||
|
} else if (qfp->qf_pattern != NULL) {
|
||||||
|
qf_fmt_text(qfp->qf_pattern, IObuff + len, IOSIZE - len);
|
||||||
len += (int)STRLEN(IObuff + len);
|
len += (int)STRLEN(IObuff + len);
|
||||||
}
|
}
|
||||||
|
if (len < IOSIZE - 2) {
|
||||||
|
IObuff[len++] = '|';
|
||||||
|
IObuff[len++] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
snprintf((char *)IObuff + len, (size_t)(IOSIZE - len), "%s",
|
// Remove newlines and leading whitespace from the text.
|
||||||
(char *)qf_types(qfp->qf_type, qfp->qf_nr));
|
// For an unrecognized line keep the indent, the compiler may
|
||||||
len += (int)STRLEN(IObuff + len);
|
// mark a word with ^^^^.
|
||||||
} else if (qfp->qf_pattern != NULL) {
|
qf_fmt_text(len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text,
|
||||||
qf_fmt_text(qfp->qf_pattern, IObuff + len, IOSIZE - len);
|
IObuff + len, IOSIZE - len);
|
||||||
len += (int)STRLEN(IObuff + len);
|
|
||||||
}
|
}
|
||||||
if (len < IOSIZE - 2) {
|
|
||||||
IObuff[len++] = '|';
|
|
||||||
IObuff[len++] = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove newlines and leading whitespace from the text.
|
|
||||||
// For an unrecognized line keep the indent, the compiler may
|
|
||||||
// mark a word with ^^^^.
|
|
||||||
qf_fmt_text(len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text,
|
|
||||||
IObuff + len, IOSIZE - len);
|
|
||||||
|
|
||||||
if (ml_append_buf(buf, lnum, IObuff,
|
if (ml_append_buf(buf, lnum, IObuff,
|
||||||
(colnr_T)STRLEN(IObuff) + 1, false) == FAIL) {
|
(colnr_T)STRLEN(IObuff) + 1, false) == FAIL) {
|
||||||
@ -3983,17 +4000,56 @@ static int qf_buf_add_line(buf_T *buf, linenr_T lnum, const qfline_T *qfp,
|
|||||||
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.
|
||||||
/// When "old_last" is NULL then "buf" must equal "curbuf"! Because ml_delete()
|
/// When "old_last" is NULL then "buf" must equal "curbuf"! Because ml_delete()
|
||||||
/// is used and autocommands will be triggered.
|
/// is used and autocommands will be triggered.
|
||||||
static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last)
|
static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last,
|
||||||
|
int qf_winid)
|
||||||
FUNC_ATTR_NONNULL_ARG(2)
|
FUNC_ATTR_NONNULL_ARG(2)
|
||||||
{
|
{
|
||||||
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) {
|
||||||
@ -4026,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(buf, lnum, qfp, dirname,
|
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;
|
||||||
}
|
}
|
||||||
@ -4037,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
|
||||||
@ -5665,7 +5736,10 @@ static int get_qfline_items(qfline_T *qfp, list_T *list)
|
|||||||
|
|
||||||
/// Add each quickfix error to list "list" as a dictionary.
|
/// Add each quickfix error to list "list" as a dictionary.
|
||||||
/// If qf_idx is -1, use the current list. Otherwise, use the specified list.
|
/// If qf_idx is -1, use the current list. Otherwise, use the specified list.
|
||||||
int get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, list_T *list)
|
/// If eidx is not 0, then return only the specified entry. Otherwise return
|
||||||
|
/// all the entries.
|
||||||
|
int get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, int eidx,
|
||||||
|
list_T *list)
|
||||||
{
|
{
|
||||||
qf_info_T *qi = qi_arg;
|
qf_info_T *qi = qi_arg;
|
||||||
qf_list_T *qfl;
|
qf_list_T *qfl;
|
||||||
@ -5682,6 +5756,10 @@ int get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, list_T *list)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (eidx < 0) {
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (qf_idx == INVALID_QFIDX) {
|
if (qf_idx == INVALID_QFIDX) {
|
||||||
qf_idx = qi->qf_curlist;
|
qf_idx = qi->qf_curlist;
|
||||||
}
|
}
|
||||||
@ -5696,7 +5774,13 @@ int get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, list_T *list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
FOR_ALL_QFL_ITEMS(qfl, qfp, i) {
|
FOR_ALL_QFL_ITEMS(qfl, qfp, i) {
|
||||||
get_qfline_items(qfp, list);
|
if (eidx > 0) {
|
||||||
|
if (eidx == i) {
|
||||||
|
return get_qfline_items(qfp, list);
|
||||||
|
}
|
||||||
|
} else if (get_qfline_items(qfp, list) == FAIL) {
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
@ -5743,7 +5827,7 @@ static int qf_get_list_from_lines(dict_T *what, dictitem_T *di, dict_T *retdict)
|
|||||||
|
|
||||||
if (qf_init_ext(qi, 0, NULL, NULL, &di->di_tv, errorformat,
|
if (qf_init_ext(qi, 0, NULL, NULL, &di->di_tv, errorformat,
|
||||||
true, (linenr_T)0, (linenr_T)0, NULL, NULL) > 0) {
|
true, (linenr_T)0, (linenr_T)0, NULL, NULL) > 0) {
|
||||||
(void)get_errorlist(qi, NULL, 0, l);
|
(void)get_errorlist(qi, NULL, 0, 0, l);
|
||||||
qf_free(&qi->qf_lists[0]);
|
qf_free(&qi->qf_lists[0]);
|
||||||
}
|
}
|
||||||
xfree(qi);
|
xfree(qi);
|
||||||
@ -5934,11 +6018,13 @@ static int qf_getprop_filewinid(const win_T *wp, const qf_info_T *qi,
|
|||||||
return tv_dict_add_nr(retdict, S_LEN("filewinid"), winid);
|
return tv_dict_add_nr(retdict, S_LEN("filewinid"), winid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the quickfix list items/entries as 'items' in retdict
|
/// Return the quickfix list items/entries as 'items' in retdict.
|
||||||
static int qf_getprop_items(qf_info_T *qi, int qf_idx, dict_T *retdict)
|
/// If eidx is not 0, then return the item at the specified index.
|
||||||
|
static int qf_getprop_items(qf_info_T *qi, int qf_idx, int eidx,
|
||||||
|
dict_T *retdict)
|
||||||
{
|
{
|
||||||
list_T *l = tv_list_alloc(kListLenMayKnow);
|
list_T *l = tv_list_alloc(kListLenMayKnow);
|
||||||
get_errorlist(qi, NULL, qf_idx, l);
|
get_errorlist(qi, NULL, qf_idx, eidx, l);
|
||||||
tv_dict_add_list(retdict, S_LEN("items"), l);
|
tv_dict_add_list(retdict, S_LEN("items"), l);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
@ -5963,15 +6049,18 @@ static int qf_getprop_ctx(qf_list_T *qfl, dict_T *retdict)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the current quickfix list index as 'idx' in retdict
|
/// Return the current quickfix list index as 'idx' in retdict.
|
||||||
static int qf_getprop_idx(qf_list_T *qfl, dict_T *retdict)
|
/// If a specific entry index (eidx) is supplied, then use that.
|
||||||
|
static int qf_getprop_idx(qf_list_T *qfl, int eidx, dict_T *retdict)
|
||||||
{
|
{
|
||||||
int curidx = qfl->qf_index;
|
if (eidx == 0) {
|
||||||
if (qf_list_empty(qfl)) {
|
eidx = qfl->qf_index;
|
||||||
// For empty lists, current index is set to 0
|
if (qf_list_empty(qfl)) {
|
||||||
curidx = 0;
|
// For empty lists, current index is set to 0
|
||||||
|
eidx = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return tv_dict_add_nr(retdict, S_LEN("idx"), curidx);
|
return tv_dict_add_nr(retdict, S_LEN("idx"), eidx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return quickfix/location list details (title) as a dictionary.
|
/// Return quickfix/location list details (title) as a dictionary.
|
||||||
@ -5984,6 +6073,7 @@ int qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
|||||||
dictitem_T *di = NULL;
|
dictitem_T *di = NULL;
|
||||||
int status = OK;
|
int status = OK;
|
||||||
int qf_idx = INVALID_QFIDX;
|
int qf_idx = INVALID_QFIDX;
|
||||||
|
int eidx = 0;
|
||||||
|
|
||||||
if ((di = tv_dict_find(what, S_LEN("lines"))) != NULL) {
|
if ((di = tv_dict_find(what, S_LEN("lines"))) != NULL) {
|
||||||
return qf_get_list_from_lines(what, di, retdict);
|
return qf_get_list_from_lines(what, di, retdict);
|
||||||
@ -6006,6 +6096,14 @@ int qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
|||||||
|
|
||||||
qfl = qf_get_list(qi, qf_idx);
|
qfl = qf_get_list(qi, qf_idx);
|
||||||
|
|
||||||
|
// If an entry index is specified, use that
|
||||||
|
if ((di = tv_dict_find(what, S_LEN("idx"))) != NULL) {
|
||||||
|
if (di->di_tv.v_type != VAR_NUMBER) {
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
eidx = (int)di->di_tv.vval.v_number;
|
||||||
|
}
|
||||||
|
|
||||||
if (flags & QF_GETLIST_TITLE) {
|
if (flags & QF_GETLIST_TITLE) {
|
||||||
status = qf_getprop_title(qfl, retdict);
|
status = qf_getprop_title(qfl, retdict);
|
||||||
}
|
}
|
||||||
@ -6016,7 +6114,7 @@ int qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
|||||||
status = tv_dict_add_nr(retdict, S_LEN("winid"), qf_winid(qi));
|
status = tv_dict_add_nr(retdict, S_LEN("winid"), qf_winid(qi));
|
||||||
}
|
}
|
||||||
if ((status == OK) && (flags & QF_GETLIST_ITEMS)) {
|
if ((status == OK) && (flags & QF_GETLIST_ITEMS)) {
|
||||||
status = qf_getprop_items(qi, qf_idx, retdict);
|
status = qf_getprop_items(qi, qf_idx, eidx, retdict);
|
||||||
}
|
}
|
||||||
if ((status == OK) && (flags & QF_GETLIST_CONTEXT)) {
|
if ((status == OK) && (flags & QF_GETLIST_CONTEXT)) {
|
||||||
status = qf_getprop_ctx(qfl, retdict);
|
status = qf_getprop_ctx(qfl, retdict);
|
||||||
@ -6025,7 +6123,7 @@ int qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
|||||||
status = tv_dict_add_nr(retdict, S_LEN("id"), qfl->qf_id);
|
status = tv_dict_add_nr(retdict, S_LEN("id"), qfl->qf_id);
|
||||||
}
|
}
|
||||||
if ((status == OK) && (flags & QF_GETLIST_IDX)) {
|
if ((status == OK) && (flags & QF_GETLIST_IDX)) {
|
||||||
status = qf_getprop_idx(qfl, retdict);
|
status = qf_getprop_idx(qfl, eidx, retdict);
|
||||||
}
|
}
|
||||||
if ((status == OK) && (flags & QF_GETLIST_SIZE)) {
|
if ((status == OK) && (flags & QF_GETLIST_SIZE)) {
|
||||||
status = tv_dict_add_nr(retdict, S_LEN("size"),
|
status = tv_dict_add_nr(retdict, S_LEN("size"),
|
||||||
@ -6042,6 +6140,17 @@ int qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the current index in the specified quickfix list
|
||||||
|
static int qf_setprop_qftf(qf_info_T *qi, qf_list_T *qfl,
|
||||||
|
dictitem_T *di)
|
||||||
|
{
|
||||||
|
XFREE_CLEAR(qfl->qf_qftf);
|
||||||
|
if (di->di_tv.v_type == VAR_STRING && di->di_tv.vval.v_string != NULL) {
|
||||||
|
qfl->qf_qftf = vim_strsave(di->di_tv.vval.v_string);
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/// Add a new quickfix entry to list at 'qf_idx' in the stack 'qi' from the
|
/// Add a new quickfix entry to list at 'qf_idx' in the stack 'qi' from the
|
||||||
/// items in the dict 'd'. If it is a valid error entry, then set 'valid_entry'
|
/// items in the dict 'd'. If it is a valid error entry, then set 'valid_entry'
|
||||||
/// to true.
|
/// to true.
|
||||||
@ -6407,6 +6516,9 @@ static int qf_set_properties(qf_info_T *qi, const dict_T *what, int action,
|
|||||||
if ((di = tv_dict_find(what, S_LEN("idx"))) != NULL) {
|
if ((di = tv_dict_find(what, S_LEN("idx"))) != NULL) {
|
||||||
retval = qf_setprop_curidx(qi, qfl, di);
|
retval = qf_setprop_curidx(qi, qfl, di);
|
||||||
}
|
}
|
||||||
|
if ((di = tv_dict_find(what, S_LEN("quickfixtextfunc"))) != NULL) {
|
||||||
|
retval = qf_setprop_qftf(qi, qfl, di);
|
||||||
|
}
|
||||||
|
|
||||||
if (newlist || retval == OK) {
|
if (newlist || retval == OK) {
|
||||||
qf_list_changed(qfl);
|
qf_list_changed(qfl);
|
||||||
|
@ -4786,4 +4786,148 @@ func Test_qfbuf_update()
|
|||||||
call Xqfbuf_update('l')
|
call Xqfbuf_update('l')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Test for getting a specific item from a quickfix list
|
||||||
|
func Xtest_getqflist_by_idx(cchar)
|
||||||
|
call s:setup_commands(a:cchar)
|
||||||
|
" Empty list
|
||||||
|
call assert_equal([], g:Xgetlist({'idx' : 1, 'items' : 0}).items)
|
||||||
|
Xexpr ['F1:10:L10', 'F1:20:L20']
|
||||||
|
let l = g:Xgetlist({'idx' : 2, 'items' : 0}).items
|
||||||
|
call assert_equal(bufnr('F1'), l[0].bufnr)
|
||||||
|
call assert_equal(20, l[0].lnum)
|
||||||
|
call assert_equal('L20', l[0].text)
|
||||||
|
call assert_equal([], g:Xgetlist({'idx' : -1, 'items' : 0}).items)
|
||||||
|
call assert_equal([], g:Xgetlist({'idx' : 3, 'items' : 0}).items)
|
||||||
|
%bwipe!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_getqflist_by_idx()
|
||||||
|
call Xtest_getqflist_by_idx('c')
|
||||||
|
call Xtest_getqflist_by_idx('l')
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" 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)
|
||||||
|
call s:setup_commands(a:cchar)
|
||||||
|
|
||||||
|
set efm=%f:%l:%c:%m
|
||||||
|
set quickfixtextfunc=Tqfexpr
|
||||||
|
Xexpr ['F1:10:2:green', 'F1:20:4:blue']
|
||||||
|
Xwindow
|
||||||
|
call assert_equal('F1-L10C2-green', getline(1))
|
||||||
|
call assert_equal('F1-L20C4-blue', getline(2))
|
||||||
|
Xclose
|
||||||
|
set quickfixtextfunc&vim
|
||||||
|
Xwindow
|
||||||
|
call assert_equal('F1|10 col 2| green', getline(1))
|
||||||
|
call assert_equal('F1|20 col 4| blue', getline(2))
|
||||||
|
Xclose
|
||||||
|
set efm&
|
||||||
|
set quickfixtextfunc&
|
||||||
|
|
||||||
|
" 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"})
|
||||||
|
Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
|
||||||
|
Xwindow
|
||||||
|
call assert_equal('Line 10, Col 2', getline(1))
|
||||||
|
call assert_equal('Line 20, Col 4', getline(2))
|
||||||
|
Xclose
|
||||||
|
" Add entries to the list when the quickfix buffer is hidden
|
||||||
|
Xaddexpr ['F1:30:6:red']
|
||||||
|
Xwindow
|
||||||
|
call assert_equal('Line 30, Col 6', getline(3))
|
||||||
|
Xclose
|
||||||
|
call g:Xsetlist([], 'r', {'quickfixtextfunc' : ''})
|
||||||
|
set quickfixtextfunc&
|
||||||
|
delfunc PerQfText
|
||||||
|
|
||||||
|
" Non-existing function
|
||||||
|
set quickfixtextfunc=Tabc
|
||||||
|
" call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
|
||||||
|
Xexpr ['F1:10:2:green', 'F1:20:4:blue']"
|
||||||
|
call assert_fails("Xwindow", 'E117:')
|
||||||
|
Xclose
|
||||||
|
set quickfixtextfunc&
|
||||||
|
|
||||||
|
" set option to a non-function
|
||||||
|
set quickfixtextfunc=[10,\ 20]
|
||||||
|
" call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
|
||||||
|
Xexpr ['F1:10:2:green', 'F1:20:4:blue']"
|
||||||
|
call assert_fails("Xwindow", 'E117:')
|
||||||
|
Xclose
|
||||||
|
set quickfixtextfunc&
|
||||||
|
|
||||||
|
" set option to a function with different set of arguments
|
||||||
|
func Xqftext(a, b, c)
|
||||||
|
return a:a .. a:b .. a:c
|
||||||
|
endfunc
|
||||||
|
set quickfixtextfunc=Xqftext
|
||||||
|
" call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
|
||||||
|
Xexpr ['F1:10:2:green', 'F1:20:4:blue']"
|
||||||
|
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:')
|
||||||
|
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&
|
||||||
|
delfunc Xqftext
|
||||||
|
delfunc Xqftext2
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_qftextfunc()
|
||||||
|
call Xtest_qftextfunc('c')
|
||||||
|
call Xtest_qftextfunc('l')
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
Loading…
Reference in New Issue
Block a user