Skip to content

Commit 1692d0c

Browse files
committed
Merge branch 'rs/grep-color'
* rs/grep-color: grep: add --heading grep: add --break grep: fix coloring of hunk marks between files
2 parents b985f2a + 1d84f72 commit 1692d0c

File tree

5 files changed

+146
-13
lines changed

5 files changed

+146
-13
lines changed

Documentation/git-grep.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,13 @@ OPTIONS
148148
gives the default to color output.
149149
Same as `--color=never`.
150150

151+
--break::
152+
Print an empty line between matches from different files.
153+
154+
--heading::
155+
Show the filename above the matches in that file instead of
156+
at the start of each shown line.
157+
151158
-[ABC] <context>::
152159
Show `context` trailing (`A` -- after), or leading (`B`
153160
-- before), or both (`C` -- context) lines, and place a

builtin/grep.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,7 @@ static pthread_cond_t cond_write;
9393
/* Signalled when we are finished with everything. */
9494
static pthread_cond_t cond_result;
9595

96-
static int print_hunk_marks_between_files;
97-
static int printed_something;
96+
static int skip_first_line;
9897

9998
static void add_work(enum work_type type, char *name, void *id)
10099
{
@@ -160,10 +159,20 @@ static void work_done(struct work_item *w)
160159
todo_done = (todo_done+1) % ARRAY_SIZE(todo)) {
161160
w = &todo[todo_done];
162161
if (w->out.len) {
163-
if (print_hunk_marks_between_files && printed_something)
164-
write_or_die(1, "--\n", 3);
165-
write_or_die(1, w->out.buf, w->out.len);
166-
printed_something = 1;
162+
const char *p = w->out.buf;
163+
size_t len = w->out.len;
164+
165+
/* Skip the leading hunk mark of the first file. */
166+
if (skip_first_line) {
167+
while (len) {
168+
len--;
169+
if (*p++ == '\n')
170+
break;
171+
}
172+
skip_first_line = 0;
173+
}
174+
175+
write_or_die(1, p, len);
167176
}
168177
free(w->name);
169178
free(w->identifier);
@@ -813,6 +822,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
813822
OPT_BOOLEAN('c', "count", &opt.count,
814823
"show the number of matches instead of matching lines"),
815824
OPT__COLOR(&opt.color, "highlight matches"),
825+
OPT_BOOLEAN(0, "break", &opt.file_break,
826+
"print empty line between matches from different files"),
827+
OPT_BOOLEAN(0, "heading", &opt.heading,
828+
"show filename only once above matches from same file"),
816829
OPT_GROUP(""),
817830
OPT_CALLBACK('C', NULL, &opt, "n",
818831
"show <n> context lines before and after matches",
@@ -967,8 +980,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
967980
use_threads = 0;
968981

969982
if (use_threads) {
970-
if (opt.pre_context || opt.post_context)
971-
print_hunk_marks_between_files = 1;
983+
if (opt.pre_context || opt.post_context || opt.file_break)
984+
skip_first_line = 1;
972985
start_threads(&opt);
973986
}
974987
#else

grep.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,10 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
721721
int rest = eol - bol;
722722
char *line_color = NULL;
723723

724-
if (opt->pre_context || opt->post_context) {
724+
if (opt->file_break && opt->last_shown == 0) {
725+
if (opt->show_hunk_mark)
726+
opt->output(opt, "\n", 1);
727+
} else if (opt->pre_context || opt->post_context) {
725728
if (opt->last_shown == 0) {
726729
if (opt->show_hunk_mark) {
727730
output_color(opt, "--", 2, opt->color_sep);
@@ -732,9 +735,13 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
732735
opt->output(opt, "\n", 1);
733736
}
734737
}
738+
if (opt->heading && opt->last_shown == 0) {
739+
output_color(opt, name, strlen(name), opt->color_filename);
740+
opt->output(opt, "\n", 1);
741+
}
735742
opt->last_shown = lno;
736743

737-
if (opt->pathname) {
744+
if (!opt->heading && opt->pathname) {
738745
output_color(opt, name, strlen(name), opt->color_filename);
739746
output_sep(opt, sign);
740747
}
@@ -941,9 +948,18 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
941948
if (!opt->output)
942949
opt->output = std_output;
943950

944-
if (opt->last_shown && (opt->pre_context || opt->post_context) &&
945-
opt->output == std_output)
946-
opt->show_hunk_mark = 1;
951+
if (opt->pre_context || opt->post_context || opt->file_break) {
952+
/* Show hunk marks, except for the first file. */
953+
if (opt->last_shown)
954+
opt->show_hunk_mark = 1;
955+
/*
956+
* If we're using threads then we can't easily identify
957+
* the first file. Always put hunk marks in that case
958+
* and skip the very first one later in work_done().
959+
*/
960+
if (opt->output != std_output)
961+
opt->show_hunk_mark = 1;
962+
}
947963
opt->last_shown = 0;
948964

949965
switch (opt->binary) {

grep.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ struct grep_opt {
110110
unsigned post_context;
111111
unsigned last_shown;
112112
int show_hunk_mark;
113+
int file_break;
114+
int heading;
113115
void *priv;
114116

115117
void (*output)(struct grep_opt *opt, const void *data, size_t size);

t/t7810-grep.sh

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,4 +716,99 @@ test_expect_success LIBPCRE 'grep -G -F -E -P pattern' '
716716
test_cmp expected actual
717717
'
718718

719+
test_config() {
720+
git config "$1" "$2" &&
721+
test_when_finished "git config --unset $1"
722+
}
723+
724+
cat >expected <<EOF
725+
hello.c<RED>:<RESET>int main(int argc, const char **argv)
726+
hello.c<RED>-<RESET>{
727+
<RED>--<RESET>
728+
hello.c<RED>:<RESET> /* char ?? */
729+
hello.c<RED>-<RESET>}
730+
<RED>--<RESET>
731+
hello_world<RED>:<RESET>Hello_world
732+
hello_world<RED>-<RESET>HeLLo_world
733+
EOF
734+
735+
test_expect_success 'grep --color, separator' '
736+
test_config color.grep.context normal &&
737+
test_config color.grep.filename normal &&
738+
test_config color.grep.function normal &&
739+
test_config color.grep.linenumber normal &&
740+
test_config color.grep.match normal &&
741+
test_config color.grep.selected normal &&
742+
test_config color.grep.separator red &&
743+
744+
git grep --color=always -A1 -e char -e lo_w hello.c hello_world |
745+
test_decode_color >actual &&
746+
test_cmp expected actual
747+
'
748+
749+
cat >expected <<EOF
750+
hello.c:int main(int argc, const char **argv)
751+
hello.c: /* char ?? */
752+
753+
hello_world:Hello_world
754+
EOF
755+
756+
test_expect_success 'grep --break' '
757+
git grep --break -e char -e lo_w hello.c hello_world >actual &&
758+
test_cmp expected actual
759+
'
760+
761+
cat >expected <<EOF
762+
hello.c:int main(int argc, const char **argv)
763+
hello.c-{
764+
--
765+
hello.c: /* char ?? */
766+
hello.c-}
767+
768+
hello_world:Hello_world
769+
hello_world-HeLLo_world
770+
EOF
771+
772+
test_expect_success 'grep --break with context' '
773+
git grep --break -A1 -e char -e lo_w hello.c hello_world >actual &&
774+
test_cmp expected actual
775+
'
776+
777+
cat >expected <<EOF
778+
hello.c
779+
int main(int argc, const char **argv)
780+
/* char ?? */
781+
hello_world
782+
Hello_world
783+
EOF
784+
785+
test_expect_success 'grep --heading' '
786+
git grep --heading -e char -e lo_w hello.c hello_world >actual &&
787+
test_cmp expected actual
788+
'
789+
790+
cat >expected <<EOF
791+
<BOLD;GREEN>hello.c<RESET>
792+
2:int main(int argc, const <BLACK;BYELLOW>char<RESET> **argv)
793+
6: /* <BLACK;BYELLOW>char<RESET> ?? */
794+
795+
<BOLD;GREEN>hello_world<RESET>
796+
3:Hel<BLACK;BYELLOW>lo_w<RESET>orld
797+
EOF
798+
799+
test_expect_success 'mimic ack-grep --group' '
800+
test_config color.grep.context normal &&
801+
test_config color.grep.filename "bold green" &&
802+
test_config color.grep.function normal &&
803+
test_config color.grep.linenumber normal &&
804+
test_config color.grep.match "black yellow" &&
805+
test_config color.grep.selected normal &&
806+
test_config color.grep.separator normal &&
807+
808+
git grep --break --heading -n --color \
809+
-e char -e lo_w hello.c hello_world |
810+
test_decode_color >actual &&
811+
test_cmp expected actual
812+
'
813+
719814
test_done

0 commit comments

Comments
 (0)