From: "Thiago Alves" <thiago.salves@gmail.com>
To: git@vger.kernel.org
Subject: [PATCH] git grep colorized
Date: Thu, 7 Aug 2008 08:53:45 -0300 [thread overview]
Message-ID: <ecd9a7b10808070453o3e0b34e5w27564d2e4ee73191@mail.gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 621 bytes --]
Hi guys,
recently I try to put some colors on my git-grep and found a patch
from Nguyễn Thái Ngọc Duy <pclouds@gmail.com> to do it!
The problem with this patch is that it doesn't support the config file
to persist the color option on grep.
I took the liberty to change his patch and add support to config files
and bash completion.
Attached is the resultant patch!
I hope this could be useful to someone.
Thiago dos Santos Alves
Computer Scientist
thiago.salves@gmail.com
-----------------------------------------------------
"Man's mind, once stretched by a new idea, never regains it's original
dimensions."
[-- Attachment #2: git_grep_color.patch --]
[-- Type: application/octet-stream, Size: 10212 bytes --]
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index fa4d133..8554068 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -15,7 +15,7 @@ SYNOPSIS
[-E | --extended-regexp] [-G | --basic-regexp]
[-F | --fixed-strings] [-n]
[-l | --files-with-matches] [-L | --files-without-match]
- [-c | --count] [--all-match]
+ [-c | --count] [--all-match] [--color | --no-color]
[-A <post-context>] [-B <pre-context>] [-C <context>]
[-f <file>] [-e] <pattern>
[--and|--or|--not|(|)|-e <pattern>...] [<tree>...]
@@ -99,6 +99,13 @@ OPTIONS
Instead of showing every matched line, show the number of
lines that match.
+--color::
+ Colorize grep output highlighting matches, file names and line numbers.
+
+--no-color::
+ Turn off grep colors, even when the configuration file gives the
+ default to color output.
+
-[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 631129d..29e7d5a 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -11,6 +11,7 @@
#include "tree-walk.h"
#include "builtin.h"
#include "grep.h"
+#include "color.h"
#ifndef NO_EXTERNAL_GREP
#ifdef __unix__
@@ -20,6 +21,7 @@
#endif
#endif
+static int grep_use_color = -1;
/*
* git grep pathspecs are somewhat different from diff-tree pathspecs;
* pathname wildcards are allowed.
@@ -386,7 +388,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
* we grep through the checked-out files. It tends to
* be a lot more optimized
*/
- if (!cached) {
+ if (!cached && !opt->color) {
hit = external_grep(opt, paths, cached);
if (hit >= 0)
return hit;
@@ -507,6 +509,22 @@ static const char emsg_missing_context_len[] =
static const char emsg_missing_argument[] =
"option requires an argument -%s";
+static int git_grep_config(const char *var, const char *value, void *cb)
+{
+ if (!strcmp(var, "color.grep")) {
+ grep_use_color = git_config_colorbool(var, value, -1);
+ return 0;
+ }
+ if (!prefixcmp(var, "color.grep.")) {
+ int slot = parse_grep_color_slot(var, 11);
+ if (!value)
+ return config_error_nonbool(var);
+ color_parse(value, var, grep_get_color(slot));
+ return 0;
+ }
+ return git_color_default_config(var, value, cb);
+}
+
int cmd_grep(int argc, const char **argv, const char *prefix)
{
int hit = 0;
@@ -524,6 +542,11 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
opt.pattern_tail = &opt.pattern_list;
opt.regflags = REG_NEWLINE;
+ git_config(git_grep_config, NULL);
+ if (grep_use_color == -1)
+ grep_use_color = git_use_color_default;
+ opt.color = grep_use_color;
+
/*
* If there is no -- then the paths must exist in the working
* tree. If there is no explicit pattern specified with -e or
@@ -711,6 +734,14 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
opt.relative = 0;
continue;
}
+ if (!strcmp("--color", arg)) {
+ opt.color = 1;
+ continue;
+ }
+ if (!strcmp("--no-color", arg)) {
+ opt.color = 0;
+ continue;
+ }
if (!strcmp("--", arg)) {
/* later processing wants to have this at argv[1] */
argv--;
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 3396e35..ee4d509 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1157,7 +1157,7 @@ _git_config ()
__gitcomp "$(__git_merge_strategies)"
return
;;
- color.branch|color.diff|color.status)
+ color.branch|color.diff|color.status|color.grep)
__gitcomp "always never auto"
return
;;
@@ -1240,6 +1240,11 @@ _git_config ()
color.diff.new
color.diff.commit
color.diff.whitespace
+ color.grep
+ color.grep.filepath
+ color.grep.lineno
+ color.grep.separator
+ color.grep.match
color.pager
color.status
color.status.header
@@ -1390,6 +1395,22 @@ _git_shortlog ()
__git_complete_revlist
}
+_git_grep ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --*)
+ __gitcomp "
+ --cached --text --ignore-case --word-regexp --invert-match
+ --full-name --extend-regexp --fixed-strings --files-with-matches
+ --files-without-match --count --and --or --not --all-match
+ --color
+ "
+ return
+ ;;
+ esac
+}
+
_git_show ()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
@@ -1642,7 +1663,7 @@ _git ()
fetch) _git_fetch ;;
format-patch) _git_format_patch ;;
gc) _git_gc ;;
- grep) _git_grep ;;
+ grep) _git_grep ;;
help) _git_help ;;
init) _git_init ;;
log) _git_log ;;
diff --git a/grep.c b/grep.c
index f67d671..5c3e6cd 100644
--- a/grep.c
+++ b/grep.c
@@ -1,7 +1,39 @@
#include "cache.h"
#include "grep.h"
+#include "color.h"
#include "xdiff-interface.h"
+static char grep_colors[][COLOR_MAXLEN] = {
+ "\033[m", /* reset */
+ "", /* PLAIN (normal) */
+ "\033[35m", /* FILEPATH (magenta) */
+ "\033[32m", /* LINENO (green) */
+ "\033[36m", /* SEPARATOR (cyan) */
+ "\033[1m\033[31m", /* MATCH (red)*/
+};
+
+const char *grep_get_color(enum color_grep ix)
+{
+ return grep_colors[ix];
+}
+
+int parse_grep_color_slot(const char *var, int ofs)
+{
+ if (!strcasecmp(var+ofs, "plain"))
+ return COLOR_GREP_PLAIN;
+ if (!strcasecmp(var+ofs, "reset"))
+ return COLOR_GREP_RESET;
+ if (!strcasecmp(var+ofs, "filepath"))
+ return COLOR_GREP_FILEPATH;
+ if (!strcasecmp(var+ofs, "lineno"))
+ return COLOR_GREP_LINENO;
+ if (!strcasecmp(var+ofs, "separator"))
+ return COLOR_GREP_SEPARATOR;
+ if (!strcasecmp(var+ofs, "match"))
+ return COLOR_GREP_MATCH;
+ die("bad config variable '%s'", var);
+}
+
void append_grep_pattern(struct grep_opt *opt, const char *pat,
const char *origin, int no, enum grep_pat_token t)
{
@@ -247,7 +279,10 @@ static int fixmatch(const char *pattern, char *line, regmatch_t *match)
}
}
-static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol, char *eol, enum grep_context ctx)
+static int match_one_pattern_1(struct grep_opt *opt, struct grep_pat *p,
+ char *bol, char *eol,
+ enum grep_context ctx, int eflags,
+ int *rm_so, int *rm_eo)
{
int hit = 0;
int at_true_bol = 1;
@@ -261,7 +296,7 @@ static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol
if (!opt->fixed) {
regex_t *exp = &p->regexp;
hit = !regexec(exp, bol, ARRAY_SIZE(pmatch),
- pmatch, 0);
+ pmatch, eflags);
}
else {
hit = !fixmatch(p->pattern, bol, pmatch);
@@ -298,9 +333,20 @@ static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol
goto again;
}
}
+ if (hit) {
+ if (rm_so)
+ *rm_so = pmatch[0].rm_so;
+ if (rm_eo)
+ *rm_eo = pmatch[0].rm_eo;
+ }
return hit;
}
+static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol, char *eol, enum grep_context ctx)
+{
+ return match_one_pattern_1(opt, p, bol, eol, ctx, 0, NULL, NULL);
+}
+
static int match_expr_eval(struct grep_opt *o,
struct grep_expr *x,
char *bol, char *eol,
@@ -365,6 +411,54 @@ static int match_line(struct grep_opt *opt, char *bol, char *eol,
return 0;
}
+static void show_line_colored(struct grep_opt *opt, char *bol, char *eol,
+ const char *name, unsigned lno, char sign)
+{
+ struct grep_pat *p;
+ int rm_so, rm_eo, eflags = 0;
+ int ch;
+
+ if (opt->pathname)
+ printf("%s%s%s%c%s",
+ grep_get_color(COLOR_GREP_FILEPATH),
+ name,
+ grep_get_color(COLOR_GREP_SEPARATOR),
+ sign,
+ grep_get_color(COLOR_GREP_RESET));
+ if (opt->linenum)
+ printf("%s%d%s%c%s",
+ grep_get_color(COLOR_GREP_LINENO),
+ lno,
+ grep_get_color(COLOR_GREP_SEPARATOR),
+ sign,
+ grep_get_color(COLOR_GREP_RESET));
+
+ ch = *eol;
+ *eol = 0;
+ while (bol < eol) {
+ for (p = opt->pattern_list; p; p = p->next) {
+ if (match_one_pattern_1(opt, p, bol, eol, GREP_CONTEXT_BODY, eflags, &rm_so, &rm_eo))
+ break;
+ }
+
+ /* No match, break the loop */
+ if (!p ||
+ (rm_so < 0) || (eol - bol) <= rm_so ||
+ (rm_eo < 0) || (eol - bol) < rm_eo)
+ break;
+
+ printf("%.*s%s%.*s%s",
+ rm_so, bol,
+ grep_get_color(COLOR_GREP_MATCH),
+ rm_eo-rm_so, bol+rm_so,
+ grep_get_color(COLOR_GREP_RESET));
+ bol += rm_eo;
+ eflags = REG_NOTBOL;
+ }
+ printf("%s\n", bol);
+ *eol = ch;
+}
+
static int grep_buffer_1(struct grep_opt *opt, const char *name,
char *buf, unsigned long size, int collect_hits)
{
@@ -466,8 +560,12 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
}
if (last_shown && lno != last_shown + 1)
printf(hunk_mark);
- if (!opt->count)
- show_line(opt, bol, eol, name, lno, ':');
+ if (!opt->count) {
+ if (opt->color)
+ show_line_colored(opt, bol, eol, name, lno, ':');
+ else
+ show_line(opt, bol, eol, name, lno, ':');
+ }
last_shown = last_hit = lno;
}
else if (last_hit &&
diff --git a/grep.h b/grep.h
index d252dd2..9073114 100644
--- a/grep.h
+++ b/grep.h
@@ -33,6 +33,15 @@ enum grep_expr_node {
GREP_NODE_OR,
};
+enum color_grep {
+ COLOR_GREP_RESET = 0,
+ COLOR_GREP_PLAIN = 1,
+ COLOR_GREP_FILEPATH = 2,
+ COLOR_GREP_LINENO = 3,
+ COLOR_GREP_SEPARATOR = 4,
+ COLOR_GREP_MATCH = 5,
+};
+
struct grep_expr {
enum grep_expr_node node;
unsigned hit;
@@ -68,11 +77,14 @@ struct grep_opt {
unsigned extended:1;
unsigned relative:1;
unsigned pathname:1;
+ unsigned color:1;
int regflags;
unsigned pre_context;
unsigned post_context;
};
+extern const char *grep_get_color(enum color_grep ix);
+extern int parse_grep_color_slot(const char *var, int ofs);
extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);
extern void compile_grep_patterns(struct grep_opt *opt);
extern void free_grep_patterns(struct grep_opt *opt);
reply other threads:[~2008-08-07 12:25 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ecd9a7b10808070453o3e0b34e5w27564d2e4ee73191@mail.gmail.com \
--to=thiago.salves@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).