@matheusbsbs / matheus-bagliano / commits / 55f638bdc6
Fork 0

grep: Colorize filename, line number, and separator

Colorize the filename, line number, and separator in git grep output, as GNU grep does. The colors are customizable through color.grep.<slot>. The default is to only color the separator (in cyan), since this gives the biggest legibility increase without overwhelming the user with colors. GNU grep also defaults cyan for the separator, but defaults to magenta for the filename and to green for the line number, as well. There is one difference from GNU grep: When a binary file matches without -a, GNU grep does not color the <file> in "Binary file <file> matches", but we do. Like GNU grep, if --null is given, the null separators are not colored. For config.txt, use a a sub-list to describe the slots, rather than a single paragraph with parentheses, since this is much more readable. Remove the cast to int for `rm_eo - rm_so` since it is not necessary. Signed-off-by: Mark Lodato <lodatom@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Mark Lodato committed Mar 7, 2010 at 11:52 UTC 55f638bdc6507b3a2ce03290741f592934afaee7
4 files changed +78 -34
Documentation/config.txt
+17 -3
@@ -683,9 +683,23 @@ color.grep::
683 `never`), never. When set to `true` or `auto`, use color only
684 when the output is written to the terminal. Defaults to `false`.
685
686 -color.grep.match::
687 - Use customized color for matches. The value of this variable
688 - may be specified as in color.branch.<slot>.
686 +color.grep.<slot>::
687 + Use customized color for grep colorization. `<slot>` specifies which
688 + part of the line to use the specified color, and is one of
689 ++
690 +--
691 +`filename`;;
692 + filename prefix (when not using `-h`)
693 +`linenumber`;;
694 + line number prefix (when using `-n`)
695 +`match`;;
696 + matching text
697 +`separator`;;
698 + separators between fields on a line (`:`, `-`, and `=`)
699 + and between hunks (`--`)
700 +--
701 ++
702 +The values of these variables may be specified as in color.branch.<slot>.
703
704 color.interactive::
705 When set to `always`, always use colors for interactive prompts
builtin-grep.c
+18 -7
@@ -289,6 +289,7 @@ static int wait_all(void)
289 static int grep_config(const char *var, const char *value, void *cb)
290 {
291 struct grep_opt *opt = cb;
292 + char *color = NULL;
293
294 switch (userdiff_config(var, value)) {
295 case 0: break;
@@ -296,17 +297,24 @@ static int grep_config(const char *var, const char *value, void *cb)
297 default: return 0;
298 }
299
299 - if (!strcmp(var, "color.grep")) {
300 + if (!strcmp(var, "color.grep"))
301 opt->color = git_config_colorbool(var, value, -1);
301 - return 0;
302 - }
303 - if (!strcmp(var, "color.grep.match")) {
302 + else if (!strcmp(var, "color.grep.filename"))
303 + color = opt->color_filename;
304 + else if (!strcmp(var, "color.grep.linenumber"))
305 + color = opt->color_lineno;
306 + else if (!strcmp(var, "color.grep.match"))
307 + color = opt->color_match;
308 + else if (!strcmp(var, "color.grep.separator"))
309 + color = opt->color_sep;
310 + else
311 + return git_color_default_config(var, value, cb);
312 + if (color) {
313 if (!value)
314 return config_error_nonbool(var);
306 - color_parse(value, var, opt->color_match);
307 - return 0;
315 + color_parse(value, var, color);
316 }
309 - return git_color_default_config(var, value, cb);
317 + return 0;
318 }
319
320 /*
@@ -871,7 +879,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
879 opt.regflags = REG_NEWLINE;
880 opt.max_depth = -1;
881
882 + strcpy(opt.color_filename, "");
883 + strcpy(opt.color_lineno, "");
884 strcpy(opt.color_match, GIT_COLOR_BOLD_RED);
885 + strcpy(opt.color_sep, GIT_COLOR_CYAN);
886 opt.color = -1;
887 git_config(grep_config, &opt);
888 if (opt.color == -1)
grep.c
+40 -24
@@ -270,9 +270,28 @@ static int word_char(char ch)
270 return isalnum(ch) || ch == '_';
271 }
272
273 +static void output_color(struct grep_opt *opt, const void *data, size_t size,
274 + const char *color)
275 +{
276 + if (opt->color && color && color[0]) {
277 + opt->output(opt, color, strlen(color));
278 + opt->output(opt, data, size);
279 + opt->output(opt, GIT_COLOR_RESET, strlen(GIT_COLOR_RESET));
280 + } else
281 + opt->output(opt, data, size);
282 +}
283 +
284 +static void output_sep(struct grep_opt *opt, char sign)
285 +{
286 + if (opt->null_following_name)
287 + opt->output(opt, "\0", 1);
288 + else
289 + output_color(opt, &sign, 1, opt->color_sep);
290 +}
291 +
292 static void show_name(struct grep_opt *opt, const char *name)
293 {
275 - opt->output(opt, name, strlen(name));
294 + output_color(opt, name, strlen(name), opt->color_filename);
295 opt->output(opt, opt->null_following_name ? "\0" : "\n", 1);
296 }
297
@@ -510,31 +529,30 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
529 const char *name, unsigned lno, char sign)
530 {
531 int rest = eol - bol;
513 - char sign_str[1];
532
515 - sign_str[0] = sign;
533 if (opt->pre_context || opt->post_context) {
534 if (opt->last_shown == 0) {
518 - if (opt->show_hunk_mark)
519 - opt->output(opt, "--\n", 3);
520 - else
535 + if (opt->show_hunk_mark) {
536 + output_color(opt, "--", 2, opt->color_sep);
537 + opt->output(opt, "\n", 1);
538 + } else
539 opt->show_hunk_mark = 1;
522 - } else if (lno > opt->last_shown + 1)
523 - opt->output(opt, "--\n", 3);
540 + } else if (lno > opt->last_shown + 1) {
541 + output_color(opt, "--", 2, opt->color_sep);
542 + opt->output(opt, "\n", 1);
543 + }
544 }
545 opt->last_shown = lno;
546
527 - if (opt->null_following_name)
528 - sign_str[0] = '\0';
547 if (opt->pathname) {
530 - opt->output(opt, name, strlen(name));
531 - opt->output(opt, sign_str, 1);
548 + output_color(opt, name, strlen(name), opt->color_filename);
549 + output_sep(opt, sign);
550 }
551 if (opt->linenum) {
552 char buf[32];
553 snprintf(buf, sizeof(buf), "%d", lno);
536 - opt->output(opt, buf, strlen(buf));
537 - opt->output(opt, sign_str, 1);
554 + output_color(opt, buf, strlen(buf), opt->color_lineno);
555 + output_sep(opt, sign);
556 }
557 if (opt->color) {
558 regmatch_t match;
@@ -548,12 +566,9 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
566 break;
567
568 opt->output(opt, bol, match.rm_so);
551 - opt->output(opt, opt->color_match,
552 - strlen(opt->color_match));
553 - opt->output(opt, bol + match.rm_so,
554 - (int)(match.rm_eo - match.rm_so));
555 - opt->output(opt, GIT_COLOR_RESET,
556 - strlen(GIT_COLOR_RESET));
569 + output_color(opt, bol + match.rm_so,
570 + match.rm_eo - match.rm_so,
571 + opt->color_match);
572 bol += match.rm_eo;
573 rest -= match.rm_eo;
574 eflags = REG_NOTBOL;
@@ -823,7 +838,8 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
838 return 1;
839 if (binary_match_only) {
840 opt->output(opt, "Binary file ", 12);
826 - opt->output(opt, name, strlen(name));
841 + output_color(opt, name, strlen(name),
842 + opt->color_filename);
843 opt->output(opt, " matches\n", 9);
844 return 1;
845 }
@@ -882,9 +898,9 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
898 */
899 if (opt->count && count) {
900 char buf[32];
885 - opt->output(opt, name, strlen(name));
886 - snprintf(buf, sizeof(buf), "%c%u\n",
887 - opt->null_following_name ? '\0' : ':', count);
901 + output_color(opt, name, strlen(name), opt->color_filename);
902 + output_sep(opt, ':');
903 + snprintf(buf, sizeof(buf), "%u\n", count);
904 opt->output(opt, buf, strlen(buf));
905 }
906 return !!last_hit;
grep.h
+3
@@ -84,7 +84,10 @@ struct grep_opt {
84 int color;
85 int max_depth;
86 int funcname;
87 + char color_filename[COLOR_MAXLEN];
88 + char color_lineno[COLOR_MAXLEN];
89 char color_match[COLOR_MAXLEN];
90 + char color_sep[COLOR_MAXLEN];
91 int regflags;
92 unsigned pre_context;
93 unsigned post_context;