Here's the patch for 6.2.11. Since -S has now been taken by --scope,
I've used -N for --project.
--
Jason.
diff -pur global-6.2.11/global/global.c global-6.2-11/global/global.c
--- global-6.2.11/global/global.c 2014-03-12 12:49:34 +1000
+++ global-6.2-11/global/global.c 2014-03-12 23:45:32 +1000
@@ -38,6 +38,11 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef SLIST_ENTRY
+#endif
#include "getopt.h"
#include "global.h"
@@ -54,6 +59,7 @@ static void usage(void);
static void help(void);
static void setcom(int);
int decide_tag_by_context(const char *, const char *, int);
+int prepend_args(const char *, int *, char ***);
int main(int, char **);
int completion_tags(const char *, const char *, const char *, int);
void completion(const char *, const char *, const char *, int);
@@ -73,6 +79,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 */
@@ -148,16 +155,21 @@ help(void)
static struct option const long_options[] = {
{"absolute", no_argument, NULL, 'a'},
{"completion", no_argument, NULL, 'c'},
+ {"color", optional_argument, NULL, 'C'},
+ {"colour", optional_argument, NULL, 'C'},
{"definition", no_argument, NULL, 'd'},
{"regexp", required_argument, NULL, 'e'},
+ {"extended-regexp", no_argument, NULL, 'E'},
{"file", no_argument, NULL, 'f'},
{"local", no_argument, NULL, 'l'},
{"file-list", required_argument, NULL, 'L'},
{"nofilter", optional_argument, NULL, 'n'},
+ {"project", no_argument, NULL, 'N'},
{"grep", no_argument, NULL, 'g'},
{"basic-regexp", no_argument, NULL, 'G'},
{"ignore-case", no_argument, NULL, 'i'},
{"idutils", no_argument, NULL, 'I'},
+ {"match-case", no_argument, NULL, 'm'},
{"other", no_argument, NULL, 'o'},
{"only-other", no_argument, NULL, 'O'},
{"print-dbpath", no_argument, NULL, 'p'},
@@ -332,6 +344,62 @@ finish:
}
return db;
}
+/**
+ * prepend_args: insert arguments from a string into an array
+ *
+ * @param[in] var string containing arguments to be inserted
+ * @param argc current and new array size
+ * @param argv current and new array arguments
+ * @return number of arguments prepended
+ *
+ * @note preserves first element and assumes NULL exists after last.
+ * @note backslash is used to escape the next character.
+ * @note in DOS and Windows, @CODE{~} is translated to @CODE{=}
(@FILE{COMMAND.COM} compatibility).
+ */
+int
+prepend_args(const char *var, int *argc, char ***argv)
+{
+ int cnt = 0;
+
+ if (var && *var) {
+ char *buf = check_strdup(var);
+ char *s = buf;
+ char *d = buf;
+ char **a, **args, **arg = *argv;
+ int i;
+ for (;;) {
+ while (*s && isspace(*s))
+ ++s;
+ if (!*s)
+ break;
+ ++cnt;
+ do {
+ *d = *s++;
+#if defined(__DJGPP__) || defined(_WIN32)
+ if (*d == '~')
+ *d = '=';
+ else
+#endif
+ if (*d == '\\' && *s)
+ *d = *s++;
+ ++d;
+ } while (*s && !isspace(*s));
+ *d++ = '\0';
+ }
+ a = args = check_malloc((*argc + cnt + 1) * sizeof(char*));
+ *a++ = *arg++;
+ s = buf;
+ for (i = 0; i < cnt; ++i) {
+ *a++ = s;
+ s = strchr(s, '\0') + 1;
+ }
+ memcpy(a, arg, *argc * sizeof(char*));
+ *argc += cnt;
+ *argv = args;
+ }
+
+ return cnt;
+}
int
main(int argc, char **argv)
{
@@ -340,8 +408,11 @@ main(int argc, char **argv)
int optchar;
int option_index = 0;
+ if (getenv("GTAGSTHROUGH"))
+ Tflag++;
+ prepend_args(getenv("GLOBAL_OPTIONS"), &argc, &argv);
logging_arguments(argc, argv);
- while ((optchar = getopt_long(argc, argv,
"acde:ifgGIlL:noOpPqrsS:tTuvVx", long_options, &option_index)) != EOF) {
+ while ((optchar = getopt_long(argc, argv,
"acCde:EifgGIlL:mnNoOpPqrsS:tTuvVx", long_options, &option_index)) != EOF) {
switch (optchar) {
case 0:
break;
@@ -352,12 +423,28 @@ main(int argc, char **argv)
cflag++;
setcom(optchar);
break;
+ case 'C':
+ if (optarg) {
+ if (!strcmp(optarg, "never"))
+ Cflag = 0;
+ else if (!strcmp(optarg, "always"))
+ Cflag = 1;
+ else if (!strcmp(optarg, "auto"))
+ Cflag = 2;
+ else
+ die_with_code(2, "unknown color type
for the --color option.");
+ } else
+ Cflag = 2;
+ break;
case 'd':
dflag++;
break;
case 'e':
av = optarg;
break;
+ case 'E':
+ Gflag = 0;
+ break;
case 'f':
fflag++;
xflag++;
@@ -384,6 +471,9 @@ main(int argc, char **argv)
case 'L':
file_list = optarg;
break;
+ case 'm':
+ iflag = 0;
+ break;
case 'n':
nflag++;
if (optarg) {
@@ -395,6 +485,9 @@ main(int argc, char **argv)
nofilter = BOTH_FILTER;
}
break;
+ case 'N':
+ Tflag = 0;
+ break;
case 'o':
oflag++;
break;
@@ -531,12 +624,23 @@ main(int argc, char **argv)
warning("cannot encode '/' and '.' in the path.
Ignored.");
set_encode_chars((unsigned char *)encode_chars);
}
- if (getenv("GTAGSTHROUGH"))
- Tflag++;
if (qflag)
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 == 2)
+ Cflag = 0;
+#endif
+ if (Cflag == 2 && !isatty(1))
+ Cflag = 0;
+ if (Cflag)
+ highlight_init();
+ }
argc -= optind;
argv += optind;
@@ -1067,6 +1171,7 @@ idutils(const char *pattern, const char
const char *lid;
int linenum, count;
char *p, *q, *grep;
+ regex_t preg;
lid = usable("lid");
if (!lid)
@@ -1101,6 +1206,38 @@ idutils(const char *pattern, const char
cv = convert_open(type, format, root, cwd, dbpath, stdout, NOTAGS);
count = 0;
strcpy(path, "./");
+ if (Cflag) {
+ int flags = REG_EXTENDED;
+ STRBUF *pb = strbuf_open(0);
+ if (isregex(pattern)) {
+ FILE *tp;
+ STRBUF *tb = strbuf_open(0);
+ strbuf_sprintf(tb, "%s --file=%s/ID --result=none
--regexp", lid, quote_shell(dbpath));
+ if (iflag)
+ strbuf_puts(tb, " --ignore-case");
+ strbuf_putc(tb, ' ');
+ strbuf_puts(tb, quote_shell(pattern));
+ tp = popen(strbuf_value(tb), "r");
+ strbuf_puts(pb, "\\b(");
+ while ((grep = strbuf_fgets(tb, tp, STRBUF_NOCRLF)) !=
NULL) {
+ strbuf_puts(pb, grep);
+ strbuf_putc(pb, '|');
+ }
+ strbuf_unputc(pb, '|');
+ strbuf_puts(pb, ")\\b");
+ pclose(tp);
+ strbuf_close(tb);
+ } else {
+ strbuf_puts(pb, "\\b");
+ strbuf_puts(pb, pattern);
+ strbuf_puts(pb, "\\b");
+ if (iflag)
+ flags |= REG_ICASE;
+ }
+ if (regcomp(&preg, strbuf_value(pb), flags) != 0)
+ die("invalid regular expression.");
+ strbuf_close(pb);
+ }
while ((grep = strbuf_fgets(ib, ip, STRBUF_NOCRLF)) != NULL) {
q = path + 2;
/* extract path name */
@@ -1137,6 +1274,11 @@ idutils(const char *pattern, const char
/*
* print out.
*/
+ if (Cflag) {
+ regmatch_t m;
+ if (regexec(&preg, p, 1, &m, 0) == 0)
+ p = highlight(p, m.rm_so, m.rm_eo -
m.rm_so);
+ }
convert_put_using(cv, encoded_pattern, path, linenum,
p, NULL);
break;
}
@@ -1149,6 +1291,8 @@ idutils(const char *pattern, const char
print_count(count);
fprintf(stderr, " (using idutils index in '%s').\n", dbpath);
}
+ if (Cflag)
+ regfree(&preg);
}
/**
* grep: @NAME{grep} pattern
@@ -1249,7 +1393,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++;
@@ -1257,6 +1402,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);
}
@@ -1328,10 +1475,13 @@ pathlist(const char *pattern, const char
*/
p = path + strlen(localprefix) - 1;
if (pattern) {
- int result = regexec(&preg, p, 0, 0, 0);
+ regmatch_t m;
+ int result = regexec(&preg, p, Cflag ? 1 : 0, &m, 0);
if ((!Vflag && result != 0) || (Vflag && result == 0))
continue;
+ if (Cflag && result == 0)
+ path = highlight(path, m.rm_so + p - path,
m.rm_eo - m.rm_so);
} else if (Vflag)
continue;
if (format == FORMAT_PATH)
@@ -1428,6 +1578,8 @@ put_syms(int type, const char *tag, int
default:
return;
}
+ if (Cflag)
+ line_image = highlight_tag(tag, line_image);
convert_put_using(data->cv, tag, path, lno, line_image, data->fid);
data->count++;
}
diff -pur global-6.2.11/global/literal.c global-6.2-11/global/literal.c
--- global-6.2.11/global/literal.c 2014-03-12 12:49:34 +1000
+++ global-6.2-11/global/literal.c 2014-03-12 23:24:25 +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
@@ -120,6 +126,7 @@ literal_search(CONVERT *cv, const char *
long lineno;
int f;
int count = 0;
+ int start;
if ((f = open(file, O_BINARY)) < 0) {
warning("cannot open '%s'.", file);
@@ -157,6 +164,7 @@ literal_search(CONVERT *cv, const char *
linep = p = buf;
ccount = stb.st_size;
lineno = 1;
+ start = 0;
c = w;
for (;;) {
if (--ccount < 0)
@@ -185,6 +193,7 @@ literal_search(CONVERT *cv, const char *
else goto nstate;
}
if (c->out) {
+ start = p - linep - patlen + 1;
while (*p++ != '\n') {
if (--ccount < 0)
break;
@@ -197,12 +206,16 @@ 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);
count++;
}
nomatch: lineno++;
diff -pur global-6.2.11/global/manual.in global-6.2-11/global/manual.in
--- global-6.2.11/global/manual.in 2014-03-12 12:49:34 +1000
+++ global-6.2-11/global/manual.in 2014-03-12 23:46:50 +1000
@@ -25,12 +25,12 @@
@HEADER GLOBAL,1,Jun 2013,GNU Project
@NAME global - print locations of given symbols
@SYNOPSIS
- @name{global} [-adGilnqrsStTvx][-e] @arg{pattern}
- @name{global} -c[diIoOPrsT] @arg{prefix}
- @name{global} -f[adlnqrsStvx][-L file-list] @arg{files}
- @name{global} -g[aGilnoOqStvVx][-L file-list][-e] @arg{pattern}
[@arg{files}]
- @name{global} -I[ailnqStvx][-e] @arg{pattern}
- @name{global} -P[aGilnoOqStvVx][-e] @arg{pattern}
+ @name{global} [-aCdEGilmnNqrsStTvx][-e] @arg{pattern}
+ @name{global} -c[diImNoOPrsT] @arg{prefix}
+ @name{global} -f[aCdlnqrsStvx][-L file-list] @arg{files}
+ @name{global} -g[aCEGilmnoOqStvVx][-L file-list][-e] @arg{pattern}
[@arg{files}]
+ @name{global} -I[aCilmnqStvx][-e] @arg{pattern}
+ @name{global} -P[aCEGilmnoOqStvVx][-e] @arg{pattern}
@name{global} -p[qrv]
@name{global} -u[qv]
@DESCRIPTION
@@ -94,10 +94,18 @@
@begin_itemize
@item{@option{-a}, @option{--absolute}}
Print absolute path names. By default, print relative path
names.
+ @item{@option{-C}, @option{--color}, @option{--colour} @arg{when}}
+ Use color to highlight the pattern within the line; @arg{when}
may be one
+ of: @arg{never}, @arg{always} or @arg{auto} (default). The
default color is bold red
+ text on current background; the environment variable
@var{GREP_COLORS} or
+ @var{GREP_COLOR} defines it.
@item{@option{-d}, @option{--definition}}
Print locations of definitions.
@item{@option{-e}, @option{--regexp} @arg{pattern}}
Use @arg{pattern} as the pattern; useful to protect patterns
starting with @samp{-}.
+ @item{@option{-E}, @option{--extended-regexp}}
+ Interpret @arg{pattern} as an extended regular expression.
+ This is provided to override @option{-G} in
@var{GLOBAL_OPTIONS}.
@item{@option{--encode-path} @arg{chars}}
Convert path characters in @arg{chars} into a @samp{%} symbol,
followed by the
two-digit hexadecimal representation of the character.
@@ -122,6 +130,9 @@
@item{@option{--literal}}
Execute literal search instead of regular expression search.
This option is only valid when the @option{-g} command is
specified.
+ @item{@option{-m}, @option{--match-case}}
+ Consider case distinctions in the pattern.
+ This is provided to override @option{-i} in
@var{GLOBAL_OPTIONS}.
@item{@option{--match-part @arg{part}}}
Specify how path name completion should match, where @arg{part}
is one of:
@val{first}, @val{last} or @val{all} (default).
@@ -129,6 +140,9 @@
@item{@option{-n}, @option{--nofilter}}
Suppress sort filter and path conversion filter.
+ @item{@option{-N}, @option{--project}}
+ Consider only the project's tag files.
+ This is provided to override @option{-T} in
@var{GLOBAL_OPTIONS}.
@item{@option{-O}, @option{--only-other}}
Treat only text files other than source code, like
@file{README}.
This option is valid only with the @option{-g} or @option{-P}
command.
@@ -234,6 +248,15 @@
The following environment variables affect the execution of
@name{global}:
@begin_itemize
+ @item{@var{GLOBAL_OPTIONS}}
+ Use this variable to always add options to the beginning of the
+ command line (like 'global $GLOBAL_OPTIONS ...').
+ Backslash is used to escape the next character.
+ @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.
@item{@var{GTAGSBLANKENCODE}}
If this variable is set, the @option{--encode-path=" <TAB>"}
option is specified.
@@ -262,6 +285,7 @@
The root directory of the project.
@item{@var{GTAGSTHROUGH}}
If this variable is set, the @option{-T} option is specified.
+ (Deprecated, please use @var{GLOBAL_OPTIONS} instead.)
@item{@var{MAKEOBJDIR}}
If this variable is set, @file{$MAKEOBJDIR} is used as the name
of BSD-style objdir. The default is @file{obj}.
diff -pur global-6.2.11/global/output.c global-6.2-11/global/output.c
--- global-6.2.11/global/output.c 2014-03-12 12:49:34 +1000
+++ global-6.2-11/global/output.c 2014-03-12 23:24:25 +1000
@@ -40,6 +40,7 @@ static void put_standard_format(CONVERT
extern const char *root;
extern int nosource;
extern int format;
+extern int Cflag;
/** get next number and seek to the next character */
#define GET_NEXT_NUMBER(p) do {
\
@@ -180,6 +181,8 @@ put_compact_format(CONVERT *cv, GTP *gtp
}
if (flags & GTAGS_COMPNAME)
tagname = (char *)uncompress(tagname, gtp->tag);
+ if (Cflag)
+ src = highlight_tag(tagname, src);
convert_put_using(cv, tagname, gtp->path, n, src, fid);
count++;
last_lineno = last = n;
@@ -210,6 +213,8 @@ put_compact_format(CONVERT *cv, GTP *gtp
}
if (flags & GTAGS_COMPNAME)
tagname = (char *)uncompress(tagname, gtp->tag);
+ if (Cflag)
+ src = highlight_tag(tagname, src);
convert_put_using(cv, tagname, gtp->path, n, src, fid);
count++;
last_lineno = n;
@@ -251,5 +256,7 @@ put_standard_format(CONVERT *cv, GTP *gt
if (flags & GTAGS_COMPRESS)
image = (char *)uncompress(image, gtp->tag);
}
+ if (Cflag)
+ image = highlight_tag(tagname, image);
convert_put_using(cv, tagname, gtp->path, gtp->lineno, image, fid);
}
diff -pur global-6.2.11/libutil/pathconvert.c
global-6.2-11/libutil/pathconvert.c
--- global-6.2.11/libutil/pathconvert.c 2014-03-12 12:49:34 +1000
+++ global-6.2-11/libutil/pathconvert.c 2014-03-12 23:24:25 +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,82 @@ convert_close(CONVERT *cv)
gpath_close();
free(cv);
}
+void
+highlight_init(void)
+{
+ STATIC_STRBUF(sb);
+ const char *sgr;
+
+ sgr = getenv("GREP_COLOR");
+ if (sgr)
+ match_sgr = 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);
+ }
+ }
+}
+/**
+ * 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);
+ if (len <= 0)
+ strbuf_puts(sb, s);
+ else {
+ 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);
+}
+/**
+ * highlight_tag: wrap an SGR sequence around @a tag in @a s.
+ *
+ * @param[in] tag tag
+ * @param[in] s line of text
+ * @return highlighted text (s if not found)
+ *
+ * @note Finds the first word matching tag, not necessarily the tag itself.
+ */
+const char *
+highlight_tag(const char *tag, const char *s)
+{
+ static regex_t preg;
+ regmatch_t m;
+ STATIC_STRBUF(tb);
+ int len = strlen(tag);
+
+ if (strbuf_getlen(tb) != len + 2
+ || strncmp(tag, strbuf_value(tb) + 1, len) != 0) {
+ strbuf_clear(tb);
+ strbuf_puts(tb, "\\b");
+ strbuf_puts(tb, tag);
+ strbuf_puts(tb, "\\b");
+ regfree(&preg);
+ regcomp(&preg, strbuf_value(tb), 0);
+ }
+ if (regexec(&preg, s, 1, &m, 0) == 0)
+ s = highlight(s, m.rm_so, m.rm_eo - m.rm_so);
+ return s;
+}
diff -pur global-6.2.11/libutil/pathconvert.h
global-6.2-11/libutil/pathconvert.h
--- global-6.2.11/libutil/pathconvert.h 2014-03-12 12:49:34 +1000
+++ global-6.2-11/libutil/pathconvert.h 2014-03-12 23:24:25 +1000
@@ -42,5 +42,8 @@ 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);
+void highlight_init(void);
+char *highlight(const char *, int, int);
+const char *highlight_tag(const char *, const char *);
#endif /* ! _PATHCONVERT_H_ */
_______________________________________________
Bug-global mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/bug-global