|
27 | 27 | // Color table. See https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
|
28 | 28 | // for how to choose these. The order is same as jv_kind definition, and
|
29 | 29 | // the last color is used for object keys.
|
30 |
| -static char color_bufs[8][16]; |
31 |
| -static const char *color_bufps[8]; |
32 |
| -static const char *const def_colors[] = |
33 |
| - {COL("0;90"), COL("0;39"), COL("0;39"), COL("0;39"), |
| 30 | +#define DEFAULT_COLORS \ |
| 31 | + {COL("0;90"), COL("0;39"), COL("0;39"), COL("0;39"),\ |
34 | 32 | COL("0;32"), COL("1;39"), COL("1;39"), COL("1;34")};
|
| 33 | +static const char *const default_colors[] = DEFAULT_COLORS; |
| 34 | +static const char *colors[] = DEFAULT_COLORS; |
| 35 | +#define COLORS_LEN (sizeof(colors) / sizeof(colors[0])) |
35 | 36 | #define FIELD_COLOR (colors[7])
|
36 | 37 |
|
37 |
| -static const char *const *colors = def_colors; |
| 38 | +static char *colors_buf = NULL; |
| 39 | +int jq_set_colors(const char *code_str) { |
| 40 | + if (code_str == NULL) |
| 41 | + return 1; |
38 | 42 |
|
39 |
| -int |
40 |
| -jq_set_colors(const char *c) |
41 |
| -{ |
42 |
| - const char *e; |
43 |
| - size_t i; |
| 43 | + // the start of each color code in the env var, and the byte after the end of the last one |
| 44 | + const char *codes[COLORS_LEN + 1]; |
| 45 | + size_t num_colors; |
| 46 | + // must be initialized before `goto default_colors`, used later to loop over every color |
| 47 | + size_t ci = 0; |
44 | 48 |
|
45 |
| - if (c == NULL) |
46 |
| - return 1; |
47 |
| - colors = def_colors; |
48 |
| - memset(color_bufs, 0, sizeof(color_bufs)); |
49 |
| - for (i = 0; i < sizeof(def_colors) / sizeof(def_colors[0]); i++) |
50 |
| - color_bufps[i] = def_colors[i]; |
51 |
| - for (i = 0; i < sizeof(def_colors) / sizeof(def_colors[0]) && *c != '\0'; i++, c = e) { |
52 |
| - if ((e = strchr(c, ':')) == NULL) |
53 |
| - e = c + strlen(c); |
54 |
| - if ((size_t)(e - c) > sizeof(color_bufs[i]) - 4 /* ESC [ m NUL */) |
55 |
| - return 0; |
56 |
| - color_bufs[i][0] = ESC[0]; |
57 |
| - color_bufs[i][1] = '['; |
58 |
| - (void) strncpy(&color_bufs[i][2], c, e - c); |
59 |
| - if (strspn(&color_bufs[i][2], "0123456789;") < strlen(&color_bufs[i][2])) |
60 |
| - return 0; |
61 |
| - color_bufs[i][2 + (e - c)] = 'm'; |
62 |
| - color_bufps[i] = color_bufs[i]; |
63 |
| - if (e[0] == ':') |
64 |
| - e++; |
| 49 | + for (num_colors = 0;; num_colors++) { |
| 50 | + codes[num_colors] = code_str; |
| 51 | + code_str += strspn(code_str, "0123456789;"); |
| 52 | + if (code_str[0] == '\0' || num_colors + 1 >= COLORS_LEN) { |
| 53 | + break; |
| 54 | + } else if (code_str[0] != ':') { |
| 55 | + return 0; // invalid character |
| 56 | + } |
| 57 | + code_str++; |
| 58 | + } |
| 59 | + if (codes[num_colors] != code_str) { |
| 60 | + // count the last color and store its end (plus one byte for consistency with starts) |
| 61 | + // an empty last color would be ignored (for cases like "" and "0:") |
| 62 | + num_colors++; |
| 63 | + codes[num_colors] = code_str + 1; |
| 64 | + } else if (num_colors == 0) { |
| 65 | + if (colors_buf != NULL) { |
| 66 | + jv_mem_free(colors_buf); |
| 67 | + colors_buf = NULL; |
| 68 | + } |
| 69 | + goto default_colors; |
| 70 | + } |
| 71 | + |
| 72 | + colors_buf = jv_mem_realloc( |
| 73 | + colors_buf, |
| 74 | + // add ESC '[' 'm' to each string |
| 75 | + // '\0' is already included in difference of codes |
| 76 | + codes[num_colors] - codes[0] + 3 * num_colors |
| 77 | + ); |
| 78 | + char *cb = colors_buf; |
| 79 | + for (; ci < num_colors; ci++) { |
| 80 | + colors[ci] = cb; |
| 81 | + size_t len = codes[ci + 1] - 1 - codes[ci]; |
| 82 | + |
| 83 | + cb[0] = ESC[0]; |
| 84 | + cb[1] = '['; |
| 85 | + memcpy(cb + 2, codes[ci], len); |
| 86 | + cb[2 + len] = 'm'; |
| 87 | + cb[3 + len] = '\0'; |
| 88 | + |
| 89 | + cb += len + 4; |
65 | 90 | }
|
66 |
| - colors = color_bufps; |
| 91 | + default_colors: |
| 92 | + for (; ci < COLORS_LEN; ci++) |
| 93 | + colors[ci] = default_colors[ci]; |
67 | 94 | return 1;
|
68 | 95 | }
|
69 | 96 |
|
|
0 commit comments