[-l | --files-with-matches] [-L | --files-without-match]
[-z | --null]
[-c | --count] [--all-match]
+ [--color | --no-color]
[-A <post-context>] [-B <pre-context>] [-C <context>]
[-f <file>] [-e] <pattern>
[--and|--or|--not|(|)|-e <pattern>...] [<tree>...]
Instead of showing every matched line, show the number of
lines that match.
+--color::
+ Show colored matches.
+
+--no-color::
+ Turn off match highlighting, even when the configuration file
+ gives the default to color output.
+
-[ABC] <context>::
Show `context` trailing (`A` -- after), or leading (`B`
-- before), or both (`C` -- context) lines, and place a
static int builtin_grep;
+static int grep_config(const char *var, const char *value, void *cb)
+{
+ struct grep_opt *opt = cb;
+
+ if (!strcmp(var, "grep.color") || !strcmp(var, "color.grep")) {
+ opt->color = git_config_colorbool(var, value, -1);
+ return 0;
+ }
+ if (!strcmp(var, "grep.color.match") ||
+ !strcmp(var, "color.grep.match")) {
+ if (!value)
+ return config_error_nonbool(var);
+ color_parse(value, var, opt->color_match);
+ return 0;
+ }
+ return git_color_default_config(var, value, cb);
+}
+
/*
* git grep pathspecs are somewhat different from diff-tree pathspecs;
* pathname wildcards are allowed.
opt.pattern_tail = &opt.pattern_list;
opt.regflags = REG_NEWLINE;
+ strcpy(opt.color_match, GIT_COLOR_RED GIT_COLOR_BOLD);
+ opt.color = -1;
+ git_config(grep_config, &opt);
+ if (opt.color == -1)
+ opt.color = git_use_color_default;
+
/*
* If there is no -- then the paths must exist in the working
* tree. If there is no explicit pattern specified with -e or
opt.relative = 0;
continue;
}
+ if (!strcmp("--color", arg)) {
+ opt.color = 1;
+ continue;
+ }
+ if (!strcmp("--no-color", arg)) {
+ opt.color = 0;
+ continue;
+ }
if (!strcmp("--", arg)) {
/* later processing wants to have this at argv[1] */
argv--;
return isalnum(ch) || ch == '_';
}
-static void show_line(struct grep_opt *opt, const char *bol, const char *eol,
- const char *name, unsigned lno, char sign)
-{
- if (opt->null_following_name)
- sign = '\0';
- if (opt->pathname)
- printf("%s%c", name, sign);
- if (opt->linenum)
- printf("%d%c", lno, sign);
- printf("%.*s\n", (int)(eol-bol), bol);
-}
-
static void show_name(struct grep_opt *opt, const char *name)
{
printf("%s%c", name, opt->null_following_name ? '\0' : '\n');
return 0;
}
+static int match_next_pattern(struct grep_pat *p, char *bol, char *eol,
+ enum grep_context ctx,
+ regmatch_t *pmatch, int eflags)
+{
+ regmatch_t match;
+
+ if (!match_one_pattern(p, bol, eol, ctx, &match, eflags))
+ return 0;
+ if (match.rm_so < 0 || match.rm_eo < 0)
+ return 0;
+ if (pmatch->rm_so >= 0 && pmatch->rm_eo >= 0) {
+ if (match.rm_so > pmatch->rm_so)
+ return 1;
+ if (match.rm_so == pmatch->rm_so && match.rm_eo < pmatch->rm_eo)
+ return 1;
+ }
+ pmatch->rm_so = match.rm_so;
+ pmatch->rm_eo = match.rm_eo;
+ return 1;
+}
+
+static int next_match(struct grep_opt *opt, char *bol, char *eol,
+ enum grep_context ctx, regmatch_t *pmatch, int eflags)
+{
+ struct grep_pat *p;
+ int hit = 0;
+
+ pmatch->rm_so = pmatch->rm_eo = -1;
+ if (bol < eol) {
+ for (p = opt->pattern_list; p; p = p->next) {
+ switch (p->token) {
+ case GREP_PATTERN: /* atom */
+ case GREP_PATTERN_HEAD:
+ case GREP_PATTERN_BODY:
+ hit |= match_next_pattern(p, bol, eol, ctx,
+ pmatch, eflags);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return hit;
+}
+
+static void show_line(struct grep_opt *opt, char *bol, char *eol,
+ const char *name, unsigned lno, char sign)
+{
+ int rest = eol - bol;
+
+ if (opt->null_following_name)
+ sign = '\0';
+ if (opt->pathname)
+ printf("%s%c", name, sign);
+ if (opt->linenum)
+ printf("%d%c", lno, sign);
+ if (opt->color) {
+ regmatch_t match;
+ enum grep_context ctx = GREP_CONTEXT_BODY;
+ int ch = *eol;
+ int eflags = 0;
+
+ *eol = '\0';
+ while (next_match(opt, bol, eol, ctx, &match, eflags)) {
+ printf("%.*s%s%.*s%s",
+ match.rm_so, bol,
+ opt->color_match,
+ match.rm_eo - match.rm_so, bol + match.rm_so,
+ GIT_COLOR_RESET);
+ bol += match.rm_eo;
+ rest -= match.rm_eo;
+ eflags = REG_NOTBOL;
+ }
+ *eol = ch;
+ }
+ printf("%.*s\n", rest, bol);
+}
+
static int grep_buffer_1(struct grep_opt *opt, const char *name,
char *buf, unsigned long size, int collect_hits)
{