# HG changeset patch # User Christian Brabandt # Date 1698260404 -7200 # Node ID 5614c43616fe57974ba809c59668fbfc5f88738d # Parent 88cad94caef9a31353f9fa90a28e99d37ded531e patch 9.0.2064: cannot use buffer-number for errorformat Commit: https://github.com/vim/vim/commit/b731800522af00fd348814d33a065b92e698afc3 Author: Yegappan Lakshmanan Date: Wed Oct 25 20:50:28 2023 +0200 patch 9.0.2064: cannot use buffer-number for errorformat Problem: cannot use buffer-number for errorformat Solution: add support for parsing a buffer number using '%b' in 'errorformat' closes: #13419 Signed-off-by: Christian Brabandt Co-authored-by: Yegappan Lakshmanan diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -1422,6 +1422,7 @@ rest is ignored. Items can only be 1023 Basic items %f file name (finds a string) + %b buffer number (finds a number) %o module name (finds a string) %l line number (finds a number) %e end line number (finds a number) @@ -1461,6 +1462,11 @@ On MS-Windows a leading "C:" will be inc This means that a file name which is a single alphabetical letter will not be detected. +The "%b" conversion is used to parse a buffer number. This is useful for +referring to lines in a scratch buffer or a buffer with no name. If a buffer +with the matching number doesn't exist, then that line is used as a non-error +line. + The "%p" conversion is normally followed by a "^". It's used for compilers that output a line like: > ^ diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -5945,8 +5945,6 @@ 8 Add ":rename" command: rename the fi 7 Instead of filtering errors with a shell script it should be possible to do this with Vim script. A function that filters the raw text that comes from the 'makeprg'? -- Add %b to 'errorformat': buffer number. (Yegappan Lakshmanan / Suresh - Govindachar) 7 Allow a window not to have a statusline. Makes it possible to use a window as a buffer-tab selection. 8 Allow non-active windows to have a different statusline. (Yakov Lerner) diff --git a/src/quickfix.c b/src/quickfix.c --- a/src/quickfix.c +++ b/src/quickfix.c @@ -120,7 +120,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 13 // maximum number of % recognized +#define FMT_PATTERNS 14 // maximum number of % recognized /* * Structure used to hold the info of one part of 'errorformat' @@ -275,20 +275,21 @@ static struct fmtpattern } 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 + {'b', "\\d\\+"}, // 1 + {'n', "\\d\\+"}, // 2 + {'l', "\\d\\+"}, // 3 + {'e', "\\d\\+"}, // 4 + {'c', "\\d\\+"}, // 5 + {'k', "\\d\\+"}, // 6 + {'t', "."}, // 7 +#define FMT_PATTERN_M 8 + {'m', ".\\+"}, // 8 +#define FMT_PATTERN_R 9 + {'r', ".*"}, // 9 + {'p', "[- .]*"}, // 10 + {'v', "\\d\\+"}, // 11 + {'s', ".\\+"}, // 12 + {'o', ".\\+"} // 13 }; /* @@ -942,6 +943,7 @@ qf_get_nextline(qfstate_T *state) typedef struct { char_u *namebuf; + int bnr; char_u *module; char_u *errmsg; int errmsglen; @@ -989,6 +991,22 @@ qf_parse_fmt_f(regmatch_T *rmp, int midx * Return the matched value in "fields->enr". */ static int +qf_parse_fmt_b(regmatch_T *rmp, int midx, qffields_T *fields) +{ + if (rmp->startp[midx] == NULL) + return QF_FAIL; + int bnr = (int)atol((char *)rmp->startp[midx]); + if (buflist_findnr(bnr) == NULL) + return QF_FAIL; + fields->bnr = bnr; + return QF_OK; +} + +/* + * Parse the match for error number ('%n') pattern in regmatch. + * Return the matched value in "fields->enr". + */ + static int qf_parse_fmt_n(regmatch_T *rmp, int midx, qffields_T *fields) { if (rmp->startp[midx] == NULL) @@ -1213,6 +1231,7 @@ qf_parse_fmt_o(regmatch_T *rmp, int midx static int (*qf_parse_fmt[FMT_PATTERNS])(regmatch_T *, int, qffields_T *) = { NULL, // %f + qf_parse_fmt_b, qf_parse_fmt_n, qf_parse_fmt_l, qf_parse_fmt_e, @@ -1309,6 +1328,7 @@ qf_parse_get_fields( return QF_FAIL; fields->namebuf[0] = NUL; + fields->bnr = 0; fields->module[0] = NUL; fields->pattern[0] = NUL; if (!qf_multiscan) @@ -1713,7 +1733,7 @@ qf_init_process_nextline( : ((qfl->qf_currfile != NULL && fields->valid) ? qfl->qf_currfile : (char_u *)NULL), fields->module, - 0, + fields->bnr, fields->errmsg, fields->lnum, fields->end_lnum, diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -6447,4 +6447,53 @@ func Test_quickfix_buffer_contents() call setqflist([], 'f') endfunc +" Test for "%b" in "errorformat" +func Test_efm_format_b() + call setqflist([], 'f') + new + call setline(1, ['1: abc', '1: def', '1: ghi']) + let b1 = bufnr() + new + call setline(1, ['2: abc', '2: def', '2: ghi']) + let b2 = bufnr() + new + call setline(1, ['3: abc', '3: def', '3: ghi']) + let b3 = bufnr() + new + let lines =<< trim eval END + {b1}:1:1 + {b2}:2:2 + {b3}:3:3 + END + call setqflist([], ' ', #{lines: lines, efm: '%b:%l:%c'}) + cfirst + call assert_equal([b1, 1, 1], [bufnr(), line('.'), col('.')]) + cnext + call assert_equal([b2, 2, 2], [bufnr(), line('.'), col('.')]) + cnext + call assert_equal([b3, 3, 3], [bufnr(), line('.'), col('.')]) + enew! + + " Use a non-existing buffer + let lines =<< trim eval END + 9991:1:1:m1 + 9992:2:2:m2 + {b3}:3:3:m3 + END + call setqflist([], ' ', #{lines: lines, efm: '%b:%l:%c:%m'}) + cfirst | cnext + call assert_equal([b3, 3, 3], [bufnr(), line('.'), col('.')]) + " Lines with non-existing buffer numbers should be used as non-error lines + call assert_equal([ + \ #{lnum: 0, bufnr: 0, end_lnum: 0, pattern: '', valid: 0, vcol: 0, nr: -1, + \ module: '', type: '', end_col: 0, col: 0, text: '9991:1:1:m1'}, + \ #{lnum: 0, bufnr: 0, end_lnum: 0, pattern: '', valid: 0, vcol: 0, nr: -1, + \ module: '', type: '', end_col: 0, col: 0, text: '9992:2:2:m2'}, + \ #{lnum: 3, bufnr: b3, end_lnum: 0, pattern: '', valid: 1, vcol: 0, + \ nr: -1, module: '', type: '', end_col: 0, col: 3, text: 'm3'}], + \ getqflist()) + %bw! + call setqflist([], 'f') +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -705,6 +705,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2064, +/**/ 2063, /**/ 2062,