git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH 0/3] grep: add result grouping, ack style
@ 2011-06-05 15:21 René Scharfe
  2011-06-05 15:24 ` [PATCH 1/3] grep: fix coloring of hunk marks between files René Scharfe
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: René Scharfe @ 2011-06-05 15:21 UTC (permalink / raw
  To: Git Mailing List; +Cc: Junio C Hamano, Mark Lodato

ack (http://betterthangrep.com/) has a nice way to display results from
multiple files by writing the file name once at the top instead of at
the start of each matching line.  This short series starts with a fix
that is needed anyway and then adds the basic options that enable this
display mode.

[PATCH 1/3] grep: fix coloring of hunk marks between files
[PATCH 2/3] grep: add --break
[PATCH 3/3] grep: add --heading

 Documentation/git-grep.txt |    7 +++
 builtin/grep.c             |   29 ++++++++++----
 grep.c                     |   26 ++++++++++--
 grep.h                     |    2 +
 t/t7810-grep.sh            |   95 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 146 insertions(+), 13 deletions(-)

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] grep: fix coloring of hunk marks between files
  2011-06-05 15:21 [PATCH 0/3] grep: add result grouping, ack style René Scharfe
@ 2011-06-05 15:24 ` René Scharfe
  2011-06-05 15:24 ` [PATCH 2/3] grep: add --break René Scharfe
  2011-06-05 15:24 ` [PATCH 3/3] grep: add --heading René Scharfe
  2 siblings, 0 replies; 5+ messages in thread
From: René Scharfe @ 2011-06-05 15:24 UTC (permalink / raw
  To: Git Mailing List; +Cc: Junio C Hamano, Mark Lodato

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 <rene.scharfe@lsrfire.ath.cx>
---
 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 871afaa..0d5a90b 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 d03d9e2..3f15085 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 69bd576..539a8fe 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 <<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
+'
+
 test_done
-- 
1.7.6.rc0.3.ga805ac

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] grep: add --break
  2011-06-05 15:21 [PATCH 0/3] grep: add result grouping, ack style René Scharfe
  2011-06-05 15:24 ` [PATCH 1/3] grep: fix coloring of hunk marks between files René Scharfe
@ 2011-06-05 15:24 ` René Scharfe
  2011-06-05 15:24 ` [PATCH 3/3] grep: add --heading René Scharfe
  2 siblings, 0 replies; 5+ messages in thread
From: René Scharfe @ 2011-06-05 15:24 UTC (permalink / raw
  To: Git Mailing List; +Cc: Junio C Hamano, Mark Lodato

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 <rene.scharfe@lsrfire.ath.cx>
---
 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 e150c77..dea7cad 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] <context>::
 	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 0d5a90b..42bb87f 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 <n> 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 3f15085..b0b860a 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 cd055cd..638bee8 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 539a8fe..f55793e 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 <<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
+'
+
 test_done
-- 
1.7.6.rc0.3.ga805ac

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] grep: add --heading
  2011-06-05 15:21 [PATCH 0/3] grep: add result grouping, ack style René Scharfe
  2011-06-05 15:24 ` [PATCH 1/3] grep: fix coloring of hunk marks between files René Scharfe
  2011-06-05 15:24 ` [PATCH 2/3] grep: add --break René Scharfe
@ 2011-06-05 15:24 ` René Scharfe
  2011-06-06 12:26   ` Michał Kiedrowicz
  2 siblings, 1 reply; 5+ messages in thread
From: René Scharfe @ 2011-06-05 15:24 UTC (permalink / raw
  To: Git Mailing List; +Cc: Junio C Hamano, Mark Lodato

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 <rene.scharfe@lsrfire.ath.cx>
---
 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 deletions(-)

diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index dea7cad..07b3c6a 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] <context>::
 	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 42bb87f..cccf8da 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 <n> context lines before and after matches",
diff --git a/grep.c b/grep.c
index b0b860a..04e9ba4 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 638bee8..c568297 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 f55793e..1227fa6 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 <<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
-- 
1.7.6.rc0.3.ga805ac

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 3/3] grep: add --heading
  2011-06-05 15:24 ` [PATCH 3/3] grep: add --heading René Scharfe
@ 2011-06-06 12:26   ` Michał Kiedrowicz
  0 siblings, 0 replies; 5+ messages in thread
From: Michał Kiedrowicz @ 2011-06-06 12:26 UTC (permalink / raw
  To: git

René Scharfe <rene.scharfe <at> lsrfire.ath.cx> writes:
> 
> 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 \
> 

Nice! I really missed that.

You can also add --perl-regexp (since 1.7.6-rc0) to alias.ack to achive more
compability with ack (although it uses Perl regexes, not PCRE).

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2011-06-06 12:26 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-06-05 15:21 [PATCH 0/3] grep: add result grouping, ack style René Scharfe
2011-06-05 15:24 ` [PATCH 1/3] grep: fix coloring of hunk marks between files René Scharfe
2011-06-05 15:24 ` [PATCH 2/3] grep: add --break René Scharfe
2011-06-05 15:24 ` [PATCH 3/3] grep: add --heading René Scharfe
2011-06-06 12:26   ` Michał Kiedrowicz

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).