]> git.ipfire.org Git - thirdparty/git.git/blame - color.c
refs: print error message in debug output
[thirdparty/git.git] / color.c
CommitLineData
7c92fe0e 1#include "cache.h"
b2141fc1 2#include "config.h"
85023577 3#include "color.h"
7c92fe0e 4
4c7f1819 5static int git_use_color_default = GIT_COLOR_AUTO;
e269eb79 6int color_stdout_is_tty = -1;
6b2f2d98 7
7cd52b5b
DM
8/*
9 * The list of available column colors.
10 */
11const char *column_colors_ansi[] = {
12 GIT_COLOR_RED,
13 GIT_COLOR_GREEN,
14 GIT_COLOR_YELLOW,
15 GIT_COLOR_BLUE,
16 GIT_COLOR_MAGENTA,
17 GIT_COLOR_CYAN,
18 GIT_COLOR_BOLD_RED,
19 GIT_COLOR_BOLD_GREEN,
20 GIT_COLOR_BOLD_YELLOW,
21 GIT_COLOR_BOLD_BLUE,
22 GIT_COLOR_BOLD_MAGENTA,
23 GIT_COLOR_BOLD_CYAN,
24 GIT_COLOR_RESET,
25};
26
4a28eb0a
ES
27enum {
28 COLOR_BACKGROUND_OFFSET = 10,
29 COLOR_FOREGROUND_ANSI = 30,
30 COLOR_FOREGROUND_RGB = 38,
31 COLOR_FOREGROUND_256 = 38,
1751b09a 32 COLOR_FOREGROUND_BRIGHT_ANSI = 90,
4a28eb0a
ES
33};
34
7cd52b5b
DM
35/* Ignore the RESET at the end when giving the size */
36const int column_colors_ansi_max = ARRAY_SIZE(column_colors_ansi) - 1;
37
695d95df
JK
38/* An individual foreground or background color. */
39struct color {
40 enum {
41 COLOR_UNSPECIFIED = 0,
42 COLOR_NORMAL,
05f1f41c 43 COLOR_ANSI, /* basic 0-7 ANSI colors + "default" (value = 9) */
17a4be26
JK
44 COLOR_256,
45 COLOR_RGB
695d95df
JK
46 } type;
47 /* The numeric value for ANSI and 256-color modes */
48 unsigned char value;
17a4be26
JK
49 /* 24-bit RGB color values */
50 unsigned char red, green, blue;
695d95df
JK
51};
52
53/*
54 * "word" is a buffer of length "len"; does it match the NUL-terminated
55 * "match" exactly?
56 */
57static int match_word(const char *word, int len, const char *match)
7c92fe0e 58{
695d95df
JK
59 return !strncasecmp(word, match, len) && !match[len];
60}
61
17a4be26
JK
62static int get_hex_color(const char *in, unsigned char *out)
63{
64 unsigned int val;
65 val = (hexval(in[0]) << 4) | hexval(in[1]);
66 if (val & ~0xff)
67 return -1;
68 *out = val;
69 return 0;
70}
71
1751b09a
ES
72/*
73 * If an ANSI color is recognized in "name", fill "out" and return 0.
74 * Otherwise, leave out unchanged and return -1.
75 */
76static int parse_ansi_color(struct color *out, const char *name, int len)
695d95df
JK
77{
78 /* Positions in array must match ANSI color codes */
7c92fe0e 79 static const char * const color_names[] = {
695d95df 80 "black", "red", "green", "yellow",
7c92fe0e
JK
81 "blue", "magenta", "cyan", "white"
82 };
7c92fe0e 83 int i;
1751b09a
ES
84 int color_offset = COLOR_FOREGROUND_ANSI;
85
05f1f41c
RE
86 if (match_word(name, len, "default")) {
87 /*
88 * Restores to the terminal's default color, which may not be
89 * the same as explicitly setting "white" or "black".
90 *
91 * ECMA-48 - Control Functions \
92 * for Coded Character Sets, 5th edition (June 1991):
93 * > 39 default display colour (implementation-defined)
94 * > 49 default background colour (implementation-defined)
95 *
96 * Although not supported /everywhere/--according to terminfo,
97 * some terminals define "op" (original pair) as a blunt
98 * "set to white on black", or even "send full SGR reset"--
99 * it's standard and well-supported enough that if a user
100 * asks for it in their config this will do the right thing.
101 */
102 out->type = COLOR_ANSI;
103 out->value = 9 + color_offset;
104 return 0;
105 }
106
1751b09a
ES
107 if (strncasecmp(name, "bright", 6) == 0) {
108 color_offset = COLOR_FOREGROUND_BRIGHT_ANSI;
109 name += 6;
110 len -= 6;
111 }
112 for (i = 0; i < ARRAY_SIZE(color_names); i++) {
113 if (match_word(name, len, color_names[i])) {
114 out->type = COLOR_ANSI;
115 out->value = i + color_offset;
116 return 0;
117 }
118 }
119 return -1;
120}
121
122static int parse_color(struct color *out, const char *name, int len)
123{
124 char *end;
695d95df
JK
125 long val;
126
127 /* First try the special word "normal"... */
128 if (match_word(name, len, "normal")) {
129 out->type = COLOR_NORMAL;
130 return 0;
131 }
132
17a4be26
JK
133 /* Try a 24-bit RGB value */
134 if (len == 7 && name[0] == '#') {
135 if (!get_hex_color(name + 1, &out->red) &&
136 !get_hex_color(name + 3, &out->green) &&
137 !get_hex_color(name + 5, &out->blue)) {
138 out->type = COLOR_RGB;
139 return 0;
140 }
141 }
142
695d95df 143 /* Then pick from our human-readable color names... */
1751b09a
ES
144 if (parse_ansi_color(out, name, len) == 0) {
145 return 0;
7c92fe0e 146 }
695d95df
JK
147
148 /* And finally try a literal 256-color-mode number */
149 val = strtol(name, &end, 10);
150 if (end - name == len) {
151 /*
152 * Allow "-1" as an alias for "normal", but other negative
153 * numbers are bogus.
154 */
155 if (val < -1)
156 ; /* fall through to error */
157 else if (val < 0) {
158 out->type = COLOR_NORMAL;
159 return 0;
c444f032 160 /* Rewrite 0-7 as more-portable standard colors. */
695d95df
JK
161 } else if (val < 8) {
162 out->type = COLOR_ANSI;
4a28eb0a 163 out->value = val + COLOR_FOREGROUND_ANSI;
3759d27a 164 return 0;
c444f032
ES
165 /* Rewrite 8-15 as more-portable aixterm colors. */
166 } else if (val < 16) {
167 out->type = COLOR_ANSI;
168 out->value = val - 8 + COLOR_FOREGROUND_BRIGHT_ANSI;
169 return 0;
695d95df
JK
170 } else if (val < 256) {
171 out->type = COLOR_256;
172 out->value = val;
173 return 0;
174 }
175 }
176
177 return -1;
7c92fe0e
JK
178}
179
df8e472c 180static int parse_attr(const char *name, size_t len)
7c92fe0e 181{
df8e472c
JK
182 static const struct {
183 const char *name;
184 size_t len;
185 int val, neg;
186 } attrs[] = {
187#define ATTR(x, val, neg) { (x), sizeof(x)-1, (val), (neg) }
188 ATTR("bold", 1, 22),
189 ATTR("dim", 2, 22),
54590a0e 190 ATTR("italic", 3, 23),
df8e472c
JK
191 ATTR("ul", 4, 24),
192 ATTR("blink", 5, 25),
9dc3515c
JK
193 ATTR("reverse", 7, 27),
194 ATTR("strike", 9, 29)
df8e472c 195#undef ATTR
7c92fe0e 196 };
df8e472c 197 int negate = 0;
7c92fe0e 198 int i;
df8e472c 199
5621068f
JK
200 if (skip_prefix_mem(name, len, "no", &name, &len)) {
201 skip_prefix_mem(name, len, "-", &name, &len);
df8e472c 202 negate = 1;
5621068f 203 }
df8e472c
JK
204
205 for (i = 0; i < ARRAY_SIZE(attrs); i++) {
206 if (attrs[i].len == len && !memcmp(attrs[i].name, name, len))
207 return negate ? attrs[i].neg : attrs[i].val;
7c92fe0e
JK
208 }
209 return -1;
210}
211
f6c5a296 212int color_parse(const char *value, char *dst)
2c2dc7c8 213{
f6c5a296 214 return color_parse_mem(value, strlen(value), dst);
2c2dc7c8
RS
215}
216
695d95df
JK
217/*
218 * Write the ANSI color codes for "c" to "out"; the string should
219 * already have the ANSI escape code in it. "out" should have enough
220 * space in it to fit any color.
221 */
4a28eb0a 222static char *color_output(char *out, int len, const struct color *c, int background)
695d95df 223{
4a28eb0a
ES
224 int offset = 0;
225
226 if (background)
227 offset = COLOR_BACKGROUND_OFFSET;
695d95df
JK
228 switch (c->type) {
229 case COLOR_UNSPECIFIED:
230 case COLOR_NORMAL:
231 break;
232 case COLOR_ANSI:
4a28eb0a 233 out += xsnprintf(out, len, "%d", c->value + offset);
695d95df
JK
234 break;
235 case COLOR_256:
4a28eb0a
ES
236 out += xsnprintf(out, len, "%d;5;%d", COLOR_FOREGROUND_256 + offset,
237 c->value);
695d95df 238 break;
17a4be26 239 case COLOR_RGB:
4a28eb0a
ES
240 out += xsnprintf(out, len, "%d;2;%d;%d;%d",
241 COLOR_FOREGROUND_RGB + offset,
cbc8feea 242 c->red, c->green, c->blue);
17a4be26 243 break;
695d95df
JK
244 }
245 return out;
246}
247
248static int color_empty(const struct color *c)
249{
250 return c->type <= COLOR_NORMAL;
251}
252
f6c5a296 253int color_parse_mem(const char *value, int value_len, char *dst)
7c92fe0e
JK
254{
255 const char *ptr = value;
2c2dc7c8 256 int len = value_len;
cbc8feea 257 char *end = dst + COLOR_MAXLEN;
de658515 258 unsigned int has_reset = 0;
8b124135 259 unsigned int attr = 0;
695d95df
JK
260 struct color fg = { COLOR_UNSPECIFIED };
261 struct color bg = { COLOR_UNSPECIFIED };
7c92fe0e 262
bc407565
NTND
263 while (len > 0 && isspace(*ptr)) {
264 ptr++;
265 len--;
266 }
267
55cccf4b
JK
268 if (!len) {
269 dst[0] = '\0';
270 return 0;
271 }
c2f41bf5 272
de658515 273 /* [reset] [fg [bg]] [attr]... */
2c2dc7c8 274 while (len > 0) {
7c92fe0e 275 const char *word = ptr;
3e1952ed 276 struct color c = { COLOR_UNSPECIFIED };
2c2dc7c8 277 int val, wordlen = 0;
7c92fe0e 278
2c2dc7c8
RS
279 while (len > 0 && !isspace(word[wordlen])) {
280 wordlen++;
281 len--;
282 }
7c92fe0e 283
2c2dc7c8
RS
284 ptr = word + wordlen;
285 while (len > 0 && isspace(*ptr)) {
7c92fe0e 286 ptr++;
2c2dc7c8
RS
287 len--;
288 }
7c92fe0e 289
de658515
RE
290 if (match_word(word, wordlen, "reset")) {
291 has_reset = 1;
292 continue;
293 }
294
695d95df
JK
295 if (!parse_color(&c, word, wordlen)) {
296 if (fg.type == COLOR_UNSPECIFIED) {
297 fg = c;
7c92fe0e
JK
298 continue;
299 }
695d95df
JK
300 if (bg.type == COLOR_UNSPECIFIED) {
301 bg = c;
7c92fe0e
JK
302 continue;
303 }
304 goto bad;
305 }
2c2dc7c8 306 val = parse_attr(word, wordlen);
8b124135
JH
307 if (0 <= val)
308 attr |= (1 << val);
309 else
7c92fe0e 310 goto bad;
7c92fe0e
JK
311 }
312
cbc8feea
JK
313#undef OUT
314#define OUT(x) do { \
315 if (dst == end) \
033abf97 316 BUG("color parsing ran out of space"); \
cbc8feea
JK
317 *dst++ = (x); \
318} while(0)
319
de658515 320 if (has_reset || attr || !color_empty(&fg) || !color_empty(&bg)) {
7c92fe0e 321 int sep = 0;
8b124135 322 int i;
7c92fe0e 323
cbc8feea
JK
324 OUT('\033');
325 OUT('[');
8b124135 326
de658515
RE
327 if (has_reset)
328 sep++;
329
8b124135
JH
330 for (i = 0; attr; i++) {
331 unsigned bit = (1 << i);
332 if (!(attr & bit))
333 continue;
334 attr &= ~bit;
335 if (sep++)
cbc8feea
JK
336 OUT(';');
337 dst += xsnprintf(dst, end - dst, "%d", i);
7c92fe0e 338 }
695d95df 339 if (!color_empty(&fg)) {
7c92fe0e 340 if (sep++)
cbc8feea 341 OUT(';');
4a28eb0a 342 dst = color_output(dst, end - dst, &fg, 0);
7c92fe0e 343 }
695d95df 344 if (!color_empty(&bg)) {
7c92fe0e 345 if (sep++)
cbc8feea 346 OUT(';');
4a28eb0a 347 dst = color_output(dst, end - dst, &bg, 1);
7c92fe0e 348 }
cbc8feea 349 OUT('m');
7c92fe0e 350 }
cbc8feea 351 OUT(0);
f6c5a296 352 return 0;
7c92fe0e 353bad:
f6c5a296 354 return error(_("invalid color value: %.*s"), value_len, value);
cbc8feea 355#undef OUT
7c92fe0e
JK
356}
357
e269eb79 358int git_config_colorbool(const char *var, const char *value)
7c92fe0e 359{
57f2b842
JH
360 if (value) {
361 if (!strcasecmp(value, "never"))
362 return 0;
363 if (!strcasecmp(value, "always"))
2c1acdf6 364 return 1;
57f2b842 365 if (!strcasecmp(value, "auto"))
daa0c3d9 366 return GIT_COLOR_AUTO;
7c92fe0e 367 }
57f2b842 368
73e9da01
ML
369 if (!var)
370 return -1;
371
57f2b842
JH
372 /* Missing or explicit false to turn off colorization */
373 if (!git_config_bool(var, value))
7c92fe0e 374 return 0;
57f2b842
JH
375
376 /* any normal truth value defaults to 'auto' */
daa0c3d9
JK
377 return GIT_COLOR_AUTO;
378}
379
295d949c 380static int check_auto_color(int fd)
daa0c3d9 381{
295d949c
JS
382 static int color_stderr_is_tty = -1;
383 int *is_tty_p = fd == 1 ? &color_stdout_is_tty : &color_stderr_is_tty;
384 if (*is_tty_p < 0)
385 *is_tty_p = isatty(fd);
386 if (*is_tty_p || (fd == 1 && pager_in_use() && pager_use_color)) {
a64f213d 387 if (!is_terminal_dumb())
57f2b842
JH
388 return 1;
389 }
390 return 0;
7c92fe0e
JK
391}
392
295d949c 393int want_color_fd(int fd, int var)
daa0c3d9 394{
6cdf8a79
395 /*
396 * NEEDSWORK: This function is sometimes used from multiple threads, and
397 * we end up using want_auto racily. That "should not matter" since
398 * we always write the same value, but it's still wrong. This function
399 * is listed in .tsan-suppressions for the time being.
400 */
401
295d949c 402 static int want_auto[3] = { -1, -1, -1 };
daa0c3d9 403
65bb21e7
ES
404 if (fd < 1 || fd >= ARRAY_SIZE(want_auto))
405 BUG("file descriptor out of range: %d", fd);
406
c9bfb953
JK
407 if (var < 0)
408 var = git_use_color_default;
409
daa0c3d9 410 if (var == GIT_COLOR_AUTO) {
295d949c
JS
411 if (want_auto[fd] < 0)
412 want_auto[fd] = check_auto_color(fd);
413 return want_auto[fd];
daa0c3d9 414 }
c9bfb953 415 return var;
daa0c3d9
JK
416}
417
3e1dd17a 418int git_color_config(const char *var, const char *value, void *cb)
6b2f2d98
MK
419{
420 if (!strcmp(var, "color.ui")) {
e269eb79 421 git_use_color_default = git_config_colorbool(var, value);
6b2f2d98
MK
422 return 0;
423 }
424
3e1dd17a
JK
425 return 0;
426}
427
33c643bb
JK
428int git_color_default_config(const char *var, const char *value, void *cb)
429{
430 if (git_color_config(var, value, cb) < 0)
431 return -1;
432
433 return git_default_config(var, value, cb);
434}
435
becbdae8
JN
436void color_print_strbuf(FILE *fp, const char *color, const struct strbuf *sb)
437{
438 if (*color)
439 fprintf(fp, "%s", color);
440 fprintf(fp, "%s", sb->buf);
441 if (*color)
442 fprintf(fp, "%s", GIT_COLOR_RESET);
443}
444
f26a0012 445static int color_vfprintf(FILE *fp, const char *color, const char *fmt,
7c92fe0e
JK
446 va_list args, const char *trail)
447{
448 int r = 0;
449
450 if (*color)
f26a0012
KH
451 r += fprintf(fp, "%s", color);
452 r += vfprintf(fp, fmt, args);
7c92fe0e 453 if (*color)
dc6ebd4c 454 r += fprintf(fp, "%s", GIT_COLOR_RESET);
7c92fe0e 455 if (trail)
f26a0012 456 r += fprintf(fp, "%s", trail);
7c92fe0e
JK
457 return r;
458}
459
f26a0012 460int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
7c92fe0e
JK
461{
462 va_list args;
463 int r;
464 va_start(args, fmt);
f26a0012 465 r = color_vfprintf(fp, color, fmt, args, NULL);
7c92fe0e
JK
466 va_end(args);
467 return r;
468}
469
f26a0012 470int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...)
7c92fe0e
JK
471{
472 va_list args;
473 int r;
474 va_start(args, fmt);
f26a0012 475 r = color_vfprintf(fp, color, fmt, args, "\n");
7c92fe0e
JK
476 va_end(args);
477 return r;
478}
148135fc
JK
479
480int color_is_nil(const char *c)
481{
482 return !strcmp(c, "NIL");
483}