To: vim_dev@googlegroups.com Subject: Patch 8.2.4329 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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 == 1 character column)) %v virtual column number (finds a number representing screen column of the error (1 == 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 is 1 ! character column) %v virtual column number (finds a number representing screen column of the error (1 == 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 -- Bram@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 ///