changeset 27605:bf540a32439a v8.2.4329

patch 8.2.4329: no support for end line number and column in 'errorformat' Commit: https://github.com/vim/vim/commit/e023d499378942a6c3a3855cbe461ec2cb570f63 Author: haya14busa <haya14busa@gmail.com> Date: Tue Feb 8 18:09:29 2022 +0000 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 https://github.com/vim/vim/issues/9624)
author Bram Moolenaar <Bram@vim.org>
date Tue, 08 Feb 2022 19:15:03 +0100
parents 4f782c34c224
children a03441c13f68
files runtime/doc/quickfix.txt src/quickfix.c src/testdir/test_quickfix.vim src/version.c
diffstat 4 files changed, 88 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/quickfix.txt
+++ b/runtime/doc/quickfix.txt
@@ -1385,12 +1385,17 @@ Basic items
 	%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
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -118,7 +118,7 @@ struct qf_info_S
 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
+#define FMT_PATTERNS 13		// maximum number of % recognized
 
 /*
  * Structure used to hold the info of one part of 'errorformat'
@@ -224,6 +224,9 @@ static bufref_T  qf_last_bufref = {NULL,
  */
 #define LINE_MAXLEN 4096
 
+/*
+ * Patterns used.  Keep in sync with qf_parse_fmt[].
+ */
 static struct fmtpattern
 {
     char_u	convchar;
@@ -231,16 +234,20 @@ static struct fmtpattern
 } fmt_pat[FMT_PATTERNS] =
     {
 	{'f', ".\\+"},	    // only used when at end
-	{'n', "\\d\\+"},
-	{'l', "\\d\\+"},
-	{'c', "\\d\\+"},
-	{'t', "."},
-	{'m', ".\\+"},
-	{'r', ".*"},
-	{'p', "[- 	.]*"},
-	{'v', "\\d\\+"},
-	{'s', ".\\+"},
-	{'o', ".\\+"}
+	{'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,9 +272,9 @@ efmpat_to_regpat(
 	semsg(_(e_too_many_chr_in_format_string), *efmpat);
 	return NULL;
     }
-    if ((idx && idx < 6
+    if ((idx && idx < FMT_PATTERN_R
 		&& vim_strchr((char_u *)"DXOPQ", efminfo->prefix) != NULL)
-	    || (idx == 6
+	    || (idx == FMT_PATTERN_R
 		&& vim_strchr((char_u *)"OPQ", efminfo->prefix) == NULL))
     {
 	semsg(_(e_unexpected_chr_in_format_str), *efmpat);
@@ -948,7 +955,7 @@ qf_parse_fmt_n(regmatch_T *rmp, int midx
 }
 
 /*
- * 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".
  */
     static int
@@ -961,6 +968,19 @@ qf_parse_fmt_l(regmatch_T *rmp, int midx
 }
 
 /*
+ * 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,6 +994,19 @@ qf_parse_fmt_c(regmatch_T *rmp, int midx
 }
 
 /*
+ * 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,16 +1165,19 @@ qf_parse_fmt_o(regmatch_T *rmp, int midx
  * '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,
+    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,
+    NULL, // %r
     qf_parse_fmt_p,
     qf_parse_fmt_v,
     qf_parse_fmt_s,
@@ -1186,14 +1222,14 @@ qf_parse_match(
 	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)
+	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 == 6 && midx > 0)			// %r
+	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,11 +1399,15 @@ qf_parse_multiline_pfx(
 
 	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,
--- a/src/testdir/test_quickfix.vim
+++ b/src/testdir/test_quickfix.vim
@@ -1469,6 +1469,29 @@ func Test_efm_error_type()
   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'
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    4329,
+/**/
     4328,
 /**/
     4327,