summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNico Williams <nico@cryptonector.com>2017-04-29 13:00:52 -0500
committerWilliam Langford <wlangfor@gmail.com>2017-04-29 14:00:52 -0400
commit6d89e297febdbcbad4ecf201e56fc8ec99f67137 (patch)
treecc70c53bf330c65c8cabe10152c89ce9805c5e12
parent32d8f2000a80c3702b04f3423180ebfeaa503eb7 (diff)
Add JQ_COLORS env var for color config (fix #1252)
-rw-r--r--docs/content/3.manual/manual.yml42
-rw-r--r--jq.1.prebuilt84
-rw-r--r--src/jq.h2
-rw-r--r--src/jv_print.c37
-rw-r--r--src/main.c3
-rwxr-xr-xtests/shtest54
6 files changed, 221 insertions, 1 deletions
diff --git a/docs/content/3.manual/manual.yml b/docs/content/3.manual/manual.yml
index f666ceb1..fcca8412 100644
--- a/docs/content/3.manual/manual.yml
+++ b/docs/content/3.manual/manual.yml
@@ -160,6 +160,9 @@ sections:
terminal. You can force it to produce color even if writing to
a pipe or a file using `-C`, and disable color with `-M`.
+ Colors can be configured with the `JQ_COLORS` environment
+ variable (see below).
+
* `--ascii-output` / `-a`:
jq usually outputs non-ASCII Unicode codepoints as UTF-8, even
@@ -3195,3 +3198,42 @@ sections:
could then use to, for example, search for, download, and
install missing dependencies.
+ - title: Colors
+ body: |
+
+ To configure alternative colors just set the `JQ_COLORS`
+ environment variable to colon-delimited list of partial terminal
+ escape sequences like `"1;31"`, in this order:
+
+ - color for `null`
+ - color for `false`
+ - color for `true`
+ - color for numbers
+ - color for strings
+ - color for arrays
+ - color for objects
+
+ The default color scheme is the same as setting
+ `"JQ_COLORS=1;30:0;39:0;39:0;39:0;32:1;39:1;39"`.
+
+ This is not a manual for VT100/ANSI escapes. However, each of
+ these color specifications should consist of two numbers separated
+ by a semi-colon, where the first number is one of these:
+
+ - 1 (bright)
+ - 2 (dim)
+ - 4 (underscore)
+ - 5 (blink)
+ - 7 (reverse)
+ - 8 (hidden)
+
+ and the second is one of these:
+
+ - 30 (black)
+ - 31 (red)
+ - 32 (green)
+ - 33 (yellow)
+ - 34 (blue)
+ - 35 (magenta)
+ - 36 (cyan)
+ - 37 (white)
diff --git a/jq.1.prebuilt b/jq.1.prebuilt
index ef04d741..21a0fcd0 100644
--- a/jq.1.prebuilt
+++ b/jq.1.prebuilt
@@ -105,6 +105,9 @@ Use the given number of spaces (no more than 8) for indentation\.
.IP
By default, jq outputs colored JSON if writing to a terminal\. You can force it to produce color even if writing to a pipe or a file using \fB\-C\fR, and disable color with \fB\-M\fR\.
.
+.IP
+Colors can be configured with the \fBJQ_COLORS\fR environment variable (see below)\.
+.
.IP "\(bu" 4
\fB\-\-ascii\-output\fR / \fB\-a\fR:
.
@@ -3373,6 +3376,87 @@ Takes a module name as input and outputs the module\'s metadata as an object, wi
.P
Programs can use this to query a module\'s metadata, which they could then use to, for example, search for, download, and install missing dependencies\.
.
+.SH "COLORS"
+To configure alternative colors just set the \fBJQ_COLORS\fR environment variable to colon\-delimited list of partial terminal escape sequences like \fB"1;31"\fR, in this order:
+.
+.IP "\(bu" 4
+color for \fBnull\fR
+.
+.IP "\(bu" 4
+color for \fBfalse\fR
+.
+.IP "\(bu" 4
+color for \fBtrue\fR
+.
+.IP "\(bu" 4
+color for numbers
+.
+.IP "\(bu" 4
+color for strings
+.
+.IP "\(bu" 4
+color for arrays
+.
+.IP "\(bu" 4
+color for objects
+.
+.IP "" 0
+.
+.P
+The default color scheme is the same as setting \fB"JQ_COLORS=1;30:0;39:0;39:0;39:0;32:1;39:1;39"\fR\.
+.
+.P
+This is not a manual for VT100/ANSI escapes\. However, each of these color specifications should consist of two numbers separated by a semi\-colon, where the first number is one of these:
+.
+.IP "\(bu" 4
+1 (bright)
+.
+.IP "\(bu" 4
+2 (dim)
+.
+.IP "\(bu" 4
+4 (underscore)
+.
+.IP "\(bu" 4
+5 (blink)
+.
+.IP "\(bu" 4
+7 (reverse)
+.
+.IP "\(bu" 4
+8 (hidden)
+.
+.IP "" 0
+.
+.P
+and the second is one of these:
+.
+.IP "\(bu" 4
+30 (black)
+.
+.IP "\(bu" 4
+31 (red)
+.
+.IP "\(bu" 4
+32 (green)
+.
+.IP "\(bu" 4
+33 (yellow)
+.
+.IP "\(bu" 4
+34 (blue)
+.
+.IP "\(bu" 4
+35 (magenta)
+.
+.IP "\(bu" 4
+36 (cyan)
+.
+.IP "\(bu" 4
+37 (white)
+.
+.IP "" 0
+.
.SH "BUGS"
Presumably\. Report them or discuss them at:
.
diff --git a/src/jq.h b/src/jq.h
index 3067d8ae..5269de3f 100644
--- a/src/jq.h
+++ b/src/jq.h
@@ -66,4 +66,6 @@ jv jq_util_input_get_position(jq_state*);
jv jq_util_input_get_current_filename(jq_state*);
jv jq_util_input_get_current_line(jq_state*);
+int jq_set_colors(const char *);
+
#endif /* !JQ_H */
diff --git a/src/jv_print.c b/src/jv_print.c
index 3fcf8378..5ebc01e6 100644
--- a/src/jv_print.c
+++ b/src/jv_print.c
@@ -27,11 +27,46 @@
static const jv_kind color_kinds[] =
{JV_KIND_NULL, JV_KIND_FALSE, JV_KIND_TRUE, JV_KIND_NUMBER,
JV_KIND_STRING, JV_KIND_ARRAY, JV_KIND_OBJECT};
-static const char* const colors[] =
+static char color_bufs[sizeof(color_kinds)/sizeof(color_kinds[0])][16];
+static const char *color_bufps[8];
+static const char* def_colors[] =
{COL("1;30"), COL("0;39"), COL("0;39"), COL("0;39"),
COL("0;32"), COL("1;39"), COL("1;39")};
#define FIELD_COLOR COL("34;1")
+static const char **colors = def_colors;
+
+int
+jq_set_colors(const char *c)
+{
+ const char *e;
+ size_t i;
+
+ if (c == NULL)
+ return 1;
+ colors = def_colors;
+ memset(color_bufs, 0, sizeof(color_bufs));
+ for (i = 0; i < sizeof(def_colors) / sizeof(def_colors[0]); i++)
+ color_bufps[i] = def_colors[i];
+ for (i = 0; i < sizeof(def_colors) / sizeof(def_colors[0]) && *c != '\0'; i++, c = e) {
+ if ((e = strchr(c, ':')) == NULL)
+ e = c + strlen(c);
+ if ((size_t)(e - c) > sizeof(color_bufs[i]) - 4 /* ESC [ m NUL */)
+ return 0;
+ color_bufs[i][0] = ESC[0];
+ color_bufs[i][1] = '[';
+ (void) strncpy(&color_bufs[i][2], c, e - c);
+ if (strspn(&color_bufs[i][2], "0123456789;") < strlen(&color_bufs[i][2]))
+ return 0;
+ color_bufs[i][2 + (e - c)] = 'm';
+ color_bufps[i] = color_bufs[i];
+ if (e[0] == ':')
+ e++;
+ }
+ colors = color_bufps;
+ return 1;
+}
+
static void put_buf(const char *s, int len, FILE *fout, jv *strout, int is_tty) {
if (strout) {
*strout = jv_string_append_buf(*strout, s, len);
diff --git a/src/main.c b/src/main.c
index 3cbf3152..a7f50b51 100644
--- a/src/main.c
+++ b/src/main.c
@@ -525,6 +525,9 @@ int main(int argc, char* argv[]) {
if (options & COLOR_OUTPUT) dumpopts |= JV_PRINT_COLOR;
if (options & NO_COLOR_OUTPUT) dumpopts &= ~JV_PRINT_COLOR;
+ if (getenv("JQ_COLORS") != NULL && !jq_set_colors(getenv("JQ_COLORS")))
+ fprintf(stderr, "Failed to set $JQ_COLORS\n");
+
if (jv_get_kind(lib_search_paths) == JV_KIND_NULL) {
// Default search path list
lib_search_paths = JV_ARRAY(jv_string("~/.jq"),
diff --git a/tests/shtest b/tests/shtest
index cec1fc59..af1b159e 100755
--- a/tests/shtest
+++ b/tests/shtest
@@ -244,4 +244,58 @@ if [ "`$VALGRIND $Q $JQ -n '"xyz\n"|halt_error(1)' 2>&1`" != xyz ]; then
exit 1
fi
+# Check $JQ_COLORS
+$JQ -Ccn . > $d/color
+printf '\033[1;30mnull\033[0m\n' > $d/expect
+cmp $d/color $d/expect
+JQ_COLORS='4;31' $JQ -Ccn . > $d/color
+printf '\033[4;31mnull\033[0m\n' > $d/expect
+cmp $d/color $d/expect
+JQ_COLORS='1;30:0;31:0;32:0;33:0;34:1;35:1;36' \
+ $JQ -Ccn '[{"a":true,"b":false},123,null]' > $d/color
+(
+printf '\033[1;35m[\033[1;36m{'
+printf '\033[0m\033[34;1m"a"\033['
+printf '0m\033[1;36m:\033[0m\033['
+printf '0;32mtrue\033[0m\033[1'
+printf ';36m,\033[0m\033[34;1m'
+printf '"b"\033[0m\033[1;36m:\033'
+printf '[0m\033[0;31mfalse\033'
+printf '[0m\033[1;36m\033[1;36'
+printf 'm}\033[0m\033[1;35m,\033['
+printf '0;33m123\033[0m\033[1;'
+printf '35m,\033[1;30mnull\033'
+printf '[0m\033[1;35m\033[1;35'
+printf 'm]\033[0m\n'
+) > $d/expect
+cmp $d/color $d/expect
+
+# Check garbage in JQ_COLORS. We write each color sequence into a 16
+# char buffer that needs to hold ESC [ <color> m NUL, so each color
+# sequence can be no more than 12 chars (bytes). These emit a warning
+# on stderr.
+set -vx
+echo 'Failed to set $JQ_COLORS' > $d/expect_warning
+$JQ -Ccn '[{"a":true,"b":false},123,null]' > $d/expect
+JQ_COLORS='garbage;30:*;31:,;3^:0;$%:0;34:1;35:1;36' \
+ $JQ -Ccn '[{"a":true,"b":false},123,null]' > $d/color 2>$d/warning
+cmp $d/color $d/expect
+cmp $d/warning $d/expect_warning
+JQ_COLORS='1234567890123456789;30:0;31:0;32:0;33:0;34:1;35:1;36' \
+ $JQ -Ccn '[{"a":true,"b":false},123,null]' > $d/color 2>$d/warning
+cmp $d/color $d/expect
+cmp $d/warning $d/expect_warning
+JQ_COLORS='1;31234567890123456789:0;31:0;32:0;33:0;34:1;35:1;36' \
+ $JQ -Ccn '[{"a":true,"b":false},123,null]' > $d/color 2>$d/warning
+cmp $d/color $d/expect
+cmp $d/warning $d/expect_warning
+JQ_COLORS='1234567890123456;1234567890123456:1234567890123456;1234567890123456:1234567890123456;1234567890123456:1234567890123456;1234567890123456:1234567890123456;1234567890123456:1234567890123456;1234567890123456:1234567890123456;1234567890123456' \
+ $JQ -Ccn '[{"a":true,"b":false},123,null]' > $d/color 2>$d/warning
+cmp $d/color $d/expect
+cmp $d/warning $d/expect_warning
+JQ_COLORS="0123456789123:0123456789123:0123456789123:0123456789123:0123456789123:0123456789123:0123456789123:0123456789123:" \
+ $JQ -Ccn '[{"a":true,"b":false},123,null]' > $d/color 2>$d/warning
+cmp $d/color $d/expect
+cmp $d/warning $d/expect_warning
+
exit 0