From 08303c3636ef750bfafd1c47f363120cb439b367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Sun, 5 Jun 2011 17:24:15 +0200 Subject: grep: fix coloring of hunk marks between files Commit 431d6e7b (grep: enable threading for context line printing) split the printing of the "--\n" mark between results from different files out into two places: show_line() in grep.c for the non-threaded case and work_done() in builtin/grep.c for the threaded case. Commit 55f638bd (grep: Colorize filename, line number, and separator) updated the former, but not the latter, so the separators between files are not colored if threads are used. This patch merges the two. In the threaded case, hunk marks are now printed by show_line() for every file, including the first one, and the very first mark is simply skipped in work_done(). This ensures that the output is properly colored and works just as well. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- builtin/grep.c | 23 ++++++++++++++++------- grep.c | 15 ++++++++++++--- t/t7810-grep.sh | 30 ++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/builtin/grep.c b/builtin/grep.c index 871afaa3c7..0d5a90b94b 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -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) 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); @@ -968,7 +977,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) if (use_threads) { if (opt.pre_context || opt.post_context) - print_hunk_marks_between_files = 1; + skip_first_line = 1; start_threads(&opt); } #else diff --git a/grep.c b/grep.c index d03d9e24c2..3f15085d0e 100644 --- a/grep.c +++ b/grep.c @@ -941,9 +941,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) { + /* 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) { diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index 69bd576d1c..539a8fe6e9 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -716,4 +716,34 @@ 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 <: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 --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 +' + test_done -- cgit v1.2.3 From a8f0e7649eba3ce78e1f09fc4dcbb2c3fcc3d866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Sun, 5 Jun 2011 17:24:25 +0200 Subject: grep: add --break With --break, an empty line is printed between matches from different files, increasing readability. This option is taken from ack (http://betterthangrep.com/). Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- Documentation/git-grep.txt | 3 +++ builtin/grep.c | 4 +++- grep.c | 7 +++++-- grep.h | 1 + t/t7810-grep.sh | 28 ++++++++++++++++++++++++++++ 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt index e150c77cff..dea7cad0c2 100644 --- a/Documentation/git-grep.txt +++ b/Documentation/git-grep.txt @@ -148,6 +148,9 @@ OPTIONS gives the default to color output. Same as `--color=never`. +--break:: + Print an empty line between matches from different files. + -[ABC] :: Show `context` trailing (`A` -- after), or leading (`B` -- before), or both (`C` -- context) lines, and place a diff --git a/builtin/grep.c b/builtin/grep.c index 0d5a90b94b..42bb87f544 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -822,6 +822,8 @@ 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_GROUP(""), OPT_CALLBACK('C', NULL, &opt, "n", "show context lines before and after matches", @@ -976,7 +978,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix) use_threads = 0; if (use_threads) { - if (opt.pre_context || opt.post_context) + if (opt.pre_context || opt.post_context || opt.file_break) skip_first_line = 1; start_threads(&opt); } diff --git a/grep.c b/grep.c index 3f15085d0e..b0b860a984 100644 --- a/grep.c +++ b/grep.c @@ -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); @@ -941,7 +944,7 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name, if (!opt->output) opt->output = std_output; - if (opt->pre_context || opt->post_context) { + 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; diff --git a/grep.h b/grep.h index cd055cdfa8..638bee848d 100644 --- a/grep.h +++ b/grep.h @@ -110,6 +110,7 @@ struct grep_opt { unsigned post_context; unsigned last_shown; int show_hunk_mark; + int file_break; void *priv; void (*output)(struct grep_opt *opt, const void *data, size_t size); diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index 539a8fe6e9..f55793e3cb 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -746,4 +746,32 @@ test_expect_success 'grep --color, separator' ' test_cmp expected actual ' +cat >expected <actual && + test_cmp expected actual +' + +cat >expected <actual && + test_cmp expected actual +' + test_done -- cgit v1.2.3 From 1d84f72ef1dee1f851e11a6d92e8ab3f1979b2a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Sun, 5 Jun 2011 17:24:36 +0200 Subject: grep: add --heading With --heading, the filename is printed once before matches from that file instead of at the start of each line, giving more screen space to the actual search results. This option is taken from ack (http://betterthangrep.com/). And now git grep can dress up like it: $ git config alias.ack "grep --break --heading --line-number" $ git ack -e --heading Documentation/git-grep.txt 154:--heading:: t/t7810-grep.sh 785:test_expect_success 'grep --heading' ' 786: git grep --heading -e char -e lo_w hello.c hello_world >actual && 808: git grep --break --heading -n --color \ Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- Documentation/git-grep.txt | 4 ++++ builtin/grep.c | 2 ++ grep.c | 6 +++++- grep.h | 1 + t/t7810-grep.sh | 37 +++++++++++++++++++++++++++++++++++++ 5 files changed, 49 insertions(+), 1 deletion(-) diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt index dea7cad0c2..07b3c6a086 100644 --- a/Documentation/git-grep.txt +++ b/Documentation/git-grep.txt @@ -151,6 +151,10 @@ OPTIONS --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] :: Show `context` trailing (`A` -- after), or leading (`B` -- before), or both (`C` -- context) lines, and place a diff --git a/builtin/grep.c b/builtin/grep.c index 42bb87f544..cccf8da6d2 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -824,6 +824,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix) 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 context lines before and after matches", diff --git a/grep.c b/grep.c index b0b860a984..04e9ba4ec4 100644 --- a/grep.c +++ b/grep.c @@ -735,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); } diff --git a/grep.h b/grep.h index 638bee848d..c5682973ea 100644 --- a/grep.h +++ b/grep.h @@ -111,6 +111,7 @@ struct grep_opt { 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); diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index f55793e3cb..1227fa69b4 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -774,4 +774,41 @@ test_expect_success 'grep --break with context' ' test_cmp expected actual ' +cat >expected <actual && + test_cmp expected actual +' + +cat >expected <hello.c +2:int main(int argc, const char **argv) +6: /* char ?? */ + +hello_world +3:Hello_world +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 -- cgit v1.2.3