Revision: 568
http://www.exim.org/viewvc/pcre2?view=rev&revision=568
Author: ph10
Date: 2016-10-14 17:17:48 +0100 (Fri, 14 Oct 2016)
Log Message:
-----------
Dmitry Cherniachenko's patch for colouring pcre2grep output in Windows.
Modified Paths:
--------------
code/trunk/ChangeLog
code/trunk/doc/pcre2grep.1
code/trunk/src/pcre2grep.c
Modified: code/trunk/ChangeLog
===================================================================
--- code/trunk/ChangeLog 2016-10-14 15:47:27 UTC (rev 567)
+++ code/trunk/ChangeLog 2016-10-14 16:17:48 UTC (rev 568)
@@ -74,7 +74,11 @@
12. Added some "const" qualifiers to variables in pcre2grep.
+13. Added Dmitry Cherniachenko's patch for colouring output in Windows
+(untested by me). Also, look for GREP_COLOUR or GREP_COLOR if the environment
+variables PCRE2GREP_COLOUR and PCRE2GREP_COLOR are not found.
+
Version 10.22 29-July-2016
--------------------------
Modified: code/trunk/doc/pcre2grep.1
===================================================================
--- code/trunk/doc/pcre2grep.1 2016-10-14 15:47:27 UTC (rev 567)
+++ code/trunk/doc/pcre2grep.1 2016-10-14 16:17:48 UTC (rev 568)
@@ -1,4 +1,4 @@
-.TH PCRE2GREP 1 "11 October 2016" "PCRE2 10.23"
+.TH PCRE2GREP 1 "14 October 2016" "PCRE2 10.23"
.SH NAME
pcre2grep - a grep with Perl-compatible regular expressions.
.SH SYNOPSIS
@@ -206,11 +206,12 @@
just one, in order to colour them all.
.sp
The colour that is used can be specified by setting the environment variable
-PCRE2GREP_COLOUR or PCRE2GREP_COLOR. The value of this variable should be a
-string of two numbers, separated by a semicolon. They are copied directly into
-the control string for setting colour on a terminal, so it is your
-responsibility to ensure that they make sense. If neither of the environment
-variables is set, the default is "1;31", which gives red.
+PCRE2GREP_COLOUR or PCRE2GREP_COLOR. If neither of these are set,
+\fBpcre2grep\fP looks for GREP_COLOUR or GREP_COLOR. The value of the variable
+should be a string of two numbers, separated by a semicolon. They are copied
+directly into the control string for setting colour on a terminal, so it is
+your responsibility to ensure that they make sense. If neither of the
+environment variables is set, the default is "1;31", which gives red.
.TP
\fB-D\fP \fIaction\fP, \fB--devices=\fP\fIaction\fP
If an input path is not a regular file or a directory, "action" specifies how
@@ -525,12 +526,13 @@
Show only the part of the line that matched a pattern instead of the whole
line. In this mode, no context is shown. That is, the \fB-A\fP, \fB-B\fP, and
\fB-C\fP options are ignored. If there is more than one match in a line, each
-of them is shown separately. If \fB-o\fP is combined with \fB-v\fP (invert the
-sense of the match to find non-matching lines), no output is generated, but the
-return code is set appropriately. If the matched portion of the line is empty,
-nothing is output unless the file name or line number are being printed, in
-which case they are shown on an otherwise empty line. This option is mutually
-exclusive with \fB--file-offsets\fP and \fB--line-offsets\fP.
+of them is shown separately, on a separate line of output. If \fB-o\fP is
+combined with \fB-v\fP (invert the sense of the match to find non-matching
+lines), no output is generated, but the return code is set appropriately. If
+the matched portion of the line is empty, nothing is output unless the file
+name or line number are being printed, in which case they are shown on an
+otherwise empty line. This option is mutually exclusive with
+\fB--file-offsets\fP and \fB--line-offsets\fP.
.TP
\fB-o\fP\fInumber\fP, \fB--only-matching\fP=\fInumber\fP
Show only the part of the line that matched the capturing parentheses of the
@@ -542,10 +544,11 @@
capturing parentheses do not exist in the pattern, or were not set in the
match, nothing is output unless the file name or line number are being output.
.sp
-If this option is given multiple times, multiple substrings are output, in the
-order the options are given. For example, -o3 -o1 -o3 causes the substrings
-matched by capturing parentheses 3 and 1 and then 3 again to be output. By
-default, there is no separator (but see the next option).
+If this option is given multiple times, multiple substrings are output for each
+match, in the order the options are given, and all on one line. For example,
+-o3 -o1 -o3 causes the substrings matched by capturing parentheses 3 and 1 and
+then 3 again to be output. By default, there is no separator (but see the next
+option).
.TP
\fB--om-separator\fP=\fItext\fP
Specify a separating string for multiple occurrences of \fB-o\fP. The default
@@ -775,6 +778,6 @@
.rs
.sp
.nf
-Last updated: 11 October 2016
+Last updated: 14 October 2016
Copyright (c) 1997-2016 University of Cambridge.
.fi
Modified: code/trunk/src/pcre2grep.c
===================================================================
--- code/trunk/src/pcre2grep.c 2016-10-14 15:47:27 UTC (rev 567)
+++ code/trunk/src/pcre2grep.c 2016-10-14 16:17:48 UTC (rev 568)
@@ -681,6 +681,17 @@
}
#endif
+
+/************* Print optionally coloured match Unix-style and z/OS **********/
+
+static void
+print_match(const char* buf, int length)
+{
+if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);
+FWRITE(buf, 1, length, stdout);
+if (do_colour) fprintf(stdout, "%c[00m", 0x1b);
+}
+
/* End of Unix-style or native z/OS environment functions. */
@@ -814,6 +825,65 @@
return FALSE;
}
+
+/************* Print optionally coloured match in Windows **********/
+
+static HANDLE hstdout;
+static CONSOLE_SCREEN_BUFFER_INFO csbi;
+static WORD match_colour;
+
+static void
+print_match(const char* buf, int length)
+{
+if (do_colour) SetConsoleTextAttribute(hstdout, match_colour);
+FWRITE(buf, 1, length, stdout);
+if (do_colour) SetConsoleTextAttribute(hstdout, csbi.wAttributes);
+}
+
+/* Convert ANSI BGR format to RGB used by Windows */
+#define BGR_RGB(x) ((x & 1 ? 4 : 0) | (x & 2) | (x & 4 ? 1 : 0))
+
+static WORD
+decode_ANSI_colour(char *cs)
+{
+WORD result = 0;
+while (*cs)
+ {
+ if (isdigit(*cs))
+ {
+ int code = atoi(cs);
+ if (code == 1) result |= 0x08;
+ else if (code >= 30 && code <= 37) result = (result & 0xF8) | BGR_RGB(code - 30);
+ else if (code == 39) result = (result & 0xF0) | (csbi.wAttributes & 0x0F);
+ else if (code >= 40 && code <= 47) result = (result & 0x8F) | (BGR_RGB(code - 40) << 4);
+ else if (code == 49) result = (result & 0x0F) | (csbi.wAttributes & 0xF0);
+ /* aixterm high intensity colour codes */
+ else if (code >= 90 && code <= 97) result = (result & 0xF0) | BGR_RGB(code - 90) | 0x08;
+ else if (code >= 100 && code <= 107) result = (result & 0x0F) | (BGR_RGB(code - 100) << 4) | 0x80;
+
+ while (isdigit(*cs)) cs++;
+ }
+
+ if (*cs) cs++;
+ }
+
+return result;
+}
+
+static void
+init_colour_output()
+{
+if (do_colour)
+ {
+ hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ GetConsoleScreenBufferInfo(hstdout, &csbi);
+
+ match_colour = decode_ANSI_colour(colour_string);
+ /* No valid colour found - turn off colouring */
+ if (!match_colour) do_colour = FALSE;
+ }
+}
+
/* End of Windows functions */
@@ -2113,9 +2183,7 @@
if (plen > 0)
{
if (printed) fprintf(stdout, "%s", om_separator);
- if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string);
- FWRITE(matchptr + offsets[n*2], 1, plen, stdout);
- if (do_colour) fprintf(stdout, "%c[00m", 0x1b);
+ print_match(matchptr + offsets[n*2], plen);
printed = TRUE;
}
}
@@ -2283,9 +2351,7 @@
{
int plength;
FWRITE(ptr, 1, offsets[0], stdout);
- fprintf(stdout, "%c[%sm", 0x1b, colour_string);
- FWRITE(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
- fprintf(stdout, "%c[00m", 0x1b);
+ print_match(ptr + offsets[0], offsets[1] - offsets[0]);
for (;;)
{
startoffset = offsets[1];
@@ -2293,9 +2359,7 @@
!match_patterns(matchptr, length, options, startoffset, &mrc))
break;
FWRITE(matchptr + startoffset, 1, offsets[0] - startoffset, stdout);
- fprintf(stdout, "%c[%sm", 0x1b, colour_string);
- FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout);
- fprintf(stdout, "%c[00m", 0x1b);
+ print_match(matchptr + offsets[0], offsets[1] - offsets[0]);
}
/* In multiline mode, we may have already printed the complete line
@@ -3391,7 +3455,12 @@
{
char *cs = getenv("PCRE2GREP_COLOUR");
if (cs == NULL) cs = getenv("PCRE2GREP_COLOR");
+ if (cs == NULL) cs = getenv("GREP_COLOUR");
+ if (cs == NULL) cs = getenv("GREP_COLOR");
if (cs != NULL) colour_string = cs;
+#if defined HAVE_WINDOWS_H && HAVE_WINDOWS_H
+ init_colour_output();
+#endif
}
}