forked from aniani/vim
patch 8.2.4329: no support for end line number and column in 'errorformat'
Problem: No support for end line number and column in 'errorformat'. Solution: Add %e and %k. (closes #9624)
This commit is contained in:
committed by
Bram Moolenaar
parent
73a16c22a4
commit
e023d49937
@@ -1385,12 +1385,17 @@ Basic items
|
|||||||
%f file name (finds a string)
|
%f file name (finds a string)
|
||||||
%o module name (finds a string)
|
%o module name (finds a string)
|
||||||
%l line number (finds a number)
|
%l line number (finds a number)
|
||||||
|
%e end line number (finds a number)
|
||||||
%c column number (finds a number representing character
|
%c column number (finds a number representing character
|
||||||
column of the error, byte index, a <tab> is 1
|
column of the error, byte index, a <tab> is 1
|
||||||
character column)
|
character column)
|
||||||
%v virtual column number (finds a number representing
|
%v virtual column number (finds a number representing
|
||||||
screen column of the error (1 <tab> == 8 screen
|
screen column of the error (1 <tab> == 8 screen
|
||||||
columns))
|
columns))
|
||||||
|
%k end column number (finds a number representing
|
||||||
|
the character column of the error, byte index, or a
|
||||||
|
number representing screen end column of the error if
|
||||||
|
it's used with %v)
|
||||||
%t error type (finds a single character):
|
%t error type (finds a single character):
|
||||||
e - error message
|
e - error message
|
||||||
w - warning message
|
w - warning message
|
||||||
|
@@ -118,7 +118,7 @@ struct qf_info_S
|
|||||||
static qf_info_T ql_info; // global quickfix list
|
static qf_info_T ql_info; // global quickfix list
|
||||||
static int_u last_qf_id = 0; // Last used quickfix list id
|
static int_u last_qf_id = 0; // Last used quickfix list id
|
||||||
|
|
||||||
#define FMT_PATTERNS 11 // maximum number of % recognized
|
#define FMT_PATTERNS 13 // maximum number of % recognized
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Structure used to hold the info of one part of 'errorformat'
|
* Structure used to hold the info of one part of 'errorformat'
|
||||||
@@ -224,6 +224,9 @@ static bufref_T qf_last_bufref = {NULL, 0, 0};
|
|||||||
*/
|
*/
|
||||||
#define LINE_MAXLEN 4096
|
#define LINE_MAXLEN 4096
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Patterns used. Keep in sync with qf_parse_fmt[].
|
||||||
|
*/
|
||||||
static struct fmtpattern
|
static struct fmtpattern
|
||||||
{
|
{
|
||||||
char_u convchar;
|
char_u convchar;
|
||||||
@@ -231,16 +234,20 @@ static struct fmtpattern
|
|||||||
} fmt_pat[FMT_PATTERNS] =
|
} fmt_pat[FMT_PATTERNS] =
|
||||||
{
|
{
|
||||||
{'f', ".\\+"}, // only used when at end
|
{'f', ".\\+"}, // only used when at end
|
||||||
{'n', "\\d\\+"},
|
{'n', "\\d\\+"}, // 1
|
||||||
{'l', "\\d\\+"},
|
{'l', "\\d\\+"}, // 2
|
||||||
{'c', "\\d\\+"},
|
{'e', "\\d\\+"}, // 3
|
||||||
{'t', "."},
|
{'c', "\\d\\+"}, // 4
|
||||||
{'m', ".\\+"},
|
{'k', "\\d\\+"}, // 5
|
||||||
{'r', ".*"},
|
{'t', "."}, // 6
|
||||||
{'p', "[- .]*"},
|
#define FMT_PATTERN_M 7
|
||||||
{'v', "\\d\\+"},
|
{'m', ".\\+"}, // 7
|
||||||
{'s', ".\\+"},
|
#define FMT_PATTERN_R 8
|
||||||
{'o', ".\\+"}
|
{'r', ".*"}, // 8
|
||||||
|
{'p', "[- .]*"}, // 9
|
||||||
|
{'v', "\\d\\+"}, // 10
|
||||||
|
{'s', ".\\+"}, // 11
|
||||||
|
{'o', ".\\+"} // 12
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -265,9 +272,9 @@ efmpat_to_regpat(
|
|||||||
semsg(_(e_too_many_chr_in_format_string), *efmpat);
|
semsg(_(e_too_many_chr_in_format_string), *efmpat);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if ((idx && idx < 6
|
if ((idx && idx < FMT_PATTERN_R
|
||||||
&& vim_strchr((char_u *)"DXOPQ", efminfo->prefix) != NULL)
|
&& vim_strchr((char_u *)"DXOPQ", efminfo->prefix) != NULL)
|
||||||
|| (idx == 6
|
|| (idx == FMT_PATTERN_R
|
||||||
&& vim_strchr((char_u *)"OPQ", efminfo->prefix) == NULL))
|
&& vim_strchr((char_u *)"OPQ", efminfo->prefix) == NULL))
|
||||||
{
|
{
|
||||||
semsg(_(e_unexpected_chr_in_format_str), *efmpat);
|
semsg(_(e_unexpected_chr_in_format_str), *efmpat);
|
||||||
@@ -948,7 +955,7 @@ qf_parse_fmt_n(regmatch_T *rmp, int midx, qffields_T *fields)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse the match for line number (%l') pattern in regmatch.
|
* Parse the match for line number ('%l') pattern in regmatch.
|
||||||
* Return the matched value in "fields->lnum".
|
* Return the matched value in "fields->lnum".
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@@ -960,6 +967,19 @@ qf_parse_fmt_l(regmatch_T *rmp, int midx, qffields_T *fields)
|
|||||||
return QF_OK;
|
return QF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the match for end line number ('%e') pattern in regmatch.
|
||||||
|
* Return the matched value in "fields->end_lnum".
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
qf_parse_fmt_e(regmatch_T *rmp, int midx, qffields_T *fields)
|
||||||
|
{
|
||||||
|
if (rmp->startp[midx] == NULL)
|
||||||
|
return QF_FAIL;
|
||||||
|
fields->end_lnum = atol((char *)rmp->startp[midx]);
|
||||||
|
return QF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse the match for column number ('%c') pattern in regmatch.
|
* Parse the match for column number ('%c') pattern in regmatch.
|
||||||
* Return the matched value in "fields->col".
|
* Return the matched value in "fields->col".
|
||||||
@@ -973,6 +993,19 @@ qf_parse_fmt_c(regmatch_T *rmp, int midx, qffields_T *fields)
|
|||||||
return QF_OK;
|
return QF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the match for end column number ('%k') pattern in regmatch.
|
||||||
|
* Return the matched value in "fields->end_col".
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
qf_parse_fmt_k(regmatch_T *rmp, int midx, qffields_T *fields)
|
||||||
|
{
|
||||||
|
if (rmp->startp[midx] == NULL)
|
||||||
|
return QF_FAIL;
|
||||||
|
fields->end_col = (int)atol((char *)rmp->startp[midx]);
|
||||||
|
return QF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse the match for error type ('%t') pattern in regmatch.
|
* Parse the match for error type ('%t') pattern in regmatch.
|
||||||
* Return the matched value in "fields->type".
|
* Return the matched value in "fields->type".
|
||||||
@@ -1132,16 +1165,19 @@ qf_parse_fmt_o(regmatch_T *rmp, int midx, qffields_T *fields)
|
|||||||
* 'errorformat' format pattern parser functions.
|
* 'errorformat' format pattern parser functions.
|
||||||
* The '%f' and '%r' formats are parsed differently from other formats.
|
* The '%f' and '%r' formats are parsed differently from other formats.
|
||||||
* See qf_parse_match() for details.
|
* See qf_parse_match() for details.
|
||||||
|
* Keep in sync with fmt_pat[].
|
||||||
*/
|
*/
|
||||||
static int (*qf_parse_fmt[FMT_PATTERNS])(regmatch_T *, int, qffields_T *) =
|
static int (*qf_parse_fmt[FMT_PATTERNS])(regmatch_T *, int, qffields_T *) =
|
||||||
{
|
{
|
||||||
NULL,
|
NULL, // %f
|
||||||
qf_parse_fmt_n,
|
qf_parse_fmt_n,
|
||||||
qf_parse_fmt_l,
|
qf_parse_fmt_l,
|
||||||
|
qf_parse_fmt_e,
|
||||||
qf_parse_fmt_c,
|
qf_parse_fmt_c,
|
||||||
|
qf_parse_fmt_k,
|
||||||
qf_parse_fmt_t,
|
qf_parse_fmt_t,
|
||||||
qf_parse_fmt_m,
|
qf_parse_fmt_m,
|
||||||
NULL,
|
NULL, // %r
|
||||||
qf_parse_fmt_p,
|
qf_parse_fmt_p,
|
||||||
qf_parse_fmt_v,
|
qf_parse_fmt_v,
|
||||||
qf_parse_fmt_s,
|
qf_parse_fmt_s,
|
||||||
@@ -1186,14 +1222,14 @@ qf_parse_match(
|
|||||||
midx = (int)fmt_ptr->addr[i];
|
midx = (int)fmt_ptr->addr[i];
|
||||||
if (i == 0 && midx > 0) // %f
|
if (i == 0 && midx > 0) // %f
|
||||||
status = qf_parse_fmt_f(regmatch, midx, fields, idx);
|
status = qf_parse_fmt_f(regmatch, midx, fields, idx);
|
||||||
else if (i == 5)
|
else if (i == FMT_PATTERN_M)
|
||||||
{
|
{
|
||||||
if (fmt_ptr->flags == '+' && !qf_multiscan) // %+
|
if (fmt_ptr->flags == '+' && !qf_multiscan) // %+
|
||||||
status = copy_nonerror_line(linebuf, linelen, fields);
|
status = copy_nonerror_line(linebuf, linelen, fields);
|
||||||
else if (midx > 0) // %m
|
else if (midx > 0) // %m
|
||||||
status = qf_parse_fmt_m(regmatch, midx, fields);
|
status = qf_parse_fmt_m(regmatch, midx, fields);
|
||||||
}
|
}
|
||||||
else if (i == 6 && midx > 0) // %r
|
else if (i == FMT_PATTERN_R && midx > 0) // %r
|
||||||
status = qf_parse_fmt_r(regmatch, midx, tail);
|
status = qf_parse_fmt_r(regmatch, midx, tail);
|
||||||
else if (midx > 0) // others
|
else if (midx > 0) // others
|
||||||
status = (qf_parse_fmt[i])(regmatch, midx, fields);
|
status = (qf_parse_fmt[i])(regmatch, midx, fields);
|
||||||
@@ -1363,11 +1399,15 @@ qf_parse_multiline_pfx(
|
|||||||
|
|
||||||
if (!qfprev->qf_lnum)
|
if (!qfprev->qf_lnum)
|
||||||
qfprev->qf_lnum = fields->lnum;
|
qfprev->qf_lnum = fields->lnum;
|
||||||
|
if (!qfprev->qf_end_lnum)
|
||||||
|
qfprev->qf_end_lnum = fields->end_lnum;
|
||||||
if (!qfprev->qf_col)
|
if (!qfprev->qf_col)
|
||||||
{
|
{
|
||||||
qfprev->qf_col = fields->col;
|
qfprev->qf_col = fields->col;
|
||||||
qfprev->qf_viscol = fields->use_viscol;
|
qfprev->qf_viscol = fields->use_viscol;
|
||||||
}
|
}
|
||||||
|
if (!qfprev->qf_end_col)
|
||||||
|
qfprev->qf_end_col = fields->end_col;
|
||||||
if (!qfprev->qf_fnum)
|
if (!qfprev->qf_fnum)
|
||||||
qfprev->qf_fnum = qf_get_fnum(qfl,
|
qfprev->qf_fnum = qf_get_fnum(qfl,
|
||||||
qfl->qf_directory,
|
qfl->qf_directory,
|
||||||
|
@@ -1469,6 +1469,29 @@ func Test_efm_error_type()
|
|||||||
let &efm = save_efm
|
let &efm = save_efm
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Test for end_lnum ('%e') and end_col ('%k') fields in 'efm'
|
||||||
|
func Test_efm_end_lnum_col()
|
||||||
|
let save_efm = &efm
|
||||||
|
|
||||||
|
" single line
|
||||||
|
set efm=%f:%l-%e:%c-%k:%t:%m
|
||||||
|
cexpr ["Xfile1:10-20:1-2:E:msg1", "Xfile1:20-30:2-3:W:msg2",]
|
||||||
|
let output = split(execute('clist'), "\n")
|
||||||
|
call assert_equal([
|
||||||
|
\ ' 1 Xfile1:10-20 col 1-2 error: msg1',
|
||||||
|
\ ' 2 Xfile1:20-30 col 2-3 warning: msg2'], output)
|
||||||
|
|
||||||
|
" multiple lines
|
||||||
|
set efm=%A%n)%m,%Z%f:%l-%e:%c-%k
|
||||||
|
cexpr ["1)msg1", "Xfile1:14-24:1-2",
|
||||||
|
\ "2)msg2", "Xfile1:24-34:3-4"]
|
||||||
|
let output = split(execute('clist'), "\n")
|
||||||
|
call assert_equal([
|
||||||
|
\ ' 1 Xfile1:14-24 col 1-2 error 1: msg1',
|
||||||
|
\ ' 2 Xfile1:24-34 col 3-4 error 2: msg2'], output)
|
||||||
|
let &efm = save_efm
|
||||||
|
endfunc
|
||||||
|
|
||||||
func XquickfixChangedByAutocmd(cchar)
|
func XquickfixChangedByAutocmd(cchar)
|
||||||
call s:setup_commands(a:cchar)
|
call s:setup_commands(a:cchar)
|
||||||
if a:cchar == 'c'
|
if a:cchar == 'c'
|
||||||
|
@@ -746,6 +746,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 */
|
||||||
|
/**/
|
||||||
|
4329,
|
||||||
/**/
|
/**/
|
||||||
4328,
|
4328,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user