Dynamically allocate JQ_COLORS escapes for truecolor support (#3282)
This commit is contained in:
1 parent
c6e041699d
commit
aa977aa716
3 files changed
+76
-53
No files matched your search
+59
-32
@@ -27,43 +27,70 @@
|
||||
// Color table. See https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
|
||||
// for how to choose these. The order is same as jv_kind definition, and
|
||||
// the last color is used for object keys.
|
||||
static char color_bufs[8][16];
|
||||
static const char *color_bufps[8];
|
||||
static const char *const def_colors[] =
|
||||
{COL("0;90"), COL("0;39"), COL("0;39"), COL("0;39"),
|
||||
#define DEFAULT_COLORS \
|
||||
{COL("0;90"), COL("0;39"), COL("0;39"), COL("0;39"),\
|
||||
COL("0;32"), COL("1;39"), COL("1;39"), COL("1;34")};
|
||||
static const char *const default_colors[] = DEFAULT_COLORS;
|
||||
static const char *colors[] = DEFAULT_COLORS;
|
||||
#define COLORS_LEN (sizeof(colors) / sizeof(colors[0]))
|
||||
#define FIELD_COLOR (colors[7])
|
||||
|
||||
static const char *const *colors = def_colors;
|
||||
|
||||
int
|
||||
jq_set_colors(const char *c)
|
||||
{
|
||||
const char *e;
|
||||
size_t i;
|
||||
|
||||
if (c == NULL)
|
||||
static char *colors_buf = NULL;
|
||||
int jq_set_colors(const char *code_str) {
|
||||
if (code_str == 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++;
|
||||
|
||||
// the start of each color code in the env var, and the byte after the end of the last one
|
||||
const char *codes[COLORS_LEN + 1];
|
||||
size_t num_colors;
|
||||
// must be initialized before `goto default_colors`, used later to loop over every color
|
||||
size_t ci = 0;
|
||||
|
||||
for (num_colors = 0;; num_colors++) {
|
||||
codes[num_colors] = code_str;
|
||||
code_str += strspn(code_str, "0123456789;");
|
||||
if (code_str[0] == '\0' || num_colors + 1 >= COLORS_LEN) {
|
||||
break;
|
||||
} else if (code_str[0] != ':') {
|
||||
return 0; // invalid character
|
||||
}
|
||||
code_str++;
|
||||
}
|
||||
colors = color_bufps;
|
||||
if (codes[num_colors] != code_str) {
|
||||
// count the last color and store its end (plus one byte for consistency with starts)
|
||||
// an empty last color would be ignored (for cases like "" and "0:")
|
||||
num_colors++;
|
||||
codes[num_colors] = code_str + 1;
|
||||
} else if (num_colors == 0) {
|
||||
if (colors_buf != NULL) {
|
||||
jv_mem_free(colors_buf);
|
||||
colors_buf = NULL;
|
||||
}
|
||||
goto default_colors;
|
||||
}
|
||||
|
||||
colors_buf = jv_mem_realloc(
|
||||
colors_buf,
|
||||
// add ESC '[' 'm' to each string
|
||||
// '\0' is already included in difference of codes
|
||||
codes[num_colors] - codes[0] + 3 * num_colors
|
||||
);
|
||||
char *cb = colors_buf;
|
||||
for (; ci < num_colors; ci++) {
|
||||
colors[ci] = cb;
|
||||
size_t len = codes[ci + 1] - 1 - codes[ci];
|
||||
|
||||
cb[0] = ESC[0];
|
||||
cb[1] = '[';
|
||||
memcpy(cb + 2, codes[ci], len);
|
||||
cb[2 + len] = 'm';
|
||||
cb[3 + len] = '\0';
|
||||
|
||||
cb += len + 4;
|
||||
}
|
||||
default_colors:
|
||||
for (; ci < COLORS_LEN; ci++)
|
||||
colors[ci] = default_colors[ci];
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -554,7 +554,7 @@ 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")))
|
||||
if (!jq_set_colors(getenv("JQ_COLORS")))
|
||||
fprintf(stderr, "Failed to set $JQ_COLORS\n");
|
||||
|
||||
if (jv_get_kind(lib_search_paths) == JV_KIND_NULL) {
|
||||
|
||||
Reference in new issue
Block a user