diff -urp global-6.2.8/global/global.c global-6.2-8/global/global.c --- global-6.2.8/global/global.c 2013-02-28 21:21:06.000000000 +1000 +++ global-6.2-8/global/global.c 2013-06-28 18:06:43.374979000 +1000 @@ -24,6 +24,11 @@ #include #include #include +#if defined(_WIN32) && !defined(__CYGWIN__) +#define WIN32_LEAN_AND_MEAN +#include +#undef SLIST_ENTRY +#endif #include #include @@ -70,6 +75,7 @@ void encode(char *, int, const char *); const char *localprefix; /**< local prefix */ int aflag; /* [option] */ int cflag; /* command */ +int Cflag; /* [option] */ int dflag; /* command */ int fflag; /* command */ int gflag; /* command */ @@ -144,6 +150,8 @@ help(void) static struct option const long_options[] = { {"absolute", no_argument, NULL, 'a'}, {"completion", no_argument, NULL, 'c'}, + {"color", no_argument, NULL, 'C'}, + {"colour", no_argument, NULL, 'C'}, {"definition", no_argument, NULL, 'd'}, {"regexp", required_argument, NULL, 'e'}, {"file", no_argument, NULL, 'f'}, @@ -336,7 +344,7 @@ main(int argc, char **argv) int option_index = 0; logging_arguments(argc, argv); - while ((optchar = getopt_long(argc, argv, "acde:ifgGIlL:noOpPqrstTuvVx", long_options, &option_index)) != EOF) { + while ((optchar = getopt_long(argc, argv, "acCde:ifgGIlL:noOpPqrstTuvVx", long_options, &option_index)) != EOF) { switch (optchar) { case 0: break; @@ -347,6 +355,9 @@ main(int argc, char **argv) cflag++; setcom(optchar); break; + case 'C': + Cflag++; + break; case 'd': dflag++; break; @@ -527,6 +538,16 @@ main(int argc, char **argv) vflag = 0; if (show_help) help(); + if (Cflag) { + if (Vflag) + Cflag = 0; +#if defined(_WIN32) && !defined(__CYGWIN__) + else if (!(getenv("ANSICON") || LoadLibrary("ANSI32.dll"))) + Cflag = 0; +#endif + if (Cflag) + highlight_init(); + } argc -= optind; argv += optind; @@ -1253,7 +1279,8 @@ grep(const char *pattern, char *const *a die("cannot open file '%s'.", path); linenum = 0; while ((buffer = strbuf_fgets(ib, fp, STRBUF_NOCRLF)) != NULL) { - int result = regexec(&preg, buffer, 0, 0, 0); + regmatch_t m; + int result = regexec(&preg, buffer, Cflag ? 1 : 0, &m, 0); linenum++; if ((!Vflag && result == 0) || (Vflag && result != 0)) { count++; @@ -1261,6 +1288,8 @@ grep(const char *pattern, char *const *a convert_put_path(cv, path); break; } else { + if (Cflag) + buffer = highlight(buffer, m.rm_so, m.rm_eo - m.rm_so); convert_put_using(cv, encoded_pattern, path, linenum, buffer, (user_specified) ? NULL : gp->dbop->lastdat); } diff -urp global-6.2.8/global/literal.c global-6.2-8/global/literal.c --- global-6.2.8/global/literal.c 2013-02-28 21:21:06.000000000 +1000 +++ global-6.2-8/global/literal.c 2013-06-28 15:43:00.114756700 +1000 @@ -63,6 +63,7 @@ void cfail(void); extern int iflag; extern int Vflag; +extern int Cflag; extern void encode(char *, int, const char *); #define MAXSIZ 6000 @@ -76,6 +77,7 @@ static struct words { } w[MAXSIZ], *smax, *q; static char encoded_pattern[IDENTLEN]; +static int patlen; /** * literal_comple: compile literal for search. @@ -99,6 +101,10 @@ literal_comple(const char *pattern) * construct fail links. */ cfail(); + /* + * store length of pattern for possible highlight. + */ + patlen = strlen(pattern); } /** * literal_search: execute literal search @@ -119,6 +125,7 @@ literal_search(CONVERT *cv, const char * char *linep; long lineno; int f; + int start; if ((f = open(file, O_BINARY)) < 0) { warning("cannot open '%s'.", file); @@ -156,9 +163,10 @@ literal_search(CONVERT *cv, const char * linep = p = buf; ccount = stb.st_size; lineno = 1; + start = 0; c = w; for (;;) { - if (--ccount <= 0) + if (--ccount < 0) break; nstate: if (ccomp(c->inp, *p)) { @@ -184,8 +192,9 @@ literal_search(CONVERT *cv, const char * else goto nstate; } if (c->out) { + start = p - linep - patlen + 1; while (*p++ != '\n') { - if (--ccount <= 0) + if (--ccount < 0) break; } if (Vflag) @@ -195,19 +204,23 @@ literal_search(CONVERT *cv, const char * goto finish; } else { STATIC_STRBUF(sb); + char *s; strbuf_clear(sb); strbuf_nputs(sb, linep, p - linep); strbuf_unputc(sb, '\n'); strbuf_unputc(sb, '\r'); - convert_put_using(cv, encoded_pattern, file, lineno, strbuf_value(sb), NULL); + s = strbuf_value(sb); + if (Cflag) + s = highlight(s, start, patlen); + convert_put_using(cv, encoded_pattern, file, lineno, s, NULL); } nomatch: lineno++; linep = p; c = w; continue; } - if (*p++ == '\n') { + if (*p++ == '\n' || ccount == 0) { if (Vflag) goto succeed; else { diff -urp global-6.2.8/global/manual.in global-6.2-8/global/manual.in --- global-6.2.8/global/manual.in 2013-02-28 21:21:06.000000000 +1000 +++ global-6.2-8/global/manual.in 2013-06-28 17:23:39.282177300 +1000 @@ -28,7 +28,7 @@ @name{global} [-adGilnqrstTvx][-e] @arg{pattern} @name{global} -c[diIoOPrsT] @arg{prefix} @name{global} -f[adlnqrstvx][-L file-list] @arg{files} - @name{global} -g[aGilnoOqtvVx][-L file-list][-e] @arg{pattern} address@hidden + @name{global} -g[aCGilnoOqtvVx][-L file-list][-e] @arg{pattern} address@hidden @name{global} -I[ailnqtvx][-e] @arg{pattern} @name{global} -P[aGilnoOqtvVx][-e] @arg{pattern} @name{global} -p[qrv] @@ -91,6 +91,11 @@ @begin_itemize @address@hidden, @option{--absolute}} Print absolute path name. By default, print relative path name. + @address@hidden, @option{--color}, @option{--colour}} + Use color to highlight the pattern within the line. The default + color is bold red text on current background; the environment + variable @var{GREP_COLORS} or @var{GREP_COLOR} defines it. + This option is only valid when the @option{-g} command is specified. @address@hidden, @option{--definition}} Print locations of object definitions. @address@hidden @arg{context}} @@ -244,6 +249,11 @@ If this variable is set, the @option{-T} option is specified. @address@hidden If this variable is set, the --encode=" " option is specified. + @address@hidden + The color to use for @option{-C}; @var{GREP_COLORS} has precedence. + @address@hidden + The color (@arg{mt} or @arg{ms}) to use for @option{-C}; see @xref{grep,1}. + The default is @arg{1;31}, which is bold red text on current background. @end_itemize @CONFIGURATION The following configuration variables affect the execution of @name{global}: diff -urp global-6.2.8/libutil/pathconvert.c global-6.2-8/libutil/pathconvert.c --- global-6.2.8/libutil/pathconvert.c 2013-02-28 21:21:06.000000000 +1000 +++ global-6.2-8/libutil/pathconvert.c 2013-06-28 16:23:40.100315900 +1000 @@ -44,6 +44,7 @@ static unsigned char encode[256]; static int encoding; static int newline = '\n'; +static const char *match_sgr = "1;31"; /* bold red text */ #define required_encode(c) encode[(unsigned char)c] /** @@ -443,3 +444,50 @@ convert_close(CONVERT *cv) gpath_close(); free(cv); } +/** + * highlight: wrap an SGR sequence around characters in @a s. + * + * @param[in] s line of text + * @param[in] pos position to start highlight + * @param[in] len length of highlight + * @return highlighted text + */ +char * +highlight(const char *s, int pos, int len) +{ + STATIC_STRBUF(sb); + + strbuf_clear(sb); + strbuf_nputs(sb, s, pos); + strbuf_sprintf(sb, "\33[%sm", match_sgr); + strbuf_nputs(sb, s + pos, len); + strbuf_puts(sb, "\33[m"); + strbuf_puts(sb, s + pos + len); + return strbuf_value(sb); +} +void +highlight_init(void) +{ + STATIC_STRBUF(sb); + const char *sgr; + + sgr = getenv("GREP_COLORS"); + if (sgr) { + const char *part = strstr(sgr, "mt="); + if (!part) + part = strstr(sgr, "ms="); + if (part) { + const char *sep = strchr(part, ':'); + if (!sep) + sep = strchr(part, '\0'); + part += 3; + strbuf_nputs(sb, part, sep - part); + match_sgr = strbuf_value(sb); + } + } + else { + sgr = getenv("GREP_COLOR"); + if (sgr) + match_sgr = sgr; + } +} diff -urp global-6.2.8/libutil/pathconvert.h global-6.2-8/libutil/pathconvert.h --- global-6.2.8/libutil/pathconvert.h 2013-02-28 21:21:06.000000000 +1000 +++ global-6.2-8/libutil/pathconvert.h 2013-06-28 12:58:53.296479900 +1000 @@ -42,5 +42,7 @@ void convert_put(CONVERT *, const char * void convert_put_path(CONVERT *, const char *); void convert_put_using(CONVERT *, const char *, const char *, int, const char *, const char *); void convert_close(CONVERT *cv); +char *highlight(const char *, int, int); +void highlight_init(void); #endif /* ! _PATHCONVERT_H_ */