diff options
Diffstat (limited to 'grep.c')
-rw-r--r-- | grep.c | 125 |
1 files changed, 78 insertions, 47 deletions
@@ -11,7 +11,8 @@ #include "help.h" static int grep_source_load(struct grep_source *gs); -static int grep_source_is_binary(struct grep_source *gs); +static int grep_source_is_binary(struct grep_source *gs, + struct index_state *istate); static struct grep_opt grep_defaults; @@ -42,7 +43,7 @@ static void color_set(char *dst, const char *color_bytes) * We could let the compiler do this, but without C99 initializers * the code gets unwieldy and unreadable, so... */ -void init_grep_defaults(void) +void init_grep_defaults(struct repository *repo) { struct grep_opt *opt = &grep_defaults; static int run_once; @@ -52,6 +53,7 @@ void init_grep_defaults(void) run_once++; memset(opt, 0, sizeof(*opt)); + opt->repo = repo; opt->relative = 1; opt->pathname = 1; opt->max_depth = -1; @@ -65,6 +67,7 @@ void init_grep_defaults(void) color_set(opt->colors[GREP_COLOR_MATCH_SELECTED], GIT_COLOR_BOLD_RED); color_set(opt->colors[GREP_COLOR_SELECTED], ""); color_set(opt->colors[GREP_COLOR_SEP], GIT_COLOR_CYAN); + opt->only_matching = 0; opt->color = -1; opt->output = std_output; } @@ -148,17 +151,19 @@ int grep_config(const char *var, const char *value, void *cb) * default values from the template we read the configuration * information in an earlier call to git_config(grep_config). */ -void grep_init(struct grep_opt *opt, const char *prefix) +void grep_init(struct grep_opt *opt, struct repository *repo, const char *prefix) { struct grep_opt *def = &grep_defaults; int i; memset(opt, 0, sizeof(*opt)); + opt->repo = repo; opt->prefix = prefix; opt->prefix_length = (prefix && *prefix) ? strlen(prefix) : 0; opt->pattern_tail = &opt->pattern_list; opt->header_tail = &opt->header_list; + opt->only_matching = def->only_matching; opt->color = def->color; opt->extended_regexp_option = def->extended_regexp_option; opt->pattern_type_option = def->pattern_type_option; @@ -1404,26 +1409,9 @@ static int next_match(struct grep_opt *opt, char *bol, char *eol, return hit; } -static void show_line(struct grep_opt *opt, char *bol, char *eol, - const char *name, unsigned lno, ssize_t cno, char sign) +static void show_line_header(struct grep_opt *opt, const char *name, + unsigned lno, ssize_t cno, char sign) { - int rest = eol - bol; - const char *match_color, *line_color = NULL; - - if (opt->file_break && opt->last_shown == 0) { - if (opt->show_hunk_mark) - opt->output(opt, "\n", 1); - } else if (opt->pre_context || opt->post_context || opt->funcbody) { - if (opt->last_shown == 0) { - if (opt->show_hunk_mark) { - output_color(opt, "--", 2, opt->colors[GREP_COLOR_SEP]); - opt->output(opt, "\n", 1); - } - } else if (lno > opt->last_shown + 1) { - output_color(opt, "--", 2, opt->colors[GREP_COLOR_SEP]); - opt->output(opt, "\n", 1); - } - } if (opt->heading && opt->last_shown == 0) { output_color(opt, name, strlen(name), opt->colors[GREP_COLOR_FILENAME]); opt->output(opt, "\n", 1); @@ -1451,38 +1439,78 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol, output_color(opt, buf, strlen(buf), opt->colors[GREP_COLOR_COLUMNNO]); output_sep(opt, sign); } - if (opt->color) { +} + +static void show_line(struct grep_opt *opt, char *bol, char *eol, + const char *name, unsigned lno, ssize_t cno, char sign) +{ + int rest = eol - bol; + const char *match_color = NULL; + const char *line_color = NULL; + + if (opt->file_break && opt->last_shown == 0) { + if (opt->show_hunk_mark) + opt->output(opt, "\n", 1); + } else if (opt->pre_context || opt->post_context || opt->funcbody) { + if (opt->last_shown == 0) { + if (opt->show_hunk_mark) { + output_color(opt, "--", 2, opt->colors[GREP_COLOR_SEP]); + opt->output(opt, "\n", 1); + } + } else if (lno > opt->last_shown + 1) { + output_color(opt, "--", 2, opt->colors[GREP_COLOR_SEP]); + opt->output(opt, "\n", 1); + } + } + if (!opt->only_matching) { + /* + * In case the line we're being called with contains more than + * one match, leave printing each header to the loop below. + */ + show_line_header(opt, name, lno, cno, sign); + } + if (opt->color || opt->only_matching) { regmatch_t match; enum grep_context ctx = GREP_CONTEXT_BODY; int ch = *eol; int eflags = 0; - if (sign == ':') - match_color = opt->colors[GREP_COLOR_MATCH_SELECTED]; - else - match_color = opt->colors[GREP_COLOR_MATCH_CONTEXT]; - if (sign == ':') - line_color = opt->colors[GREP_COLOR_SELECTED]; - else if (sign == '-') - line_color = opt->colors[GREP_COLOR_CONTEXT]; - else if (sign == '=') - line_color = opt->colors[GREP_COLOR_FUNCTION]; + if (opt->color) { + if (sign == ':') + match_color = opt->colors[GREP_COLOR_MATCH_SELECTED]; + else + match_color = opt->colors[GREP_COLOR_MATCH_CONTEXT]; + if (sign == ':') + line_color = opt->colors[GREP_COLOR_SELECTED]; + else if (sign == '-') + line_color = opt->colors[GREP_COLOR_CONTEXT]; + else if (sign == '=') + line_color = opt->colors[GREP_COLOR_FUNCTION]; + } *eol = '\0'; while (next_match(opt, bol, eol, ctx, &match, eflags)) { if (match.rm_so == match.rm_eo) break; - output_color(opt, bol, match.rm_so, line_color); + if (opt->only_matching) + show_line_header(opt, name, lno, cno, sign); + else + output_color(opt, bol, match.rm_so, line_color); output_color(opt, bol + match.rm_so, match.rm_eo - match.rm_so, match_color); + if (opt->only_matching) + opt->output(opt, "\n", 1); bol += match.rm_eo; + cno += match.rm_eo; rest -= match.rm_eo; eflags = REG_NOTBOL; } *eol = ch; } - output_color(opt, bol, rest, line_color); - opt->output(opt, "\n", 1); + if (!opt->only_matching) { + output_color(opt, bol, rest, line_color); + opt->output(opt, "\n", 1); + } } #ifndef NO_PTHREADS @@ -1520,7 +1548,7 @@ static int match_funcname(struct grep_opt *opt, struct grep_source *gs, char *bo { xdemitconf_t *xecfg = opt->priv; if (xecfg && !xecfg->find_func) { - grep_source_load_driver(gs); + grep_source_load_driver(gs, opt->repo->index); if (gs->driver->funcname.pattern) { const struct userdiff_funcname *pe = &gs->driver->funcname; xdiff_set_find_func(xecfg, pe->pattern, pe->cflags); @@ -1683,7 +1711,8 @@ static int look_ahead(struct grep_opt *opt, return 0; } -static int fill_textconv_grep(struct userdiff_driver *driver, +static int fill_textconv_grep(struct repository *r, + struct userdiff_driver *driver, struct grep_source *gs) { struct diff_filespec *df; @@ -1716,7 +1745,7 @@ static int fill_textconv_grep(struct userdiff_driver *driver, * structure. */ grep_read_lock(); - size = fill_textconv(driver, df, &buf); + size = fill_textconv(r, driver, df, &buf); grep_read_unlock(); free_filespec(df); @@ -1776,7 +1805,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle opt->last_shown = 0; if (opt->allow_textconv) { - grep_source_load_driver(gs); + grep_source_load_driver(gs, opt->repo->index); /* * We might set up the shared textconv cache data here, which * is not thread-safe. @@ -1793,11 +1822,11 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle if (!textconv) { switch (opt->binary) { case GREP_BINARY_DEFAULT: - if (grep_source_is_binary(gs)) + if (grep_source_is_binary(gs, opt->repo->index)) binary_match_only = 1; break; case GREP_BINARY_NOMATCH: - if (grep_source_is_binary(gs)) + if (grep_source_is_binary(gs, opt->repo->index)) return 0; /* Assume unmatch */ break; case GREP_BINARY_TEXT: @@ -1812,7 +1841,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle try_lookahead = should_lookahead(opt); - if (fill_textconv_grep(textconv, gs) < 0) + if (fill_textconv_grep(opt->repo, textconv, gs) < 0) return 0; bol = gs->buf; @@ -2143,22 +2172,24 @@ static int grep_source_load(struct grep_source *gs) BUG("invalid grep_source type to load"); } -void grep_source_load_driver(struct grep_source *gs) +void grep_source_load_driver(struct grep_source *gs, + struct index_state *istate) { if (gs->driver) return; grep_attr_lock(); if (gs->path) - gs->driver = userdiff_find_by_path(gs->path); + gs->driver = userdiff_find_by_path(istate, gs->path); if (!gs->driver) gs->driver = userdiff_find_by_name("default"); grep_attr_unlock(); } -static int grep_source_is_binary(struct grep_source *gs) +static int grep_source_is_binary(struct grep_source *gs, + struct index_state *istate) { - grep_source_load_driver(gs); + grep_source_load_driver(gs, istate); if (gs->driver->binary != -1) return gs->driver->binary; |