Skip to content

Commit 017c0fc

Browse files
ttaylorrgitster
authored andcommitted
grep.[ch]: extend grep_opt to allow showing matched column
To support showing the matched column when calling 'git-grep(1)', teach 'grep_opt' the normal set of options to configure the default behavior and colorization of this feature. Now that we have opt->columnnum, use it to disable short-circuiting over ORs and ANDs so that col and icol are always filled with the earliest matches on each line. In addition, don't return the first match from match_line(), for the same reason. Signed-off-by: Taylor Blau <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 68d686e commit 017c0fc

File tree

2 files changed

+39
-10
lines changed

2 files changed

+39
-10
lines changed

grep.c

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ void init_grep_defaults(void)
4646
color_set(opt->color_filename, "");
4747
color_set(opt->color_function, "");
4848
color_set(opt->color_lineno, "");
49+
color_set(opt->color_columnno, "");
4950
color_set(opt->color_match_context, GIT_COLOR_BOLD_RED);
5051
color_set(opt->color_match_selected, GIT_COLOR_BOLD_RED);
5152
color_set(opt->color_selected, "");
@@ -155,6 +156,7 @@ void grep_init(struct grep_opt *opt, const char *prefix)
155156
opt->extended_regexp_option = def->extended_regexp_option;
156157
opt->pattern_type_option = def->pattern_type_option;
157158
opt->linenum = def->linenum;
159+
opt->columnnum = def->columnnum;
158160
opt->max_depth = def->max_depth;
159161
opt->pathname = def->pathname;
160162
opt->relative = def->relative;
@@ -164,6 +166,7 @@ void grep_init(struct grep_opt *opt, const char *prefix)
164166
color_set(opt->color_filename, def->color_filename);
165167
color_set(opt->color_function, def->color_function);
166168
color_set(opt->color_lineno, def->color_lineno);
169+
color_set(opt->color_columnno, def->color_columnno);
167170
color_set(opt->color_match_context, def->color_match_context);
168171
color_set(opt->color_match_selected, def->color_match_selected);
169172
color_set(opt->color_selected, def->color_selected);
@@ -1277,23 +1280,36 @@ static int match_expr_eval(struct grep_opt *opt, struct grep_expr *x, char *bol,
12771280
0);
12781281
break;
12791282
case GREP_NODE_AND:
1280-
if (!match_expr_eval(opt, x->u.binary.left, bol, eol, ctx, col,
1281-
icol, 0))
1282-
return 0;
1283-
h = match_expr_eval(opt, x->u.binary.right, bol, eol, ctx, col,
1283+
h = match_expr_eval(opt, x->u.binary.left, bol, eol, ctx, col,
12841284
icol, 0);
1285+
if (h || opt->columnnum) {
1286+
/*
1287+
* Don't short-circuit AND when given --column, since a
1288+
* NOT earlier in the tree may turn this into an OR. In
1289+
* this case, see the below comment.
1290+
*/
1291+
h &= match_expr_eval(opt, x->u.binary.right, bol, eol,
1292+
ctx, col, icol, 0);
1293+
}
12851294
break;
12861295
case GREP_NODE_OR:
1287-
if (!collect_hits)
1296+
if (!(collect_hits || opt->columnnum)) {
1297+
/*
1298+
* Don't short-circuit OR when given --column (or
1299+
* collecting hits) to ensure we don't skip a later
1300+
* child that would produce an earlier match.
1301+
*/
12881302
return (match_expr_eval(opt, x->u.binary.left, bol, eol,
12891303
ctx, col, icol, 0) ||
12901304
match_expr_eval(opt, x->u.binary.right, bol,
12911305
eol, ctx, col, icol, 0));
1306+
}
12921307
h = match_expr_eval(opt, x->u.binary.left, bol, eol, ctx, col,
12931308
icol, 0);
1294-
x->u.binary.left->hit |= h;
1309+
if (collect_hits)
1310+
x->u.binary.left->hit |= h;
12951311
h |= match_expr_eval(opt, x->u.binary.right, bol, eol, ctx, col,
1296-
icol, 1);
1312+
icol, collect_hits);
12971313
break;
12981314
default:
12991315
die("Unexpected node type (internal error) %d", x->node);
@@ -1316,6 +1332,7 @@ static int match_line(struct grep_opt *opt, char *bol, char *eol,
13161332
enum grep_context ctx, int collect_hits)
13171333
{
13181334
struct grep_pat *p;
1335+
int hit = 0;
13191336

13201337
if (opt->extended)
13211338
return match_expr(opt, bol, eol, ctx, col, icol,
@@ -1325,11 +1342,21 @@ static int match_line(struct grep_opt *opt, char *bol, char *eol,
13251342
for (p = opt->pattern_list; p; p = p->next) {
13261343
regmatch_t tmp;
13271344
if (match_one_pattern(p, bol, eol, ctx, &tmp, 0)) {
1328-
*col = tmp.rm_so;
1329-
return 1;
1345+
hit |= 1;
1346+
if (!opt->columnnum) {
1347+
/*
1348+
* Without --column, any single match on a line
1349+
* is enough to know that it needs to be
1350+
* printed. With --column, scan _all_ patterns
1351+
* to find the earliest.
1352+
*/
1353+
break;
1354+
}
1355+
if (*col < 0 || tmp.rm_so < *col)
1356+
*col = tmp.rm_so;
13301357
}
13311358
}
1332-
return 0;
1359+
return hit;
13331360
}
13341361

13351362
static int match_next_pattern(struct grep_pat *p, char *bol, char *eol,

grep.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ struct grep_opt {
127127
int prefix_length;
128128
regex_t regexp;
129129
int linenum;
130+
int columnnum;
130131
int invert;
131132
int ignore_case;
132133
int status_only;
@@ -159,6 +160,7 @@ struct grep_opt {
159160
char color_filename[COLOR_MAXLEN];
160161
char color_function[COLOR_MAXLEN];
161162
char color_lineno[COLOR_MAXLEN];
163+
char color_columnno[COLOR_MAXLEN];
162164
char color_match_context[COLOR_MAXLEN];
163165
char color_match_selected[COLOR_MAXLEN];
164166
char color_selected[COLOR_MAXLEN];

0 commit comments

Comments
 (0)