|
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 |
| -#define DEF_COLORS \ |
| 30 | +#define DEFAULT_COLORS \ |
31 | 31 | {COL("0;90"), COL("0;39"), COL("0;39"), COL("0;39"),\
|
32 | 32 | COL("0;32"), COL("1;39"), COL("1;39"), COL("1;34")};
|
33 |
| -static const char *const def_colors[] = DEF_COLORS; |
34 |
| -static const char *colors[] = DEF_COLORS; |
| 33 | +static const char *const default_colors[] = DEFAULT_COLORS; |
| 34 | +static const char *colors[] = DEFAULT_COLORS; |
35 | 35 | #define COLORS_LEN (sizeof(colors) / sizeof(colors[0]))
|
36 | 36 | #define FIELD_COLOR (colors[7])
|
37 | 37 |
|
38 | 38 | static char *colors_buf = NULL;
|
39 |
| -int jq_set_colors(const char *c) { |
40 |
| - if (c == NULL) |
| 39 | +int jq_set_colors(const char *code_str) { |
| 40 | + if (code_str == NULL) |
41 | 41 | return 1;
|
42 |
| - const char *offsets[COLORS_LEN + 1]; // extra item for the end of the last string |
43 | 42 |
|
44 |
| - size_t cl = 0; |
45 |
| - size_t cn = 0; |
| 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 reset`, used later to loop over every color |
| 47 | + size_t ci = 0; |
46 | 48 |
|
47 |
| - while (cl < COLORS_LEN) { |
48 |
| - offsets[cl++] = c; |
49 |
| - // gcc won't optimize out strspn |
| 49 | + for (num_colors = 0; num_colors < COLORS_LEN; num_colors++) { |
| 50 | + codes[num_colors] = code_str; |
50 | 51 | letter:
|
51 |
| - switch (c++[0]) { |
| 52 | + switch (code_str[0]) { |
52 | 53 | // technically posix doesn't specify ascii so a range wouldn't be portable
|
53 | 54 | case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case ';':
|
54 |
| - goto letter; |
| 55 | + code_str++; |
| 56 | + goto letter; // loops until end of color code |
55 | 57 | case ':':
|
56 |
| - continue; |
| 58 | + code_str++; |
| 59 | + continue; // next color |
57 | 60 | case '\0':
|
58 |
| - goto var_end; |
| 61 | + goto set_codes_end; // done |
59 | 62 | default:
|
60 |
| - return 0; |
| 63 | + return 0; // invalid character |
61 | 64 | }
|
62 | 65 | }
|
63 |
| - var_end: |
64 |
| - // don't override last color on empty variable or trailing : |
65 |
| - if (offsets[--cl] != c - 1) { |
66 |
| - offsets[++cl] = c; |
67 |
| - } else if (cl == 0) { |
| 66 | + set_codes_end: |
| 67 | + if (codes[num_colors] != code_str) { |
| 68 | + // count the last color and store its end (plus one byte for consistency with starts) |
| 69 | + // an empty last color would be ignored (for cases like "" and "0:") |
| 70 | + num_colors++; |
| 71 | + codes[num_colors] = code_str + 1; |
| 72 | + } else if (num_colors == 0) { |
68 | 73 | if (colors_buf != NULL) {
|
69 | 74 | jv_mem_free(colors_buf);
|
70 | 75 | colors_buf = NULL;
|
71 | 76 | }
|
72 |
| - goto reset; |
| 77 | + goto default_colors; |
73 | 78 | }
|
74 | 79 |
|
75 | 80 | colors_buf = jv_mem_realloc(
|
76 | 81 | colors_buf,
|
77 | 82 | // add ESC '[' 'm' to each string
|
78 |
| - // '\0' is already included in difference of offsets |
79 |
| - offsets[cl] - offsets[0] + 3 * cl |
| 83 | + // '\0' is already included in difference of codes |
| 84 | + codes[num_colors] - codes[0] + 3 * num_colors |
80 | 85 | );
|
81 | 86 | char *cb = colors_buf;
|
82 |
| - for (; cn < cl; cn++) { |
83 |
| - colors[cn] = cb; |
| 87 | + for (; ci < num_colors; ci++) { |
| 88 | + colors[ci] = cb; |
| 89 | + size_t len = codes[ci + 1] - 1 - codes[ci]; |
| 90 | + |
84 | 91 | cb[0] = ESC[0];
|
85 | 92 | cb[1] = '[';
|
86 |
| - size_t len = offsets[cn + 1] - 1 - offsets[cn]; |
87 |
| - memcpy(cb + 2, offsets[cn], len); |
88 |
| - cb[len + 2] = 'm'; |
89 |
| - cb[len + 3] = '\0'; |
| 93 | + memcpy(cb + 2, codes[ci], len); |
| 94 | + cb[2 + len] = 'm'; |
| 95 | + cb[3 + len] = '\0'; |
| 96 | + |
90 | 97 | cb += len + 4;
|
91 | 98 | }
|
92 |
| - reset: |
93 |
| - for (; cn < COLORS_LEN; cn++) |
94 |
| - colors[cn] = def_colors[cn]; |
| 99 | + default_colors: |
| 100 | + for (; ci < COLORS_LEN; ci++) |
| 101 | + colors[ci] = default_colors[ci]; |
95 | 102 | return 1;
|
96 | 103 | }
|
97 | 104 |
|
|
0 commit comments