Browse Source

Merge branch 'rs/grep-color'

* rs/grep-color:
  grep: add --heading
  grep: add --break
  grep: fix coloring of hunk marks between files
maint
Junio C Hamano 14 years ago
parent
commit
1692d0c64a
  1. 7
      Documentation/git-grep.txt
  2. 29
      builtin/grep.c
  3. 26
      grep.c
  4. 2
      grep.h
  5. 95
      t/t7810-grep.sh

7
Documentation/git-grep.txt

@ -148,6 +148,13 @@ OPTIONS @@ -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

29
builtin/grep.c

@ -93,8 +93,7 @@ static pthread_cond_t cond_write; @@ -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)
{
@ -160,10 +159,20 @@ static void work_done(struct work_item *w) @@ -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);
@ -813,6 +822,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix) @@ -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",
@ -967,8 +980,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix) @@ -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

26
grep.c

@ -721,7 +721,10 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol, @@ -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);
@ -732,9 +735,13 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol, @@ -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);
}
@ -941,9 +948,18 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name, @@ -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) {

2
grep.h

@ -110,6 +110,8 @@ struct grep_opt { @@ -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);

95
t/t7810-grep.sh

@ -716,4 +716,99 @@ test_expect_success LIBPCRE 'grep -G -F -E -P pattern' ' @@ -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

Loading…
Cancel
Save