Mercurial > vim
comparison src/quickfix.c @ 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 | ac75c145f0a9 |
children | c1d1639b52dd |
comparison
equal
deleted
inserted
replaced
27604:4f782c34c224 | 27605:bf540a32439a |
---|---|
116 }; | 116 }; |
117 | 117 |
118 static qf_info_T ql_info; // global quickfix list | 118 static qf_info_T ql_info; // global quickfix list |
119 static int_u last_qf_id = 0; // Last used quickfix list id | 119 static int_u last_qf_id = 0; // Last used quickfix list id |
120 | 120 |
121 #define FMT_PATTERNS 11 // maximum number of % recognized | 121 #define FMT_PATTERNS 13 // maximum number of % recognized |
122 | 122 |
123 /* | 123 /* |
124 * Structure used to hold the info of one part of 'errorformat' | 124 * Structure used to hold the info of one part of 'errorformat' |
125 */ | 125 */ |
126 typedef struct efm_S efm_T; | 126 typedef struct efm_S efm_T; |
222 /* | 222 /* |
223 * Maximum number of bytes allowed per line while reading a errorfile. | 223 * Maximum number of bytes allowed per line while reading a errorfile. |
224 */ | 224 */ |
225 #define LINE_MAXLEN 4096 | 225 #define LINE_MAXLEN 4096 |
226 | 226 |
227 /* | |
228 * Patterns used. Keep in sync with qf_parse_fmt[]. | |
229 */ | |
227 static struct fmtpattern | 230 static struct fmtpattern |
228 { | 231 { |
229 char_u convchar; | 232 char_u convchar; |
230 char *pattern; | 233 char *pattern; |
231 } fmt_pat[FMT_PATTERNS] = | 234 } fmt_pat[FMT_PATTERNS] = |
232 { | 235 { |
233 {'f', ".\\+"}, // only used when at end | 236 {'f', ".\\+"}, // only used when at end |
234 {'n', "\\d\\+"}, | 237 {'n', "\\d\\+"}, // 1 |
235 {'l', "\\d\\+"}, | 238 {'l', "\\d\\+"}, // 2 |
236 {'c', "\\d\\+"}, | 239 {'e', "\\d\\+"}, // 3 |
237 {'t', "."}, | 240 {'c', "\\d\\+"}, // 4 |
238 {'m', ".\\+"}, | 241 {'k', "\\d\\+"}, // 5 |
239 {'r', ".*"}, | 242 {'t', "."}, // 6 |
240 {'p', "[- .]*"}, | 243 #define FMT_PATTERN_M 7 |
241 {'v', "\\d\\+"}, | 244 {'m', ".\\+"}, // 7 |
242 {'s', ".\\+"}, | 245 #define FMT_PATTERN_R 8 |
243 {'o', ".\\+"} | 246 {'r', ".*"}, // 8 |
247 {'p', "[- .]*"}, // 9 | |
248 {'v', "\\d\\+"}, // 10 | |
249 {'s', ".\\+"}, // 11 | |
250 {'o', ".\\+"} // 12 | |
244 }; | 251 }; |
245 | 252 |
246 /* | 253 /* |
247 * Convert an errorformat pattern to a regular expression pattern. | 254 * Convert an errorformat pattern to a regular expression pattern. |
248 * See fmt_pat definition above for the list of supported patterns. The | 255 * See fmt_pat definition above for the list of supported patterns. The |
263 { | 270 { |
264 // Each errorformat pattern can occur only once | 271 // Each errorformat pattern can occur only once |
265 semsg(_(e_too_many_chr_in_format_string), *efmpat); | 272 semsg(_(e_too_many_chr_in_format_string), *efmpat); |
266 return NULL; | 273 return NULL; |
267 } | 274 } |
268 if ((idx && idx < 6 | 275 if ((idx && idx < FMT_PATTERN_R |
269 && vim_strchr((char_u *)"DXOPQ", efminfo->prefix) != NULL) | 276 && vim_strchr((char_u *)"DXOPQ", efminfo->prefix) != NULL) |
270 || (idx == 6 | 277 || (idx == FMT_PATTERN_R |
271 && vim_strchr((char_u *)"OPQ", efminfo->prefix) == NULL)) | 278 && vim_strchr((char_u *)"OPQ", efminfo->prefix) == NULL)) |
272 { | 279 { |
273 semsg(_(e_unexpected_chr_in_format_str), *efmpat); | 280 semsg(_(e_unexpected_chr_in_format_str), *efmpat); |
274 return NULL; | 281 return NULL; |
275 } | 282 } |
946 fields->enr = (int)atol((char *)rmp->startp[midx]); | 953 fields->enr = (int)atol((char *)rmp->startp[midx]); |
947 return QF_OK; | 954 return QF_OK; |
948 } | 955 } |
949 | 956 |
950 /* | 957 /* |
951 * Parse the match for line number (%l') pattern in regmatch. | 958 * Parse the match for line number ('%l') pattern in regmatch. |
952 * Return the matched value in "fields->lnum". | 959 * Return the matched value in "fields->lnum". |
953 */ | 960 */ |
954 static int | 961 static int |
955 qf_parse_fmt_l(regmatch_T *rmp, int midx, qffields_T *fields) | 962 qf_parse_fmt_l(regmatch_T *rmp, int midx, qffields_T *fields) |
956 { | 963 { |
959 fields->lnum = atol((char *)rmp->startp[midx]); | 966 fields->lnum = atol((char *)rmp->startp[midx]); |
960 return QF_OK; | 967 return QF_OK; |
961 } | 968 } |
962 | 969 |
963 /* | 970 /* |
971 * Parse the match for end line number ('%e') pattern in regmatch. | |
972 * Return the matched value in "fields->end_lnum". | |
973 */ | |
974 static int | |
975 qf_parse_fmt_e(regmatch_T *rmp, int midx, qffields_T *fields) | |
976 { | |
977 if (rmp->startp[midx] == NULL) | |
978 return QF_FAIL; | |
979 fields->end_lnum = atol((char *)rmp->startp[midx]); | |
980 return QF_OK; | |
981 } | |
982 | |
983 /* | |
964 * Parse the match for column number ('%c') pattern in regmatch. | 984 * Parse the match for column number ('%c') pattern in regmatch. |
965 * Return the matched value in "fields->col". | 985 * Return the matched value in "fields->col". |
966 */ | 986 */ |
967 static int | 987 static int |
968 qf_parse_fmt_c(regmatch_T *rmp, int midx, qffields_T *fields) | 988 qf_parse_fmt_c(regmatch_T *rmp, int midx, qffields_T *fields) |
969 { | 989 { |
970 if (rmp->startp[midx] == NULL) | 990 if (rmp->startp[midx] == NULL) |
971 return QF_FAIL; | 991 return QF_FAIL; |
972 fields->col = (int)atol((char *)rmp->startp[midx]); | 992 fields->col = (int)atol((char *)rmp->startp[midx]); |
993 return QF_OK; | |
994 } | |
995 | |
996 /* | |
997 * Parse the match for end column number ('%k') pattern in regmatch. | |
998 * Return the matched value in "fields->end_col". | |
999 */ | |
1000 static int | |
1001 qf_parse_fmt_k(regmatch_T *rmp, int midx, qffields_T *fields) | |
1002 { | |
1003 if (rmp->startp[midx] == NULL) | |
1004 return QF_FAIL; | |
1005 fields->end_col = (int)atol((char *)rmp->startp[midx]); | |
973 return QF_OK; | 1006 return QF_OK; |
974 } | 1007 } |
975 | 1008 |
976 /* | 1009 /* |
977 * Parse the match for error type ('%t') pattern in regmatch. | 1010 * Parse the match for error type ('%t') pattern in regmatch. |
1130 | 1163 |
1131 /* | 1164 /* |
1132 * 'errorformat' format pattern parser functions. | 1165 * 'errorformat' format pattern parser functions. |
1133 * The '%f' and '%r' formats are parsed differently from other formats. | 1166 * The '%f' and '%r' formats are parsed differently from other formats. |
1134 * See qf_parse_match() for details. | 1167 * See qf_parse_match() for details. |
1168 * Keep in sync with fmt_pat[]. | |
1135 */ | 1169 */ |
1136 static int (*qf_parse_fmt[FMT_PATTERNS])(regmatch_T *, int, qffields_T *) = | 1170 static int (*qf_parse_fmt[FMT_PATTERNS])(regmatch_T *, int, qffields_T *) = |
1137 { | 1171 { |
1138 NULL, | 1172 NULL, // %f |
1139 qf_parse_fmt_n, | 1173 qf_parse_fmt_n, |
1140 qf_parse_fmt_l, | 1174 qf_parse_fmt_l, |
1175 qf_parse_fmt_e, | |
1141 qf_parse_fmt_c, | 1176 qf_parse_fmt_c, |
1177 qf_parse_fmt_k, | |
1142 qf_parse_fmt_t, | 1178 qf_parse_fmt_t, |
1143 qf_parse_fmt_m, | 1179 qf_parse_fmt_m, |
1144 NULL, | 1180 NULL, // %r |
1145 qf_parse_fmt_p, | 1181 qf_parse_fmt_p, |
1146 qf_parse_fmt_v, | 1182 qf_parse_fmt_v, |
1147 qf_parse_fmt_s, | 1183 qf_parse_fmt_s, |
1148 qf_parse_fmt_o | 1184 qf_parse_fmt_o |
1149 }; | 1185 }; |
1184 { | 1220 { |
1185 status = QF_OK; | 1221 status = QF_OK; |
1186 midx = (int)fmt_ptr->addr[i]; | 1222 midx = (int)fmt_ptr->addr[i]; |
1187 if (i == 0 && midx > 0) // %f | 1223 if (i == 0 && midx > 0) // %f |
1188 status = qf_parse_fmt_f(regmatch, midx, fields, idx); | 1224 status = qf_parse_fmt_f(regmatch, midx, fields, idx); |
1189 else if (i == 5) | 1225 else if (i == FMT_PATTERN_M) |
1190 { | 1226 { |
1191 if (fmt_ptr->flags == '+' && !qf_multiscan) // %+ | 1227 if (fmt_ptr->flags == '+' && !qf_multiscan) // %+ |
1192 status = copy_nonerror_line(linebuf, linelen, fields); | 1228 status = copy_nonerror_line(linebuf, linelen, fields); |
1193 else if (midx > 0) // %m | 1229 else if (midx > 0) // %m |
1194 status = qf_parse_fmt_m(regmatch, midx, fields); | 1230 status = qf_parse_fmt_m(regmatch, midx, fields); |
1195 } | 1231 } |
1196 else if (i == 6 && midx > 0) // %r | 1232 else if (i == FMT_PATTERN_R && midx > 0) // %r |
1197 status = qf_parse_fmt_r(regmatch, midx, tail); | 1233 status = qf_parse_fmt_r(regmatch, midx, tail); |
1198 else if (midx > 0) // others | 1234 else if (midx > 0) // others |
1199 status = (qf_parse_fmt[i])(regmatch, midx, fields); | 1235 status = (qf_parse_fmt[i])(regmatch, midx, fields); |
1200 | 1236 |
1201 if (status != QF_OK) | 1237 if (status != QF_OK) |
1361 // only printable chars allowed | 1397 // only printable chars allowed |
1362 qfprev->qf_type = fields->type; | 1398 qfprev->qf_type = fields->type; |
1363 | 1399 |
1364 if (!qfprev->qf_lnum) | 1400 if (!qfprev->qf_lnum) |
1365 qfprev->qf_lnum = fields->lnum; | 1401 qfprev->qf_lnum = fields->lnum; |
1402 if (!qfprev->qf_end_lnum) | |
1403 qfprev->qf_end_lnum = fields->end_lnum; | |
1366 if (!qfprev->qf_col) | 1404 if (!qfprev->qf_col) |
1367 { | 1405 { |
1368 qfprev->qf_col = fields->col; | 1406 qfprev->qf_col = fields->col; |
1369 qfprev->qf_viscol = fields->use_viscol; | 1407 qfprev->qf_viscol = fields->use_viscol; |
1370 } | 1408 } |
1409 if (!qfprev->qf_end_col) | |
1410 qfprev->qf_end_col = fields->end_col; | |
1371 if (!qfprev->qf_fnum) | 1411 if (!qfprev->qf_fnum) |
1372 qfprev->qf_fnum = qf_get_fnum(qfl, | 1412 qfprev->qf_fnum = qf_get_fnum(qfl, |
1373 qfl->qf_directory, | 1413 qfl->qf_directory, |
1374 *fields->namebuf || qfl->qf_directory != NULL | 1414 *fields->namebuf || qfl->qf_directory != NULL |
1375 ? fields->namebuf | 1415 ? fields->namebuf |