Patch 8.2.4329
Problem: No support for end line number and column in 'errorformat'.
Solution: Add %e and %k. (closes #9624)
Files: runtime/doc/quickfix.txt, src/quickfix.c,
src/testdir/test_quickfix.vim
*** ../vim-8.2.4328/runtime/doc/quickfix.txt 2021-04-26 20:14:12.709924759 +0100
--- runtime/doc/quickfix.txt 2022-02-08 17:52:46.035090664 +0000
***************
*** 1382,1392 ****
%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))
%v virtual column number (finds a number representing
screen column of the error (1 <tab> == 8 screen
columns))
%t error type (finds a single character):
e - error message
w - warning message
--- 1385,1401 ----
%f file name (finds a string)
%o module name (finds a string)
%l line number (finds a number)
+ %e end line number (finds a number)
%c column number (finds a number representing character
! column of the error, byte index, a <tab> is 1
! character column)
%v virtual column number (finds a number representing
screen column of the error (1 <tab> == 8 screen
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):
e - error message
w - warning message
*** ../vim-8.2.4328/src/quickfix.c 2022-01-05 20:24:34.276005641 +0000
--- src/quickfix.c 2022-02-08 18:06:28.044675832 +0000
***************
*** 118,124 ****
static qf_info_T ql_info; // global quickfix list
static int_u last_qf_id = 0; // Last used quickfix list id
! #define FMT_PATTERNS 11 // maximum number of % recognized
/*
* Structure used to hold the info of one part of 'errorformat'
--- 118,124 ----
static qf_info_T ql_info; // global quickfix list
static int_u last_qf_id = 0; // Last used quickfix list id
! #define FMT_PATTERNS 13 // maximum number of % recognized
/*
* Structure used to hold the info of one part of 'errorformat'
***************
*** 224,229 ****
--- 224,232 ----
*/
#define LINE_MAXLEN 4096
+ /*
+ * Patterns used. Keep in sync with qf_parse_fmt[].
+ */
static struct fmtpattern
{
char_u convchar;
***************
*** 231,246 ****
} fmt_pat[FMT_PATTERNS] =
{
{'f', ".\\+"}, // only used when at end
! {'n', "\\d\\+"},
! {'l', "\\d\\+"},
! {'c', "\\d\\+"},
! {'t', "."},
! {'m', ".\\+"},
! {'r', ".*"},
! {'p', "[- .]*"},
! {'v', "\\d\\+"},
! {'s', ".\\+"},
! {'o', ".\\+"}
};
/*
--- 234,253 ----
} fmt_pat[FMT_PATTERNS] =
{
{'f', ".\\+"}, // only used when at end
! {'n', "\\d\\+"}, // 1
! {'l', "\\d\\+"}, // 2
! {'e', "\\d\\+"}, // 3
! {'c', "\\d\\+"}, // 4
! {'k', "\\d\\+"}, // 5
! {'t', "."}, // 6
! #define FMT_PATTERN_M 7
! {'m', ".\\+"}, // 7
! #define FMT_PATTERN_R 8
! {'r', ".*"}, // 8
! {'p', "[- .]*"}, // 9
! {'v', "\\d\\+"}, // 10
! {'s', ".\\+"}, // 11
! {'o', ".\\+"} // 12
};
/*
***************
*** 265,273 ****
semsg(_(e_too_many_chr_in_format_string), *efmpat);
return NULL;
}
! if ((idx && idx < 6
&& vim_strchr((char_u *)"DXOPQ", efminfo->prefix) != NULL)
! || (idx == 6
&& vim_strchr((char_u *)"OPQ", efminfo->prefix) == NULL))
{
semsg(_(e_unexpected_chr_in_format_str), *efmpat);
--- 272,280 ----
semsg(_(e_too_many_chr_in_format_string), *efmpat);
return NULL;
}
! if ((idx && idx < FMT_PATTERN_R
&& vim_strchr((char_u *)"DXOPQ", efminfo->prefix) != NULL)
! || (idx == FMT_PATTERN_R
&& vim_strchr((char_u *)"OPQ", efminfo->prefix) == NULL))
{
semsg(_(e_unexpected_chr_in_format_str), *efmpat);
***************
*** 948,954 ****
}
/*
! * Parse the match for line number (%l') pattern in regmatch.
* Return the matched value in "fields->lnum".
*/
static int
--- 955,961 ----
}
/*
! * Parse the match for line number ('%l') pattern in regmatch.
* Return the matched value in "fields->lnum".
*/
static int
***************
*** 961,966 ****
--- 968,986 ----
}
/*
+ * 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.
* Return the matched value in "fields->col".
*/
***************
*** 974,979 ****
--- 994,1012 ----
}
/*
+ * 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.
* Return the matched value in "fields->type".
*/
***************
*** 1132,1147 ****
* 'errorformat' format pattern parser functions.
* The '%f' and '%r' formats are parsed differently from other formats.
* See qf_parse_match() for details.
*/
static int (*qf_parse_fmt[FMT_PATTERNS])(regmatch_T *, int, qffields_T *) =
{
! NULL,
qf_parse_fmt_n,
qf_parse_fmt_l,
qf_parse_fmt_c,
qf_parse_fmt_t,
qf_parse_fmt_m,
! NULL,
qf_parse_fmt_p,
qf_parse_fmt_v,
qf_parse_fmt_s,
--- 1165,1183 ----
* 'errorformat' format pattern parser functions.
* The '%f' and '%r' formats are parsed differently from other formats.
* See qf_parse_match() for details.
+ * Keep in sync with fmt_pat[].
*/
static int (*qf_parse_fmt[FMT_PATTERNS])(regmatch_T *, int, qffields_T *) =
{
! NULL, // %f
qf_parse_fmt_n,
qf_parse_fmt_l,
+ qf_parse_fmt_e,
qf_parse_fmt_c,
+ qf_parse_fmt_k,
qf_parse_fmt_t,
qf_parse_fmt_m,
! NULL, // %r
qf_parse_fmt_p,
qf_parse_fmt_v,
qf_parse_fmt_s,
***************
*** 1186,1199 ****
midx = (int)fmt_ptr->addr[i];
if (i == 0 && midx > 0) // %f
status = qf_parse_fmt_f(regmatch, midx, fields, idx);
! else if (i == 5)
{
if (fmt_ptr->flags == '+' && !qf_multiscan) // %+
status = copy_nonerror_line(linebuf, linelen, fields);
else if (midx > 0) // %m
status = qf_parse_fmt_m(regmatch, midx, fields);
}
! else if (i == 6 && midx > 0) // %r
status = qf_parse_fmt_r(regmatch, midx, tail);
else if (midx > 0) // others
status = (qf_parse_fmt[i])(regmatch, midx, fields);
--- 1222,1235 ----
midx = (int)fmt_ptr->addr[i];
if (i == 0 && midx > 0) // %f
status = qf_parse_fmt_f(regmatch, midx, fields, idx);
! else if (i == FMT_PATTERN_M)
{
if (fmt_ptr->flags == '+' && !qf_multiscan) // %+
status = copy_nonerror_line(linebuf, linelen, fields);
else if (midx > 0) // %m
status = qf_parse_fmt_m(regmatch, midx, fields);
}
! else if (i == FMT_PATTERN_R && midx > 0) // %r
status = qf_parse_fmt_r(regmatch, midx, tail);
else if (midx > 0) // others
status = (qf_parse_fmt[i])(regmatch, midx, fields);
***************
*** 1363,1373 ****
--- 1399,1413 ----
if (!qfprev->qf_lnum)
qfprev->qf_lnum = fields->lnum;
+ if (!qfprev->qf_end_lnum)
+ qfprev->qf_end_lnum = fields->end_lnum;
if (!qfprev->qf_col)
{
qfprev->qf_col = fields->col;
qfprev->qf_viscol = fields->use_viscol;
}
+ if (!qfprev->qf_end_col)
+ qfprev->qf_end_col = fields->end_col;
if (!qfprev->qf_fnum)
qfprev->qf_fnum = qf_get_fnum(qfl,
qfl->qf_directory,
*** ../vim-8.2.4328/src/testdir/test_quickfix.vim 2022-02-08 15:05:16.664625568 +0000
--- src/testdir/test_quickfix.vim 2022-02-08 17:48:35.780264014 +0000
***************
*** 1469,1474 ****
--- 1469,1497 ----
let &efm = save_efm
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)
call s:setup_commands(a:cchar)
if a:cchar == 'c'
*** ../vim-8.2.4328/src/version.c 2022-02-08 17:40:13.649047302 +0000
--- src/version.c 2022-02-08 17:51:28.667417479 +0000
***************
*** 748,749 ****
--- 748,751 ----
{ /* Add new patch number below this line */
+ /**/
+ 4329,
/**/
--
I have a drinking problem -- I don't have a drink!
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///