mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:8.0.1782: no simple way to label quickfix entries
Problem: No simple way to label quickfix entries.
Solution: Add the "module" item, to be used instead of the file name for
display purposes. (Martin Szamotulski)
d76ce85266
This commit is contained in:
parent
ce0e083094
commit
e6c21c4bc0
@ -7064,6 +7064,8 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()*
|
||||
buffer
|
||||
filename name of a file; only used when "bufnr" is not
|
||||
present or it is invalid.
|
||||
module name of a module; if given it will be used in
|
||||
quickfix error window instead of the filename
|
||||
lnum line number in the file
|
||||
pattern search pattern used to locate the error
|
||||
col column number
|
||||
|
@ -1204,6 +1204,7 @@ you want to match case, add "\C" to the pattern |/\C|.
|
||||
Basic items
|
||||
|
||||
%f file name (finds a string)
|
||||
%o module name (finds a string)
|
||||
%l line number (finds a number)
|
||||
%c column number (finds a number representing character
|
||||
column of the error, (1 <tab> == 1 character column))
|
||||
@ -1248,6 +1249,11 @@ conversion can be used to locate lines without a line number in the error
|
||||
output. Like the output of the "grep" shell command.
|
||||
When the pattern is present the line number will not be used.
|
||||
|
||||
The "%o" conversion specifies the module name in quickfix entry. If present
|
||||
it will be used in quickfix error window instead of the filename. The module
|
||||
name is used only for displaying purposes, the file name is used when jumping
|
||||
to the file.
|
||||
|
||||
Changing directory
|
||||
|
||||
The following uppercase conversion characters specify the type of special
|
||||
|
@ -57,19 +57,20 @@ struct dir_stack_T {
|
||||
*/
|
||||
typedef struct qfline_S qfline_T;
|
||||
struct qfline_S {
|
||||
qfline_T *qf_next; /* pointer to next error in the list */
|
||||
qfline_T *qf_prev; /* pointer to previous error in the list */
|
||||
linenr_T qf_lnum; /* line number where the error occurred */
|
||||
int qf_fnum; /* file number for the line */
|
||||
int qf_col; /* column where the error occurred */
|
||||
int qf_nr; /* error number */
|
||||
char_u *qf_pattern; /* search pattern for the error */
|
||||
char_u *qf_text; /* description of the error */
|
||||
char_u qf_viscol; /* set to TRUE if qf_col is screen column */
|
||||
char_u qf_cleared; /* set to TRUE if line has been deleted */
|
||||
char_u qf_type; /* type of the error (mostly 'E'); 1 for
|
||||
:helpgrep */
|
||||
char_u qf_valid; /* valid error message detected */
|
||||
qfline_T *qf_next; ///< pointer to next error in the list
|
||||
qfline_T *qf_prev; ///< pointer to previous error in the list
|
||||
linenr_T qf_lnum; ///< line number where the error occurred
|
||||
int qf_fnum; ///< file number for the line
|
||||
int qf_col; ///< column where the error occurred
|
||||
int qf_nr; ///< error number
|
||||
char_u *qf_module; ///< module name for this error
|
||||
char_u *qf_pattern; ///< search pattern for the error
|
||||
char_u *qf_text; ///< description of the error
|
||||
char_u qf_viscol; ///< set to TRUE if qf_col is screen column
|
||||
char_u qf_cleared; ///< set to TRUE if line has been deleted
|
||||
char_u qf_type; ///< type of the error (mostly 'E'); 1 for
|
||||
// :helpgrep
|
||||
char_u qf_valid; ///< valid error message detected
|
||||
};
|
||||
|
||||
/*
|
||||
@ -122,7 +123,7 @@ struct qf_info_S {
|
||||
static qf_info_T ql_info; // global quickfix list
|
||||
static unsigned last_qf_id = 0; // Last Used quickfix list id
|
||||
|
||||
#define FMT_PATTERNS 10 /* maximum number of % recognized */
|
||||
#define FMT_PATTERNS 11 // maximum number of % recognized
|
||||
|
||||
/*
|
||||
* Structure used to hold the info of one part of 'errorformat'
|
||||
@ -177,6 +178,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
char_u *namebuf;
|
||||
char_u *module;
|
||||
char_u *errmsg;
|
||||
size_t errmsglen;
|
||||
long lnum;
|
||||
@ -250,7 +252,8 @@ static struct fmtpattern
|
||||
{ 'r', ".*" },
|
||||
{ 'p', "[- .]*" }, // NOLINT(whitespace/tab)
|
||||
{ 'v', "\\d\\+" },
|
||||
{ 's', ".\\+" }
|
||||
{ 's', ".\\+" },
|
||||
{ 'o', ".\\+" }
|
||||
};
|
||||
|
||||
// Converts a 'errorformat' string to regular expression pattern
|
||||
@ -748,6 +751,7 @@ restofline:
|
||||
continue;
|
||||
}
|
||||
fields->namebuf[0] = NUL;
|
||||
fields->module[0] = NUL;
|
||||
fields->pattern[0] = NUL;
|
||||
if (!qfl->qf_multiscan) {
|
||||
fields->errmsg[0] = NUL;
|
||||
@ -878,6 +882,16 @@ restofline:
|
||||
fields->pattern[len + 4] = '$';
|
||||
fields->pattern[len + 5] = NUL;
|
||||
}
|
||||
if ((i = (int)fmt_ptr->addr[10]) > 0) { // %o
|
||||
if (regmatch.startp[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
len = (size_t)(regmatch.endp[i] - regmatch.startp[i]);
|
||||
if (len > CMDBUFFSIZE) {
|
||||
len = CMDBUFFSIZE;
|
||||
}
|
||||
xstrlcat((char *)fields->module, (char *)regmatch.startp[i], len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1037,6 +1051,7 @@ qf_init_ext(
|
||||
}
|
||||
|
||||
fields.namebuf = xmalloc(CMDBUFFSIZE + 1);
|
||||
fields.module = xmalloc(CMDBUFFSIZE + 1);
|
||||
fields.errmsglen = CMDBUFFSIZE + 1;
|
||||
fields.errmsg = xmalloc(fields.errmsglen);
|
||||
fields.pattern = xmalloc(CMDBUFFSIZE + 1);
|
||||
@ -1131,6 +1146,7 @@ qf_init_ext(
|
||||
(*fields.namebuf || qfl->qf_directory)
|
||||
? fields.namebuf : ((qfl->qf_currfile && fields.valid)
|
||||
? qfl->qf_currfile : (char_u *)NULL),
|
||||
fields.module,
|
||||
0,
|
||||
fields.errmsg,
|
||||
fields.lnum,
|
||||
@ -1175,6 +1191,7 @@ qf_init_end:
|
||||
fclose(state.fd);
|
||||
}
|
||||
xfree(fields.namebuf);
|
||||
xfree(fields.module);
|
||||
xfree(fields.errmsg);
|
||||
xfree(fields.pattern);
|
||||
xfree(state.growbuf);
|
||||
@ -1276,6 +1293,7 @@ void qf_free_all(win_T *wp)
|
||||
/// @param qf_idx list index
|
||||
/// @param dir optional directory name
|
||||
/// @param fname file name or NULL
|
||||
/// @param module module name or NULL
|
||||
/// @param bufnum buffer number or zero
|
||||
/// @param mesg message
|
||||
/// @param lnum line number
|
||||
@ -1288,9 +1306,9 @@ void qf_free_all(win_T *wp)
|
||||
///
|
||||
/// @returns OK or FAIL.
|
||||
static int qf_add_entry(qf_info_T *qi, int qf_idx, char_u *dir, char_u *fname,
|
||||
int bufnum, char_u *mesg, long lnum, int col,
|
||||
char_u vis_col, char_u *pattern, int nr, char_u type,
|
||||
char_u valid)
|
||||
char_u *module, int bufnum, char_u *mesg, long lnum,
|
||||
int col, char_u vis_col, char_u *pattern, int nr,
|
||||
char_u type, char_u valid)
|
||||
{
|
||||
qfline_T *qfp = xmalloc(sizeof(qfline_T));
|
||||
qfline_T **lastp; // pointer to qf_last or NULL
|
||||
@ -1315,6 +1333,14 @@ static int qf_add_entry(qf_info_T *qi, int qf_idx, char_u *dir, char_u *fname,
|
||||
} else {
|
||||
qfp->qf_pattern = vim_strsave(pattern);
|
||||
}
|
||||
if (module == NULL || *module == NUL) {
|
||||
qfp->qf_module = NULL;
|
||||
} else if ((qfp->qf_module = vim_strsave(module)) == NULL) {
|
||||
xfree(qfp->qf_text);
|
||||
xfree(qfp->qf_pattern);
|
||||
xfree(qfp);
|
||||
return QF_FAIL;
|
||||
}
|
||||
qfp->qf_nr = nr;
|
||||
if (type != 1 && !vim_isprintc(type)) /* only printable chars allowed */
|
||||
type = 0;
|
||||
@ -1446,6 +1472,7 @@ void copy_loclist(win_T *from, win_T *to)
|
||||
to->w_llist->qf_curlist,
|
||||
NULL,
|
||||
NULL,
|
||||
from_qfp->qf_module,
|
||||
0,
|
||||
from_qfp->qf_text,
|
||||
from_qfp->qf_lnum,
|
||||
@ -2394,17 +2421,22 @@ void qf_list(exarg_T *eap)
|
||||
break;
|
||||
|
||||
fname = NULL;
|
||||
if (qfp->qf_fnum != 0
|
||||
&& (buf = buflist_findnr(qfp->qf_fnum)) != NULL) {
|
||||
fname = buf->b_fname;
|
||||
if (qfp->qf_type == 1) /* :helpgrep */
|
||||
fname = path_tail(fname);
|
||||
if (qfp->qf_module != NULL && *qfp->qf_module != NUL) {
|
||||
vim_snprintf((char *)IObuff, IOSIZE, "%2d %s", i,
|
||||
(char *)qfp->qf_module);
|
||||
} else {
|
||||
if (qfp->qf_fnum != 0 && (buf = buflist_findnr(qfp->qf_fnum)) != NULL) {
|
||||
fname = buf->b_fname;
|
||||
if (qfp->qf_type == 1) { // :helpgrep
|
||||
fname = path_tail(fname);
|
||||
}
|
||||
}
|
||||
if (fname == NULL) {
|
||||
snprintf((char *)IObuff, IOSIZE, "%2d", i);
|
||||
} else {
|
||||
vim_snprintf((char *)IObuff, IOSIZE, "%2d %s", i, (char *)fname);
|
||||
}
|
||||
}
|
||||
if (fname == NULL)
|
||||
sprintf((char *)IObuff, "%2d", i);
|
||||
else
|
||||
vim_snprintf((char *)IObuff, IOSIZE, "%2d %s",
|
||||
i, (char *)fname);
|
||||
msg_outtrans_attr(IObuff, i == qi->qf_lists[qi->qf_curlist].qf_index
|
||||
? HL_ATTR(HLF_QFL) : HL_ATTR(HLF_D));
|
||||
if (qfp->qf_lnum == 0) {
|
||||
@ -2565,9 +2597,10 @@ static void qf_free_items(qf_info_T *qi, int idx)
|
||||
qfp = qfl->qf_start;
|
||||
qfpnext = qfp->qf_next;
|
||||
if (!stop) {
|
||||
xfree(qfp->qf_module);
|
||||
xfree(qfp->qf_text);
|
||||
stop = (qfp == qfpnext);
|
||||
xfree(qfp->qf_pattern);
|
||||
stop = (qfp == qfpnext);
|
||||
xfree(qfp);
|
||||
if (stop) {
|
||||
// Somehow qf_count may have an incorrect value, set it to 1
|
||||
@ -3108,9 +3141,12 @@ static void qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last)
|
||||
lnum = buf->b_ml.ml_line_count;
|
||||
}
|
||||
while (lnum < qi->qf_lists[qi->qf_curlist].qf_count) {
|
||||
if (qfp->qf_fnum != 0
|
||||
&& (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL
|
||||
&& errbuf->b_fname != NULL) {
|
||||
if (qfp->qf_module != NULL) {
|
||||
STRCPY(IObuff, qfp->qf_module);
|
||||
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), sizeof(IObuff));
|
||||
} else {
|
||||
@ -3799,6 +3835,7 @@ static bool vgr_match_buflines(qf_info_T *qi, char_u *fname, buf_T *buf,
|
||||
qi->qf_curlist,
|
||||
NULL, // dir
|
||||
fname,
|
||||
NULL,
|
||||
duplicate_name ? 0 : buf->b_fnum,
|
||||
ml_get_buf(buf, regmatch->startpos[0].lnum + lnum, false),
|
||||
regmatch->startpos[0].lnum + lnum,
|
||||
@ -4306,6 +4343,10 @@ int get_errorlist(const qf_info_T *qi_arg, win_T *wp, int qf_idx, list_T *list)
|
||||
|| (tv_dict_add_nr(dict, S_LEN("vcol"), (varnumber_T)qfp->qf_viscol)
|
||||
== FAIL)
|
||||
|| (tv_dict_add_nr(dict, S_LEN("nr"), (varnumber_T)qfp->qf_nr) == FAIL)
|
||||
|| tv_dict_add_str(dict, S_LEN("module"),
|
||||
(qfp->qf_module == NULL
|
||||
? ""
|
||||
: (const char *)qfp->qf_module)) == FAIL
|
||||
|| tv_dict_add_str(dict, S_LEN("pattern"),
|
||||
(qfp->qf_pattern == NULL
|
||||
? ""
|
||||
@ -4680,6 +4721,7 @@ static int qf_add_entries(qf_info_T *qi, int qf_idx, list_T *list,
|
||||
}
|
||||
|
||||
char *const filename = tv_dict_get_string(d, "filename", true);
|
||||
char *const module = tv_dict_get_string(d, "module", true);
|
||||
int bufnum = (int)tv_dict_get_number(d, "bufnr");
|
||||
long lnum = (long)tv_dict_get_number(d, "lnum");
|
||||
int col = (int)tv_dict_get_number(d, "col");
|
||||
@ -4717,6 +4759,7 @@ static int qf_add_entries(qf_info_T *qi, int qf_idx, list_T *list,
|
||||
qf_idx,
|
||||
NULL, // dir
|
||||
(char_u *)filename,
|
||||
(char_u *)module,
|
||||
bufnum,
|
||||
(char_u *)text,
|
||||
lnum,
|
||||
@ -4728,6 +4771,7 @@ static int qf_add_entries(qf_info_T *qi, int qf_idx, list_T *list,
|
||||
valid);
|
||||
|
||||
xfree(filename);
|
||||
xfree(module);
|
||||
xfree(pattern);
|
||||
xfree(text);
|
||||
|
||||
@ -5263,15 +5307,15 @@ void ex_helpgrep(exarg_T *eap)
|
||||
if (gen_expand_wildcards(1, buff_list, &fcount,
|
||||
&fnames, EW_FILE|EW_SILENT) == OK
|
||||
&& fcount > 0) {
|
||||
for (fi = 0; fi < fcount && !got_int; ++fi) {
|
||||
/* Skip files for a different language. */
|
||||
for (fi = 0; fi < fcount && !got_int; fi++) {
|
||||
// Skip files for a different language.
|
||||
if (lang != NULL
|
||||
&& STRNICMP(lang, fnames[fi]
|
||||
+ STRLEN(fnames[fi]) - 3, 2) != 0
|
||||
&& STRNICMP(lang, fnames[fi] + STRLEN(fnames[fi]) - 3, 2) != 0
|
||||
&& !(STRNICMP(lang, "en", 2) == 0
|
||||
&& STRNICMP("txt", fnames[fi]
|
||||
+ STRLEN(fnames[fi]) - 3, 3) == 0))
|
||||
+ STRLEN(fnames[fi]) - 3, 3) == 0)) {
|
||||
continue;
|
||||
}
|
||||
fd = mch_fopen((char *)fnames[fi], "r");
|
||||
if (fd != NULL) {
|
||||
lnum = 1;
|
||||
@ -5288,6 +5332,7 @@ void ex_helpgrep(exarg_T *eap)
|
||||
qi->qf_curlist,
|
||||
NULL, // dir
|
||||
fnames[fi],
|
||||
NULL,
|
||||
0,
|
||||
line,
|
||||
lnum,
|
||||
|
@ -136,6 +136,16 @@ func XlistTests(cchar)
|
||||
\ ' 4:40 col 20 x 44: Other',
|
||||
\ ' 5:50 col 25 55: one'], l)
|
||||
|
||||
" Test for module names, one needs to explicitly set `'valid':v:true` so
|
||||
call g:Xsetlist([
|
||||
\ {'lnum':10,'col':5,'type':'W','module':'Data.Text','text':'ModuleWarning','nr':11,'valid':v:true},
|
||||
\ {'lnum':20,'col':10,'type':'W','module':'Data.Text','filename':'Data/Text.hs','text':'ModuleWarning','nr':22,'valid':v:true},
|
||||
\ {'lnum':30,'col':15,'type':'W','filename':'Data/Text.hs','text':'FileWarning','nr':33,'valid':v:true}])
|
||||
let l = split(execute('Xlist', ""), "\n")
|
||||
call assert_equal([' 1 Data.Text:10 col 5 warning 11: ModuleWarning',
|
||||
\ ' 2 Data.Text:20 col 10 warning 22: ModuleWarning',
|
||||
\ ' 3 Data/Text.hs:30 col 15 warning 33: FileWarning'], l)
|
||||
|
||||
" Error cases
|
||||
call assert_fails('Xlist abc', 'E488:')
|
||||
endfunc
|
||||
@ -1093,6 +1103,21 @@ func Test_efm2()
|
||||
call assert_equal(1, l[4].valid)
|
||||
call assert_equal(expand('unittests/dbfacadeTest.py'), bufname(l[4].bufnr))
|
||||
|
||||
" Test for %o
|
||||
set efm=%f(%o):%l\ %m
|
||||
cgetexpr ['Xtestfile(Language.PureScript.Types):20 Error']
|
||||
call writefile(['Line1'], 'Xtestfile')
|
||||
let l = getqflist()
|
||||
call assert_equal(1, len(l), string(l))
|
||||
call assert_equal('Language.PureScript.Types', l[0].module)
|
||||
copen
|
||||
call assert_equal('Language.PureScript.Types|20| Error', getline(1))
|
||||
call feedkeys("\<CR>", 'xn')
|
||||
call assert_equal('Xtestfile', expand('%:t'))
|
||||
cclose
|
||||
bd
|
||||
call delete("Xtestfile")
|
||||
|
||||
" The following sequence of commands used to crash Vim
|
||||
set efm=%W%m
|
||||
cgetexpr ['msg1']
|
||||
|
@ -37,9 +37,9 @@ for _, c in ipairs({'l', 'c'}) do
|
||||
-- Second line of each entry (i.e. `nr=-1, …`) was obtained from actual
|
||||
-- results. First line (i.e. `{lnum=…`) was obtained from legacy test.
|
||||
local list = {
|
||||
{lnum=700, col=10, text='Line 700',
|
||||
{lnum=700, col=10, text='Line 700', module='',
|
||||
nr=-1, bufnr=2, valid=1, pattern='', vcol=0, ['type']=''},
|
||||
{lnum=800, col=15, text='Line 800',
|
||||
{lnum=800, col=15, text='Line 800', module='',
|
||||
nr=-1, bufnr=3, valid=1, pattern='', vcol=0, ['type']=''},
|
||||
}
|
||||
eq(list, getlist())
|
||||
@ -58,7 +58,7 @@ for _, c in ipairs({'l', 'c'}) do
|
||||
]]):format(file))
|
||||
command(('%s %s'):format(addfcmd, file))
|
||||
list[#list + 1] = {
|
||||
lnum=900, col=30, text='Line 900',
|
||||
lnum=900, col=30, text='Line 900', module='',
|
||||
nr=-1, bufnr=5, valid=1, pattern='', vcol=0, ['type']='',
|
||||
}
|
||||
eq(list, getlist())
|
||||
@ -71,9 +71,9 @@ for _, c in ipairs({'l', 'c'}) do
|
||||
command('enew!')
|
||||
command(('%s %s'):format(getfcmd, file))
|
||||
list = {
|
||||
{lnum=222, col=77, text='Line 222',
|
||||
{lnum=222, col=77, text='Line 222', module='',
|
||||
nr=-1, bufnr=2, valid=1, pattern='', vcol=0, ['type']=''},
|
||||
{lnum=333, col=88, text='Line 333',
|
||||
{lnum=333, col=88, text='Line 333', module='',
|
||||
nr=-1, bufnr=3, valid=1, pattern='', vcol=0, ['type']=''},
|
||||
}
|
||||
eq(list, getlist())
|
||||
|
Loading…
Reference in New Issue
Block a user