On 31/05/2013 19:10, Shigio YAMAGUCHI wrote:
> On Fri, 31 May 2013 12:04:26 +0800
> Leo Liu <[email protected]> wrote:
> 
>> I like the brief output from --result=grep. Unfortunately it is not easy
>> to identify the tag found in each line. It'd be nice if the matched tag
>> is coloured, for example, like 'grep' with '--color'.
> 
> I have added the option to the TODO list.
> (http://www.gnu.org/software/global/plans.html)

Find attached a patch that adds -C (--color, --colour) to do it.  It
uses GREP_COLORS (mt or ms) or GREP_COLOR to define the color; default
is bold red text.  It only works with -g, whatever the output.  The
Windows version will require ANSICON (ANSI32.dll), but I'll include
that in my binaries (global.exe with colour and fixed idutils and
--single-update, along with gtags.exe with fixed idutils are here:
http://global.adoxa.vze.com/global.zip).

The patch also fixes literal matching at the end of the file (-V
wasn't including the last line, nor did it properly test/display the
last line if it didn't have a newline).

-- 
Jason.
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 <sys/types.h>
 #include <sys/stat.h>
 #include <errno.h>
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef SLIST_ENTRY
+#endif
 
 #include <ctype.h>
 #include <stdio.h>
@@ -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} 
[@arg{files}]
+       @name{global} -g[aCGilnoOqtvVx][-L file-list][-e] @arg{pattern} 
[@arg{files}]
        @name{global} -I[ailnqtvx][-e] @arg{pattern}
        @name{global} -P[aGilnoOqtvVx][-e] @arg{pattern}
        @name{global} -p[qrv]
@@ -91,6 +91,11 @@
        @begin_itemize
        @item{@option{-a}, @option{--absolute}}
                Print absolute path name. By default, print relative path name.
+       @item{@option{-C}, @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.
        @item{@option{-d}, @option{--definition}}
                Print locations of object definitions.
        @item{@option{--from-here} @arg{context}}
@@ -244,6 +249,11 @@
                If this variable is set, the @option{-T} option is specified.
        @item{@var{GTAGSBLANKENCODE}}
                If this variable is set, the --encode=" <TAB>" option is 
specified.
+       @item{@var{GREP_COLOR}}
+               The color to use for @option{-C}; @var{GREP_COLORS} has 
precedence.
+       @item{@var{GREP_COLORS}}
+               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_ */
_______________________________________________
Bug-global mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/bug-global

Reply via email to