Merge branch 'tb/grep-only-matching'
"git grep" learned the "--only-matching" option. * tb/grep-only-matching: grep.c: teach 'git grep --only-matching' grep.c: extract show_line_header()
This commit is contained in:
commit
87ece7ce11
@ -17,7 +17,7 @@ SYNOPSIS
|
||||
[-l | --files-with-matches] [-L | --files-without-match]
|
||||
[(-O | --open-files-in-pager) [<pager>]]
|
||||
[-z | --null]
|
||||
[-c | --count] [--all-match] [-q | --quiet]
|
||||
[ -o | --only-matching ] [-c | --count] [--all-match] [-q | --quiet]
|
||||
[--max-depth <depth>]
|
||||
[--color[=<when>] | --no-color]
|
||||
[--break] [--heading] [-p | --show-function]
|
||||
@ -201,6 +201,11 @@ providing this option will cause it to die.
|
||||
Output \0 instead of the character that normally follows a
|
||||
file name.
|
||||
|
||||
-o::
|
||||
--only-matching::
|
||||
Print only the matched (non-empty) parts of a matching line, with each such
|
||||
part on a separate output line.
|
||||
|
||||
-c::
|
||||
--count::
|
||||
Instead of showing every matched line, show the number of
|
||||
|
@ -844,6 +844,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
OPT_BOOL_F('z', "null", &opt.null_following_name,
|
||||
N_("print NUL after filenames"),
|
||||
PARSE_OPT_NOCOMPLETE),
|
||||
OPT_BOOL('o', "only-matching", &opt.only_matching,
|
||||
N_("show only matching parts of a line")),
|
||||
OPT_BOOL('c', "count", &opt.count,
|
||||
N_("show the number of matches instead of matching lines")),
|
||||
OPT__COLOR(&opt.color, N_("highlight matches")),
|
||||
@ -963,6 +965,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
if (!opt.pattern_list)
|
||||
die(_("no pattern given."));
|
||||
|
||||
/* --only-matching has no effect with --invert. */
|
||||
if (opt.invert)
|
||||
opt.only_matching = 0;
|
||||
|
||||
/*
|
||||
* We have to find "--" in a separate pass, because its presence
|
||||
* influences how we will parse arguments that come before it.
|
||||
|
91
grep.c
91
grep.c
@ -65,6 +65,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;
|
||||
}
|
||||
@ -159,6 +160,7 @@ void grep_init(struct grep_opt *opt, const char *prefix)
|
||||
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 +1406,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 +1436,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
|
||||
|
1
grep.h
1
grep.h
@ -163,6 +163,7 @@ struct grep_opt {
|
||||
int relative;
|
||||
int pathname;
|
||||
int null_following_name;
|
||||
int only_matching;
|
||||
int color;
|
||||
int max_depth;
|
||||
int funcname;
|
||||
|
@ -262,6 +262,21 @@ do
|
||||
fi
|
||||
'
|
||||
|
||||
test_expect_success "grep $L (with --column, --only-matching)" '
|
||||
{
|
||||
echo ${HC}file:1:5:mmap
|
||||
echo ${HC}file:2:5:mmap
|
||||
echo ${HC}file:3:5:mmap
|
||||
echo ${HC}file:3:13:mmap
|
||||
echo ${HC}file:4:5:mmap
|
||||
echo ${HC}file:4:13:mmap
|
||||
echo ${HC}file:5:5:mmap
|
||||
echo ${HC}file:5:13:mmap
|
||||
} >expected &&
|
||||
git grep --column -n -o -e mmap $H >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success "grep $L (t-1)" '
|
||||
echo "${HC}t/t:1:test" >expected &&
|
||||
git grep -n -e test $H >actual &&
|
||||
|
Loading…
Reference in New Issue
Block a user