* [PATCH] grep: fix match highlighting for combined patterns with context lines
@ 2014-10-21 5:56 Zoltan Klinger
2014-10-21 19:23 ` Junio C Hamano
2014-10-26 18:15 ` René Scharfe
0 siblings, 2 replies; 12+ messages in thread
From: Zoltan Klinger @ 2014-10-21 5:56 UTC (permalink / raw)
To: git; +Cc: Zoltan Klinger
When git grep is run with combined patterns such as '-e p1 --and -e p2'
and surrounding context lines are requested, the output contains
incorrectly highlighted matches.
Consider the following output (highlighted matches are surrounded by '*'
characters):
$ cat testfile
foo a
foo b
foo bar
baz bar foo
bar x
bar y
$ git grep -n -C2 -e foo --and -e bar testfile
testfile-1-*foo* a
testfile-2-*foo* b
testfile:3:*foo* *bar*
testfile:4:baz *bar* *foo*
testfile-5-*bar* x
testfile-6-*bar* y
Lines 1, 2, 5 and 6 do not match the combined patterns, they only
contain incorrectly highlighted 'false positives'.
Modify the show_line() function in grep.c to highlight matches only on
lines that match the combined pattern. Do not highlight matches on lines
that provide only context or contain only the function name of the match.
The output of the same command after the change:
$ git grep -n -C2 -e foo --and -e bar testfile
testfile-1-foo a
testfile-2-foo b
testfile:3:*foo* *bar*
testfile:4:baz *bar* *foo*
testfile-5-bar x
testfile-6-bar y
Signed-off-by: Zoltan Klinger <zoltan.klinger@gmail.com>
---
grep.c | 7 +++--
t/t7810-grep.sh | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 95 insertions(+), 2 deletions(-)
diff --git a/grep.c b/grep.c
index 4dc31ea..3c4d68e 100644
--- a/grep.c
+++ b/grep.c
@@ -1121,9 +1121,12 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
enum grep_context ctx = GREP_CONTEXT_BODY;
int ch = *eol;
int eflags = 0;
+ char *match_color = NULL;
- if (sign == ':')
+ if (sign == ':') {
line_color = opt->color_selected;
+ match_color = opt->color_match;
+ }
else if (sign == '-')
line_color = opt->color_context;
else if (sign == '=')
@@ -1136,7 +1139,7 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
output_color(opt, bol, match.rm_so, line_color);
output_color(opt, bol + match.rm_so,
match.rm_eo - match.rm_so,
- opt->color_match);
+ match_color);
bol += match.rm_eo;
rest -= match.rm_eo;
eflags = REG_NOTBOL;
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index 40615de..b0d6b6f 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -1202,4 +1202,94 @@ test_expect_success LIBPCRE 'grep -P "^ "' '
test_cmp expected actual
'
+cat >expected <<EOF
+space-line without leading space1
+space: line <RED>with <RESET>leading space1
+space: line <RED>with <RESET>leading <RED>space2<RESET>
+space: line <RED>with <RESET>leading space3
+space:line without leading <RED>space2<RESET>
+EOF
+
+test_expect_success 'grep --color -e A -e B with context' '
+ 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 red &&
+ test_config color.grep.selected normal &&
+ test_config color.grep.separator normal &&
+
+ git grep --color=always -C2 -e "with " -e space2 space |
+ test_decode_color >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+space-line without leading space1
+space- line with leading space1
+space: line <RED>with <RESET>leading <RED>space2<RESET>
+space- line with leading space3
+space-line without leading space2
+EOF
+
+test_expect_success 'grep --color -e A --and -e B with context' '
+ 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 red &&
+ test_config color.grep.selected normal &&
+ test_config color.grep.separator normal &&
+
+ git grep --color=always -C2 -e "with " --and -e space2 space |
+ test_decode_color >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+space-line without leading space1
+space: line <RED>with <RESET>leading space1
+space- line with leading space2
+space: line <RED>with <RESET>leading space3
+space-line without leading space2
+EOF
+
+test_expect_success 'grep --color -e A --and --not -e B with context' '
+ 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 red &&
+ test_config color.grep.selected normal &&
+ test_config color.grep.separator normal &&
+
+ git grep --color=always -C2 -e "with " --and --not -e space2 space |
+ test_decode_color >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+hello.c-#include <stdio.h>
+hello.c=int main(int argc, const char **argv)
+hello.c-{
+hello.c: pr<RED>int<RESET>f("<RED>Hello<RESET> world.\n");
+hello.c- return 0;
+hello.c- /* char ?? */
+hello.c-}
+EOF
+
+test_expect_success 'grep --color -e A --and -e B -p with context' '
+ 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 red &&
+ test_config color.grep.selected normal &&
+ test_config color.grep.separator normal &&
+
+ git grep --color=always -p -C3 -e int --and -e Hello --no-index hello.c |
+ test_decode_color >actual &&
+ test_cmp expected actual
+'
+
test_done
--
2.1.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH] grep: fix match highlighting for combined patterns with context lines
2014-10-21 5:56 [PATCH] grep: fix match highlighting for combined patterns with context lines Zoltan Klinger
@ 2014-10-21 19:23 ` Junio C Hamano
2014-10-21 22:40 ` Junio C Hamano
2014-10-26 18:15 ` René Scharfe
1 sibling, 1 reply; 12+ messages in thread
From: Junio C Hamano @ 2014-10-21 19:23 UTC (permalink / raw)
To: Zoltan Klinger; +Cc: git
Zoltan Klinger <zoltan.klinger@gmail.com> writes:
> When git grep is run with combined patterns such as '-e p1 --and -e p2'
> and surrounding context lines are requested, the output contains
> incorrectly highlighted matches.
>
> Consider the following output (highlighted matches are surrounded by '*'
> characters):
> $ cat testfile
> foo a
> foo b
> foo bar
> baz bar foo
> bar x
> bar y
> $ git grep -n -C2 -e foo --and -e bar testfile
> testfile-1-*foo* a
> testfile-2-*foo* b
> testfile:3:*foo* *bar*
> testfile:4:baz *bar* *foo*
> testfile-5-*bar* x
> testfile-6-*bar* y
>
> Lines 1, 2, 5 and 6 do not match the combined patterns, they only
> contain incorrectly highlighted 'false positives'.
>
> Modify the show_line() function in grep.c to highlight matches only on
> lines that match the combined pattern. Do not highlight matches on lines
> that provide only context or contain only the function name of the match.
>
> The output of the same command after the change:
> $ git grep -n -C2 -e foo --and -e bar testfile
> testfile-1-foo a
> testfile-2-foo b
> testfile:3:*foo* *bar*
> testfile:4:baz *bar* *foo*
> testfile-5-bar x
> testfile-6-bar y
If your goal is to stop colouring words on context and other kinds
of lines, do you still need the "while (next_match(...))" loop for
them? Can't you make the resulting code clearer by restructuring
the inside of the whole "if (opt->color)" block further, something
along the lines of...
if (sign != ':') {
regmatch_t match; ...
enum grep_context ctx = GREP_CONTEXT_BODY;
...
while (next_match(...)) {
... the "word-by-word" loop ...
}
} else {
switch (sign) {
case '-':
line_color = opt->color_context;
break;
case ':':
line_color = opt->color_function;
break;
}
output_color(opt, bol, ..., line_color);
}
Hmm?
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] grep: fix match highlighting for combined patterns with context lines
2014-10-21 19:23 ` Junio C Hamano
@ 2014-10-21 22:40 ` Junio C Hamano
2014-10-22 0:45 ` Zoltan Klinger
0 siblings, 1 reply; 12+ messages in thread
From: Junio C Hamano @ 2014-10-21 22:40 UTC (permalink / raw)
To: Zoltan Klinger; +Cc: git
Junio C Hamano <gitster@pobox.com> writes:
> If your goal is to stop colouring words on context and other kinds
> of lines, do you still need the "while (next_match(...))" loop for
> them? Can't you make the resulting code clearer by restructuring
> the inside of the whole "if (opt->color)" block further, something
> along the lines of...
> Hmm?
It turns out that the result of such a change becomes more readable
than the original, in that it makes it clear that reinspection of
the lines are done only for matched ones and not context lines.
The diff looks unnecessarily noisy because it indents the while ()
loop that is only needed for sign == ':', though.
grep.c | 42 ++++++++++++++++++++++--------------------
1 file changed, 22 insertions(+), 20 deletions(-)
diff --git a/grep.c b/grep.c
index c668034..b363a94 100644
--- a/grep.c
+++ b/grep.c
@@ -1112,31 +1112,33 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
output_sep(opt, sign);
}
if (opt->color) {
- regmatch_t match;
- enum grep_context ctx = GREP_CONTEXT_BODY;
- int ch = *eol;
- int eflags = 0;
+ if (sign == ':') {
+ /* paint the hits on matched lines */
+ regmatch_t match;
+ enum grep_context ctx = GREP_CONTEXT_BODY;
+ int ch = *eol;
+ int eflags = 0;
- if (sign == ':')
line_color = opt->color_selected;
- else if (sign == '-')
+ *eol = '\0';
+ while (next_match(opt, bol, eol, ctx, &match, eflags)) {
+ if (match.rm_so == match.rm_eo)
+ break;
+
+ output_color(opt, bol, match.rm_so, line_color);
+ output_color(opt, bol + match.rm_so,
+ match.rm_eo - match.rm_so,
+ opt->color_match);
+ bol += match.rm_eo;
+ rest -= match.rm_eo;
+ eflags = REG_NOTBOL;
+ }
+ *eol = ch;
+ } else if (sign == '-') {
line_color = opt->color_context;
- else if (sign == '=')
+ } else if (sign == '=') {
line_color = opt->color_function;
- *eol = '\0';
- while (next_match(opt, bol, eol, ctx, &match, eflags)) {
- if (match.rm_so == match.rm_eo)
- break;
-
- output_color(opt, bol, match.rm_so, line_color);
- output_color(opt, bol + match.rm_so,
- match.rm_eo - match.rm_so,
- opt->color_match);
- bol += match.rm_eo;
- rest -= match.rm_eo;
- eflags = REG_NOTBOL;
}
- *eol = ch;
}
output_color(opt, bol, rest, line_color);
opt->output(opt, "\n", 1);
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH] grep: fix match highlighting for combined patterns with context lines
2014-10-21 22:40 ` Junio C Hamano
@ 2014-10-22 0:45 ` Zoltan Klinger
2014-10-22 19:14 ` Junio C Hamano
0 siblings, 1 reply; 12+ messages in thread
From: Zoltan Klinger @ 2014-10-22 0:45 UTC (permalink / raw)
To: GIT Mailing-list
> Junio C Hamano <gitster@pobox.com> writes:
>
> It turns out that the result of such a change becomes more readable
> than the original, in that it makes it clear that reinspection of
> the lines are done only for matched ones and not context lines.
>
>
Agree, it looks much clearer now. Happy if you squashed your
change (commit da736e6) in zk/grep-color-words branch.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] grep: fix match highlighting for combined patterns with context lines
2014-10-22 0:45 ` Zoltan Klinger
@ 2014-10-22 19:14 ` Junio C Hamano
0 siblings, 0 replies; 12+ messages in thread
From: Junio C Hamano @ 2014-10-22 19:14 UTC (permalink / raw)
To: Zoltan Klinger; +Cc: GIT Mailing-list
Zoltan Klinger <zoltan.klinger@gmail.com> writes:
>> Junio C Hamano <gitster@pobox.com> writes:
>>
>> It turns out that the result of such a change becomes more readable
>> than the original, in that it makes it clear that reinspection of
>> the lines are done only for matched ones and not context lines.
>>
>>
> Agree, it looks much clearer now. Happy if you squashed your
> change (commit da736e6) in zk/grep-color-words branch.
OK, will do. Thanks.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] grep: fix match highlighting for combined patterns with context lines
2014-10-21 5:56 [PATCH] grep: fix match highlighting for combined patterns with context lines Zoltan Klinger
2014-10-21 19:23 ` Junio C Hamano
@ 2014-10-26 18:15 ` René Scharfe
2014-10-27 18:23 ` [PATCH][RFC] grep: add color.grep.matchcontext and color.grep.matchselected René Scharfe
1 sibling, 1 reply; 12+ messages in thread
From: René Scharfe @ 2014-10-26 18:15 UTC (permalink / raw)
To: Zoltan Klinger, git; +Cc: Junio C Hamano
Am 21.10.2014 um 07:56 schrieb Zoltan Klinger:
> When git grep is run with combined patterns such as '-e p1 --and -e p2'
> and surrounding context lines are requested, the output contains
> incorrectly highlighted matches.
>
> Consider the following output (highlighted matches are surrounded by '*'
> characters):
> $ cat testfile
> foo a
> foo b
> foo bar
> baz bar foo
> bar x
> bar y
> $ git grep -n -C2 -e foo --and -e bar testfile
> testfile-1-*foo* a
> testfile-2-*foo* b
> testfile:3:*foo* *bar*
> testfile:4:baz *bar* *foo*
> testfile-5-*bar* x
> testfile-6-*bar* y
>
> Lines 1, 2, 5 and 6 do not match the combined patterns, they only
> contain incorrectly highlighted 'false positives'.
The old code highlights all search terms, anywhere. I wouldn't call the
ones in the context lines false positives. The user might be interested
in those occurrences as well (I know I am ;).
GNU grep allows coloring to be configured in much greater detail with
its GREP_COLORS variable. I didn't think that level of tuning is
desirable until now. What your patch does is equivalent to change the
default of "ms=01;31:mc=01;31" (color matching string in selected lines
and context lines) to "ms=01;31:mc=" (color matching string in selected
lines).
The difference is only visible with -v or git grep's --not and --and.
So, if you really don't want matching string in context lines to be
colored, perhaps it's time to add a color.grep.contextmatch for matching
text in context lines?
René
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH][RFC] grep: add color.grep.matchcontext and color.grep.matchselected
2014-10-26 18:15 ` René Scharfe
@ 2014-10-27 18:23 ` René Scharfe
2014-10-27 19:29 ` Junio C Hamano
0 siblings, 1 reply; 12+ messages in thread
From: René Scharfe @ 2014-10-27 18:23 UTC (permalink / raw)
To: Zoltan Klinger, git; +Cc: Junio C Hamano
The config option color.grep.match can be used to specify the highlighting
color for matching strings. Add the options matchContext and matchSelected
to allow different colors to be specified for matching strings in the
context vs. in selected lines. This is similar to the ms and mc specifiers
in GNU grep's environment variable GREP_COLORS.
Signed-off-by: Rene Scharfe <l.s.r@web.de>
---
Only *very* lightly tested, and a test for t/is missing anyway. Just
wanted to quickly show what I meant. You'd set color.grep.matchContext=""
to turn off highlighting in context lines. What do you think?
Documentation/config.txt | 6 +++++-
grep.c | 29 ++++++++++++++++++++++-------
grep.h | 3 ++-
3 files changed, 29 insertions(+), 9 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 8b49813..78832ae 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -885,7 +885,11 @@ color.grep.<slot>::
`linenumber`;;
line number prefix (when using `-n`)
`match`;;
- matching text
+ matching text (same as setting `matchContext` and `matchSelected`)
+`matchContext`;;
+ matching text in context lines
+`matchSelected`;;
+ matching text in selected lines
`selected`;;
non-matching text in selected lines
`separator`;;
diff --git a/grep.c b/grep.c
index 4dc31ea..6e085f8 100644
--- a/grep.c
+++ b/grep.c
@@ -35,7 +35,8 @@ void init_grep_defaults(void)
strcpy(opt->color_filename, "");
strcpy(opt->color_function, "");
strcpy(opt->color_lineno, "");
- strcpy(opt->color_match, GIT_COLOR_BOLD_RED);
+ strcpy(opt->color_match_context, GIT_COLOR_BOLD_RED);
+ strcpy(opt->color_match_selected, GIT_COLOR_BOLD_RED);
strcpy(opt->color_selected, "");
strcpy(opt->color_sep, GIT_COLOR_CYAN);
opt->color = -1;
@@ -101,12 +102,22 @@ int grep_config(const char *var, const char *value, void *cb)
color = opt->color_function;
else if (!strcmp(var, "color.grep.linenumber"))
color = opt->color_lineno;
- else if (!strcmp(var, "color.grep.match"))
- color = opt->color_match;
+ else if (!strcmp(var, "color.grep.matchcontext"))
+ color = opt->color_match_context;
+ else if (!strcmp(var, "color.grep.matchselected"))
+ color = opt->color_match_selected;
else if (!strcmp(var, "color.grep.selected"))
color = opt->color_selected;
else if (!strcmp(var, "color.grep.separator"))
color = opt->color_sep;
+ else if (!strcmp(var, "color.grep.match")) {
+ int rc = 0;
+ if (!value)
+ return config_error_nonbool(var);
+ rc |= color_parse(value, opt->color_match_context);
+ rc |= color_parse(value, opt->color_match_selected);
+ return rc;
+ }
if (color) {
if (!value)
@@ -144,7 +155,8 @@ void grep_init(struct grep_opt *opt, const char *prefix)
strcpy(opt->color_filename, def->color_filename);
strcpy(opt->color_function, def->color_function);
strcpy(opt->color_lineno, def->color_lineno);
- strcpy(opt->color_match, def->color_match);
+ strcpy(opt->color_match_context, def->color_match_context);
+ strcpy(opt->color_match_selected, def->color_match_selected);
strcpy(opt->color_selected, def->color_selected);
strcpy(opt->color_sep, def->color_sep);
}
@@ -1084,7 +1096,7 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
const char *name, unsigned lno, char sign)
{
int rest = eol - bol;
- char *line_color = NULL;
+ const char *match_color, *line_color = NULL;
if (opt->file_break && opt->last_shown == 0) {
if (opt->show_hunk_mark)
@@ -1123,6 +1135,10 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
int eflags = 0;
if (sign == ':')
+ match_color = opt->color_match_selected;
+ else
+ match_color = opt->color_match_context;
+ if (sign == ':')
line_color = opt->color_selected;
else if (sign == '-')
line_color = opt->color_context;
@@ -1135,8 +1151,7 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
output_color(opt, bol, match.rm_so, line_color);
output_color(opt, bol + match.rm_so,
- match.rm_eo - match.rm_so,
- opt->color_match);
+ match.rm_eo - match.rm_so, match_color);
bol += match.rm_eo;
rest -= match.rm_eo;
eflags = REG_NOTBOL;
diff --git a/grep.h b/grep.h
index eaaced1..95f197a 100644
--- a/grep.h
+++ b/grep.h
@@ -124,7 +124,8 @@ struct grep_opt {
char color_filename[COLOR_MAXLEN];
char color_function[COLOR_MAXLEN];
char color_lineno[COLOR_MAXLEN];
- char color_match[COLOR_MAXLEN];
+ char color_match_context[COLOR_MAXLEN];
+ char color_match_selected[COLOR_MAXLEN];
char color_selected[COLOR_MAXLEN];
char color_sep[COLOR_MAXLEN];
int regflags;
--
2.1.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH][RFC] grep: add color.grep.matchcontext and color.grep.matchselected
2014-10-27 18:23 ` [PATCH][RFC] grep: add color.grep.matchcontext and color.grep.matchselected René Scharfe
@ 2014-10-27 19:29 ` Junio C Hamano
2014-10-27 19:47 ` Junio C Hamano
2014-10-27 23:32 ` Zoltan Klinger
0 siblings, 2 replies; 12+ messages in thread
From: Junio C Hamano @ 2014-10-27 19:29 UTC (permalink / raw)
To: René Scharfe; +Cc: Zoltan Klinger, git
René Scharfe <l.s.r@web.de> writes:
> The config option color.grep.match can be used to specify the highlighting
> color for matching strings. Add the options matchContext and matchSelected
> to allow different colors to be specified for matching strings in the
> context vs. in selected lines. This is similar to the ms and mc specifiers
> in GNU grep's environment variable GREP_COLORS.
>
> Signed-off-by: Rene Scharfe <l.s.r@web.de>
> ---
> Only *very* lightly tested, and a test for t/is missing anyway. Just
> wanted to quickly show what I meant. You'd set color.grep.matchContext=""
> to turn off highlighting in context lines. What do you think?
I didn't realize that people wanted to see pieces on non-matching
lines highlighted. It makes certain sense, e.g. it would allow you
to spot near-misses, but that is only true for lines that neighbour
real hits, so...
I like this approach better in that it makes those who want a
different behaviour to do the work without breaking the expectation
of those who are used to the established behaviour.
Zoltan?
> Documentation/config.txt | 6 +++++-
> grep.c | 29 ++++++++++++++++++++++-------
> grep.h | 3 ++-
> 3 files changed, 29 insertions(+), 9 deletions(-)
>
> diff --git a/Documentation/config.txt b/Documentation/config.txt
> index 8b49813..78832ae 100644
> --- a/Documentation/config.txt
> +++ b/Documentation/config.txt
> @@ -885,7 +885,11 @@ color.grep.<slot>::
> `linenumber`;;
> line number prefix (when using `-n`)
> `match`;;
> - matching text
> + matching text (same as setting `matchContext` and `matchSelected`)
> +`matchContext`;;
> + matching text in context lines
> +`matchSelected`;;
> + matching text in selected lines
> `selected`;;
> non-matching text in selected lines
> `separator`;;
> diff --git a/grep.c b/grep.c
> index 4dc31ea..6e085f8 100644
> --- a/grep.c
> +++ b/grep.c
> @@ -35,7 +35,8 @@ void init_grep_defaults(void)
> strcpy(opt->color_filename, "");
> strcpy(opt->color_function, "");
> strcpy(opt->color_lineno, "");
> - strcpy(opt->color_match, GIT_COLOR_BOLD_RED);
> + strcpy(opt->color_match_context, GIT_COLOR_BOLD_RED);
> + strcpy(opt->color_match_selected, GIT_COLOR_BOLD_RED);
> strcpy(opt->color_selected, "");
> strcpy(opt->color_sep, GIT_COLOR_CYAN);
> opt->color = -1;
> @@ -101,12 +102,22 @@ int grep_config(const char *var, const char *value, void *cb)
> color = opt->color_function;
> else if (!strcmp(var, "color.grep.linenumber"))
> color = opt->color_lineno;
> - else if (!strcmp(var, "color.grep.match"))
> - color = opt->color_match;
> + else if (!strcmp(var, "color.grep.matchcontext"))
> + color = opt->color_match_context;
> + else if (!strcmp(var, "color.grep.matchselected"))
> + color = opt->color_match_selected;
> else if (!strcmp(var, "color.grep.selected"))
> color = opt->color_selected;
> else if (!strcmp(var, "color.grep.separator"))
> color = opt->color_sep;
> + else if (!strcmp(var, "color.grep.match")) {
> + int rc = 0;
> + if (!value)
> + return config_error_nonbool(var);
> + rc |= color_parse(value, opt->color_match_context);
> + rc |= color_parse(value, opt->color_match_selected);
> + return rc;
> + }
>
> if (color) {
> if (!value)
> @@ -144,7 +155,8 @@ void grep_init(struct grep_opt *opt, const char *prefix)
> strcpy(opt->color_filename, def->color_filename);
> strcpy(opt->color_function, def->color_function);
> strcpy(opt->color_lineno, def->color_lineno);
> - strcpy(opt->color_match, def->color_match);
> + strcpy(opt->color_match_context, def->color_match_context);
> + strcpy(opt->color_match_selected, def->color_match_selected);
> strcpy(opt->color_selected, def->color_selected);
> strcpy(opt->color_sep, def->color_sep);
> }
> @@ -1084,7 +1096,7 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
> const char *name, unsigned lno, char sign)
> {
> int rest = eol - bol;
> - char *line_color = NULL;
> + const char *match_color, *line_color = NULL;
>
> if (opt->file_break && opt->last_shown == 0) {
> if (opt->show_hunk_mark)
> @@ -1123,6 +1135,10 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
> int eflags = 0;
>
> if (sign == ':')
> + match_color = opt->color_match_selected;
> + else
> + match_color = opt->color_match_context;
> + if (sign == ':')
> line_color = opt->color_selected;
> else if (sign == '-')
> line_color = opt->color_context;
> @@ -1135,8 +1151,7 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
>
> output_color(opt, bol, match.rm_so, line_color);
> output_color(opt, bol + match.rm_so,
> - match.rm_eo - match.rm_so,
> - opt->color_match);
> + match.rm_eo - match.rm_so, match_color);
> bol += match.rm_eo;
> rest -= match.rm_eo;
> eflags = REG_NOTBOL;
> diff --git a/grep.h b/grep.h
> index eaaced1..95f197a 100644
> --- a/grep.h
> +++ b/grep.h
> @@ -124,7 +124,8 @@ struct grep_opt {
> char color_filename[COLOR_MAXLEN];
> char color_function[COLOR_MAXLEN];
> char color_lineno[COLOR_MAXLEN];
> - char color_match[COLOR_MAXLEN];
> + char color_match_context[COLOR_MAXLEN];
> + char color_match_selected[COLOR_MAXLEN];
> char color_selected[COLOR_MAXLEN];
> char color_sep[COLOR_MAXLEN];
> int regflags;
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH][RFC] grep: add color.grep.matchcontext and color.grep.matchselected
2014-10-27 19:29 ` Junio C Hamano
@ 2014-10-27 19:47 ` Junio C Hamano
2014-10-27 23:32 ` Zoltan Klinger
1 sibling, 0 replies; 12+ messages in thread
From: Junio C Hamano @ 2014-10-27 19:47 UTC (permalink / raw)
To: René Scharfe; +Cc: Zoltan Klinger, git
Junio C Hamano <gitster@pobox.com> writes:
> René Scharfe <l.s.r@web.de> writes:
>
>> The config option color.grep.match can be used to specify the highlighting
>> color for matching strings. Add the options matchContext and matchSelected
>> to allow different colors to be specified for matching strings in the
>> context vs. in selected lines. This is similar to the ms and mc specifiers
>> in GNU grep's environment variable GREP_COLORS.
>>
>> Signed-off-by: Rene Scharfe <l.s.r@web.de>
>> ---
>> Only *very* lightly tested, and a test for t/is missing anyway. Just
>> wanted to quickly show what I meant. You'd set color.grep.matchContext=""
>> to turn off highlighting in context lines. What do you think?
>
> I didn't realize that people wanted to see pieces on non-matching
> lines highlighted. It makes certain sense, e.g. it would allow you
> to spot near-misses, but that is only true for lines that neighbour
> real hits, so...
>
> I like this approach better in that it makes those who want a
> different behaviour to do the work without breaking the expectation
> of those who are used to the established behaviour.
FWIW, here is a backport on top of maint-1.8.5 with Zoltan's tests,
not because I wanted to apply this as a bugfix to maintenance track,
but because I wanted to compare with what has been queued already.
To apply to post f6c5a296 (color_parse: do not mention variable name
in error message, 2014-10-07) codebase, the mangling I did for two
calls to color_parse() function needs to be undone, obviously.
Documentation/config.txt | 6 +++-
grep.c | 29 +++++++++++----
grep.h | 3 +-
t/t7810-grep.sh | 94 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 123 insertions(+), 9 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index ab26963..aa881fc 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -860,7 +860,11 @@ color.grep.<slot>::
`linenumber`;;
line number prefix (when using `-n`)
`match`;;
- matching text
+ matching text (same as setting `matchContext` and `matchSelected`)
+`matchContext`;;
+ matching text in context lines
+`matchSelected`;;
+ matching text in selected lines
`selected`;;
non-matching text in selected lines
`separator`;;
diff --git a/grep.c b/grep.c
index c668034..f950651 100644
--- a/grep.c
+++ b/grep.c
@@ -35,7 +35,8 @@ void init_grep_defaults(void)
strcpy(opt->color_filename, "");
strcpy(opt->color_function, "");
strcpy(opt->color_lineno, "");
- strcpy(opt->color_match, GIT_COLOR_BOLD_RED);
+ strcpy(opt->color_match_context, GIT_COLOR_BOLD_RED);
+ strcpy(opt->color_match_selected, GIT_COLOR_BOLD_RED);
strcpy(opt->color_selected, "");
strcpy(opt->color_sep, GIT_COLOR_CYAN);
opt->color = -1;
@@ -96,12 +97,22 @@ int grep_config(const char *var, const char *value, void *cb)
color = opt->color_function;
else if (!strcmp(var, "color.grep.linenumber"))
color = opt->color_lineno;
- else if (!strcmp(var, "color.grep.match"))
- color = opt->color_match;
+ else if (!strcmp(var, "color.grep.matchcontext"))
+ color = opt->color_match_context;
+ else if (!strcmp(var, "color.grep.matchselected"))
+ color = opt->color_match_selected;
else if (!strcmp(var, "color.grep.selected"))
color = opt->color_selected;
else if (!strcmp(var, "color.grep.separator"))
color = opt->color_sep;
+ else if (!strcmp(var, "color.grep.match")) {
+ int rc = 0;
+ if (!value)
+ return config_error_nonbool(var);
+ color_parse(value, var, opt->color_match_context);
+ color_parse(value, var, opt->color_match_selected);
+ return rc;
+ }
if (color) {
if (!value)
@@ -139,7 +150,8 @@ void grep_init(struct grep_opt *opt, const char *prefix)
strcpy(opt->color_filename, def->color_filename);
strcpy(opt->color_function, def->color_function);
strcpy(opt->color_lineno, def->color_lineno);
- strcpy(opt->color_match, def->color_match);
+ strcpy(opt->color_match_context, def->color_match_context);
+ strcpy(opt->color_match_selected, def->color_match_selected);
strcpy(opt->color_selected, def->color_selected);
strcpy(opt->color_sep, def->color_sep);
}
@@ -1079,7 +1091,7 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
const char *name, unsigned lno, char sign)
{
int rest = eol - bol;
- char *line_color = NULL;
+ const char *match_color, *line_color = NULL;
if (opt->file_break && opt->last_shown == 0) {
if (opt->show_hunk_mark)
@@ -1118,6 +1130,10 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
int eflags = 0;
if (sign == ':')
+ match_color = opt->color_match_selected;
+ else
+ match_color = opt->color_match_context;
+ if (sign == ':')
line_color = opt->color_selected;
else if (sign == '-')
line_color = opt->color_context;
@@ -1130,8 +1146,7 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
output_color(opt, bol, match.rm_so, line_color);
output_color(opt, bol + match.rm_so,
- match.rm_eo - match.rm_so,
- opt->color_match);
+ match.rm_eo - match.rm_so, match_color);
bol += match.rm_eo;
rest -= match.rm_eo;
eflags = REG_NOTBOL;
diff --git a/grep.h b/grep.h
index eaaced1..95f197a 100644
--- a/grep.h
+++ b/grep.h
@@ -124,7 +124,8 @@ struct grep_opt {
char color_filename[COLOR_MAXLEN];
char color_function[COLOR_MAXLEN];
char color_lineno[COLOR_MAXLEN];
- char color_match[COLOR_MAXLEN];
+ char color_match_context[COLOR_MAXLEN];
+ char color_match_selected[COLOR_MAXLEN];
char color_selected[COLOR_MAXLEN];
char color_sep[COLOR_MAXLEN];
int regflags;
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index f698001..e3eeaf9 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -1195,4 +1195,98 @@ test_expect_success LIBPCRE 'grep -P "^ "' '
test_cmp expected actual
'
+cat >expected <<EOF
+space-line without leading space1
+space: line <RED>with <RESET>leading space1
+space: line <RED>with <RESET>leading <RED>space2<RESET>
+space: line <RED>with <RESET>leading space3
+space:line without leading <RED>space2<RESET>
+EOF
+
+test_expect_success 'grep --color -e A -e B with context' '
+ 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.matchContext normal &&
+ test_config color.grep.matchSelected red &&
+ test_config color.grep.selected normal &&
+ test_config color.grep.separator normal &&
+
+ git grep --color=always -C2 -e "with " -e space2 space |
+ test_decode_color >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+space-line without leading space1
+space- line with leading space1
+space: line <RED>with <RESET>leading <RED>space2<RESET>
+space- line with leading space3
+space-line without leading space2
+EOF
+
+test_expect_success 'grep --color -e A --and -e B with context' '
+ 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.matchContext normal &&
+ test_config color.grep.matchSelected red &&
+ test_config color.grep.selected normal &&
+ test_config color.grep.separator normal &&
+
+ git grep --color=always -C2 -e "with " --and -e space2 space |
+ test_decode_color >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+space-line without leading space1
+space: line <RED>with <RESET>leading space1
+space- line with leading space2
+space: line <RED>with <RESET>leading space3
+space-line without leading space2
+EOF
+
+test_expect_success 'grep --color -e A --and --not -e B with context' '
+ 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.matchContext normal &&
+ test_config color.grep.matchSelected red &&
+ test_config color.grep.selected normal &&
+ test_config color.grep.separator normal &&
+
+ git grep --color=always -C2 -e "with " --and --not -e space2 space |
+ test_decode_color >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+hello.c-#include <stdio.h>
+hello.c=int main(int argc, const char **argv)
+hello.c-{
+hello.c: pr<RED>int<RESET>f("<RED>Hello<RESET> world.\n");
+hello.c- return 0;
+hello.c- /* char ?? */
+hello.c-}
+EOF
+
+test_expect_success 'grep --color -e A --and -e B -p with context' '
+ 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.matchContext normal &&
+ test_config color.grep.matchSelected red &&
+ test_config color.grep.selected normal &&
+ test_config color.grep.separator normal &&
+
+ git grep --color=always -p -C3 -e int --and -e Hello --no-index hello.c |
+ test_decode_color >actual &&
+ test_cmp expected actual
+'
+
test_done
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH][RFC] grep: add color.grep.matchcontext and color.grep.matchselected
2014-10-27 19:29 ` Junio C Hamano
2014-10-27 19:47 ` Junio C Hamano
@ 2014-10-27 23:32 ` Zoltan Klinger
2014-10-28 16:50 ` Junio C Hamano
2014-10-28 18:19 ` René Scharfe
1 sibling, 2 replies; 12+ messages in thread
From: Zoltan Klinger @ 2014-10-27 23:32 UTC (permalink / raw)
To: Junio C Hamano; +Cc: René Scharfe, GIT Mailing-list
I like René's approach, too. It's more flexible, supports the old
behaviour and it scratches my itch as well.
Don't mind if you dropped my patch and used René's instead.
>> Only *very* lightly tested, and a test for t/is missing anyway. Just
>> wanted to quickly show what I meant. You'd set color.grep.matchContext=""
>> to turn off highlighting in context lines. What do you think?
>
> I didn't realize that people wanted to see pieces on non-matching
> lines highlighted. It makes certain sense, e.g. it would allow you
> to spot near-misses, but that is only true for lines that neighbour
> real hits, so...
>
> I like this approach better in that it makes those who want a
> different behaviour to do the work without breaking the expectation
> of those who are used to the established behaviour.
>
> Zoltan?
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH][RFC] grep: add color.grep.matchcontext and color.grep.matchselected
2014-10-27 23:32 ` Zoltan Klinger
@ 2014-10-28 16:50 ` Junio C Hamano
2014-10-28 18:19 ` René Scharfe
1 sibling, 0 replies; 12+ messages in thread
From: Junio C Hamano @ 2014-10-28 16:50 UTC (permalink / raw)
To: Zoltan Klinger; +Cc: René Scharfe, GIT Mailing-list
Zoltan Klinger <zoltan.klinger@gmail.com> writes:
> I like René's approach, too. It's more flexible, supports the old
> behaviour and it scratches my itch as well.
OK, then let's go with that one.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH][RFC] grep: add color.grep.matchcontext and color.grep.matchselected
2014-10-27 23:32 ` Zoltan Klinger
2014-10-28 16:50 ` Junio C Hamano
@ 2014-10-28 18:19 ` René Scharfe
1 sibling, 0 replies; 12+ messages in thread
From: René Scharfe @ 2014-10-28 18:19 UTC (permalink / raw)
To: Zoltan Klinger; +Cc: Junio C Hamano, GIT Mailing-list
Am 28.10.2014 um 00:32 schrieb Zoltan Klinger:
> I like René's approach, too. It's more flexible, supports the old
> behaviour and it scratches my itch as well.
> Don't mind if you dropped my patch and used René's instead.
Good. :) And here's the t/ part of your patch, slightly changed to
exercise the new config options.
---
t/t7810-grep.sh | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 93 insertions(+)
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index 40615de..5d3e161 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -1202,4 +1202,97 @@ test_expect_success LIBPCRE 'grep -P "^ "' '
test_cmp expected actual
'
+cat >expected <<EOF
+space-line without leading space1
+space: line <RED>with <RESET>leading space1
+space: line <RED>with <RESET>leading <RED>space2<RESET>
+space: line <RED>with <RESET>leading space3
+space:line without leading <RED>space2<RESET>
+EOF
+
+test_expect_success 'grep --color -e A -e B with context' '
+ 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 red &&
+ test_config color.grep.selected normal &&
+ test_config color.grep.separator normal &&
+
+ git grep --color=always -C2 -e "with " -e space2 space |
+ test_decode_color >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+space-line without leading space1
+space- line <GREEN>with <RESET>leading space1
+space: line <RED>with <RESET>leading <RED>space2<RESET>
+space- line <GREEN>with <RESET>leading space3
+space-line without leading <GREEN>space2<RESET>
+EOF
+
+test_expect_success 'grep --color -e A --and -e B with context' '
+ 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.matchContext green &&
+ test_config color.grep.matchSelected red &&
+ test_config color.grep.selected normal &&
+ test_config color.grep.separator normal &&
+
+ git grep --color=always -C2 -e "with " --and -e space2 space |
+ test_decode_color >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+space-line without leading space1
+space: line <RED>with <RESET>leading space1
+space- line <GREEN>with <RESET>leading <GREEN>space2<RESET>
+space: line <RED>with <RESET>leading space3
+space-line without leading <GREEN>space2<RESET>
+EOF
+
+test_expect_success 'grep --color -e A --and --not -e B with context' '
+ 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.matchContext green &&
+ test_config color.grep.matchSelected red &&
+ test_config color.grep.selected normal &&
+ test_config color.grep.separator normal &&
+
+ git grep --color=always -C2 -e "with " --and --not -e space2 space |
+ test_decode_color >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+hello.c-#include <stdio.h>
+hello.c=<GREEN>int<RESET> main(<GREEN>int<RESET> argc, const char **argv)
+hello.c-{
+hello.c: pr<RED>int<RESET>f("<RED>Hello<RESET> world.\n");
+hello.c- return 0;
+hello.c- /* char ?? */
+hello.c-}
+EOF
+
+test_expect_success 'grep --color -e A --and -e B -p with context' '
+ 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.matchContext green &&
+ test_config color.grep.matchSelected red &&
+ test_config color.grep.selected normal &&
+ test_config color.grep.separator normal &&
+
+ git grep --color=always -p -C3 -e int --and -e Hello --no-index hello.c |
+ test_decode_color >actual &&
+ test_cmp expected actual
+'
+
test_done
--
2.1.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
end of thread, other threads:[~2014-10-28 18:20 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-10-21 5:56 [PATCH] grep: fix match highlighting for combined patterns with context lines Zoltan Klinger
2014-10-21 19:23 ` Junio C Hamano
2014-10-21 22:40 ` Junio C Hamano
2014-10-22 0:45 ` Zoltan Klinger
2014-10-22 19:14 ` Junio C Hamano
2014-10-26 18:15 ` René Scharfe
2014-10-27 18:23 ` [PATCH][RFC] grep: add color.grep.matchcontext and color.grep.matchselected René Scharfe
2014-10-27 19:29 ` Junio C Hamano
2014-10-27 19:47 ` Junio C Hamano
2014-10-27 23:32 ` Zoltan Klinger
2014-10-28 16:50 ` Junio C Hamano
2014-10-28 18:19 ` René Scharfe
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 NNTP newsgroup(s).