Skip to content

Commit

Permalink
Merge branch 'rs/grep-color'
Browse files Browse the repository at this point in the history
* rs/grep-color:
  grep: add --heading
  grep: add --break
  grep: fix coloring of hunk marks between files
  • Loading branch information
Junio C Hamano committed Jun 30, 2011
2 parents b985f2a + 1d84f72 commit 1692d0c
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 13 deletions.
7 changes: 7 additions & 0 deletions Documentation/git-grep.txt
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,13 @@ OPTIONS
gives the default to color output.
Same as `--color=never`.

--break::
Print an empty line between matches from different files.

--heading::
Show the filename above the matches in that file instead of
at the start of each shown line.

-[ABC] <context>::
Show `context` trailing (`A` -- after), or leading (`B`
-- before), or both (`C` -- context) lines, and place a
Expand Down
29 changes: 21 additions & 8 deletions builtin/grep.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,7 @@ static pthread_cond_t cond_write;
/* Signalled when we are finished with everything. */
static pthread_cond_t cond_result;

static int print_hunk_marks_between_files;
static int printed_something;
static int skip_first_line;

static void add_work(enum work_type type, char *name, void *id)
{
Expand Down Expand Up @@ -160,10 +159,20 @@ static void work_done(struct work_item *w)
todo_done = (todo_done+1) % ARRAY_SIZE(todo)) {
w = &todo[todo_done];
if (w->out.len) {
if (print_hunk_marks_between_files && printed_something)
write_or_die(1, "--\n", 3);
write_or_die(1, w->out.buf, w->out.len);
printed_something = 1;
const char *p = w->out.buf;
size_t len = w->out.len;

/* Skip the leading hunk mark of the first file. */
if (skip_first_line) {
while (len) {
len--;
if (*p++ == '\n')
break;
}
skip_first_line = 0;
}

write_or_die(1, p, len);
}
free(w->name);
free(w->identifier);
Expand Down Expand Up @@ -813,6 +822,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
OPT_BOOLEAN('c', "count", &opt.count,
"show the number of matches instead of matching lines"),
OPT__COLOR(&opt.color, "highlight matches"),
OPT_BOOLEAN(0, "break", &opt.file_break,
"print empty line between matches from different files"),
OPT_BOOLEAN(0, "heading", &opt.heading,
"show filename only once above matches from same file"),
OPT_GROUP(""),
OPT_CALLBACK('C', NULL, &opt, "n",
"show <n> context lines before and after matches",
Expand Down Expand Up @@ -967,8 +980,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
use_threads = 0;

if (use_threads) {
if (opt.pre_context || opt.post_context)
print_hunk_marks_between_files = 1;
if (opt.pre_context || opt.post_context || opt.file_break)
skip_first_line = 1;
start_threads(&opt);
}
#else
Expand Down
26 changes: 21 additions & 5 deletions grep.c
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,10 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
int rest = eol - bol;
char *line_color = NULL;

if (opt->pre_context || opt->post_context) {
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) {
if (opt->last_shown == 0) {
if (opt->show_hunk_mark) {
output_color(opt, "--", 2, opt->color_sep);
Expand All @@ -732,9 +735,13 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
opt->output(opt, "\n", 1);
}
}
if (opt->heading && opt->last_shown == 0) {
output_color(opt, name, strlen(name), opt->color_filename);
opt->output(opt, "\n", 1);
}
opt->last_shown = lno;

if (opt->pathname) {
if (!opt->heading && opt->pathname) {
output_color(opt, name, strlen(name), opt->color_filename);
output_sep(opt, sign);
}
Expand Down Expand Up @@ -941,9 +948,18 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
if (!opt->output)
opt->output = std_output;

if (opt->last_shown && (opt->pre_context || opt->post_context) &&
opt->output == std_output)
opt->show_hunk_mark = 1;
if (opt->pre_context || opt->post_context || opt->file_break) {
/* Show hunk marks, except for the first file. */
if (opt->last_shown)
opt->show_hunk_mark = 1;
/*
* If we're using threads then we can't easily identify
* the first file. Always put hunk marks in that case
* and skip the very first one later in work_done().
*/
if (opt->output != std_output)
opt->show_hunk_mark = 1;
}
opt->last_shown = 0;

switch (opt->binary) {
Expand Down
2 changes: 2 additions & 0 deletions grep.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ struct grep_opt {
unsigned post_context;
unsigned last_shown;
int show_hunk_mark;
int file_break;
int heading;
void *priv;

void (*output)(struct grep_opt *opt, const void *data, size_t size);
Expand Down
95 changes: 95 additions & 0 deletions t/t7810-grep.sh
Original file line number Diff line number Diff line change
Expand Up @@ -716,4 +716,99 @@ test_expect_success LIBPCRE 'grep -G -F -E -P pattern' '
test_cmp expected actual
'

test_config() {
git config "$1" "$2" &&
test_when_finished "git config --unset $1"
}

cat >expected <<EOF
hello.c<RED>:<RESET>int main(int argc, const char **argv)
hello.c<RED>-<RESET>{
<RED>--<RESET>
hello.c<RED>:<RESET> /* char ?? */
hello.c<RED>-<RESET>}
<RED>--<RESET>
hello_world<RED>:<RESET>Hello_world
hello_world<RED>-<RESET>HeLLo_world
EOF

test_expect_success 'grep --color, separator' '
test_config color.grep.context normal &&
test_config color.grep.filename normal &&
test_config color.grep.function normal &&
test_config color.grep.linenumber normal &&
test_config color.grep.match normal &&
test_config color.grep.selected normal &&
test_config color.grep.separator red &&
git grep --color=always -A1 -e char -e lo_w hello.c hello_world |
test_decode_color >actual &&
test_cmp expected actual
'

cat >expected <<EOF
hello.c:int main(int argc, const char **argv)
hello.c: /* char ?? */
hello_world:Hello_world
EOF

test_expect_success 'grep --break' '
git grep --break -e char -e lo_w hello.c hello_world >actual &&
test_cmp expected actual
'

cat >expected <<EOF
hello.c:int main(int argc, const char **argv)
hello.c-{
--
hello.c: /* char ?? */
hello.c-}
hello_world:Hello_world
hello_world-HeLLo_world
EOF

test_expect_success 'grep --break with context' '
git grep --break -A1 -e char -e lo_w hello.c hello_world >actual &&
test_cmp expected actual
'

cat >expected <<EOF
hello.c
int main(int argc, const char **argv)
/* char ?? */
hello_world
Hello_world
EOF

test_expect_success 'grep --heading' '
git grep --heading -e char -e lo_w hello.c hello_world >actual &&
test_cmp expected actual
'

cat >expected <<EOF
<BOLD;GREEN>hello.c<RESET>
2:int main(int argc, const <BLACK;BYELLOW>char<RESET> **argv)
6: /* <BLACK;BYELLOW>char<RESET> ?? */
<BOLD;GREEN>hello_world<RESET>
3:Hel<BLACK;BYELLOW>lo_w<RESET>orld
EOF

test_expect_success 'mimic ack-grep --group' '
test_config color.grep.context normal &&
test_config color.grep.filename "bold green" &&
test_config color.grep.function normal &&
test_config color.grep.linenumber normal &&
test_config color.grep.match "black yellow" &&
test_config color.grep.selected normal &&
test_config color.grep.separator normal &&
git grep --break --heading -n --color \
-e char -e lo_w hello.c hello_world |
test_decode_color >actual &&
test_cmp expected actual
'

test_done

0 comments on commit 1692d0c

Please sign in to comment.