]> git.ipfire.org Git - thirdparty/git.git/blame - color.c
Git 2.17.3
[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
27/* Ignore the RESET at the end when giving the size */
28const int column_colors_ansi_max = ARRAY_SIZE(column_colors_ansi) - 1;
29
695d95df
JK
30/* An individual foreground or background color. */
31struct color {
32 enum {
33 COLOR_UNSPECIFIED = 0,
34 COLOR_NORMAL,
35 COLOR_ANSI, /* basic 0-7 ANSI colors */
17a4be26
JK
36 COLOR_256,
37 COLOR_RGB
695d95df
JK
38 } type;
39 /* The numeric value for ANSI and 256-color modes */
40 unsigned char value;
17a4be26
JK
41 /* 24-bit RGB color values */
42 unsigned char red, green, blue;
695d95df
JK
43};
44
45/*
46 * "word" is a buffer of length "len"; does it match the NUL-terminated
47 * "match" exactly?
48 */
49static int match_word(const char *word, int len, const char *match)
7c92fe0e 50{
695d95df
JK
51 return !strncasecmp(word, match, len) && !match[len];
52}
53
17a4be26
JK
54static int get_hex_color(const char *in, unsigned char *out)
55{
56 unsigned int val;
57 val = (hexval(in[0]) << 4) | hexval(in[1]);
58 if (val & ~0xff)
59 return -1;
60 *out = val;
61 return 0;
62}
63
695d95df
JK
64static int parse_color(struct color *out, const char *name, int len)
65{
66 /* Positions in array must match ANSI color codes */
7c92fe0e 67 static const char * const color_names[] = {
695d95df 68 "black", "red", "green", "yellow",
7c92fe0e
JK
69 "blue", "magenta", "cyan", "white"
70 };
71 char *end;
72 int i;
695d95df
JK
73 long val;
74
75 /* First try the special word "normal"... */
76 if (match_word(name, len, "normal")) {
77 out->type = COLOR_NORMAL;
78 return 0;
79 }
80
17a4be26
JK
81 /* Try a 24-bit RGB value */
82 if (len == 7 && name[0] == '#') {
83 if (!get_hex_color(name + 1, &out->red) &&
84 !get_hex_color(name + 3, &out->green) &&
85 !get_hex_color(name + 5, &out->blue)) {
86 out->type = COLOR_RGB;
87 return 0;
88 }
89 }
90
695d95df 91 /* Then pick from our human-readable color names... */
7c92fe0e 92 for (i = 0; i < ARRAY_SIZE(color_names); i++) {
695d95df
JK
93 if (match_word(name, len, color_names[i])) {
94 out->type = COLOR_ANSI;
95 out->value = i;
96 return 0;
97 }
7c92fe0e 98 }
695d95df
JK
99
100 /* And finally try a literal 256-color-mode number */
101 val = strtol(name, &end, 10);
102 if (end - name == len) {
103 /*
104 * Allow "-1" as an alias for "normal", but other negative
105 * numbers are bogus.
106 */
107 if (val < -1)
108 ; /* fall through to error */
109 else if (val < 0) {
110 out->type = COLOR_NORMAL;
111 return 0;
112 /* Rewrite low numbers as more-portable standard colors. */
113 } else if (val < 8) {
114 out->type = COLOR_ANSI;
115 out->value = val;
3759d27a 116 return 0;
695d95df
JK
117 } else if (val < 256) {
118 out->type = COLOR_256;
119 out->value = val;
120 return 0;
121 }
122 }
123
124 return -1;
7c92fe0e
JK
125}
126
df8e472c 127static int parse_attr(const char *name, size_t len)
7c92fe0e 128{
df8e472c
JK
129 static const struct {
130 const char *name;
131 size_t len;
132 int val, neg;
133 } attrs[] = {
134#define ATTR(x, val, neg) { (x), sizeof(x)-1, (val), (neg) }
135 ATTR("bold", 1, 22),
136 ATTR("dim", 2, 22),
54590a0e 137 ATTR("italic", 3, 23),
df8e472c
JK
138 ATTR("ul", 4, 24),
139 ATTR("blink", 5, 25),
9dc3515c
JK
140 ATTR("reverse", 7, 27),
141 ATTR("strike", 9, 29)
df8e472c 142#undef ATTR
7c92fe0e 143 };
df8e472c 144 int negate = 0;
7c92fe0e 145 int i;
df8e472c 146
5621068f
JK
147 if (skip_prefix_mem(name, len, "no", &name, &len)) {
148 skip_prefix_mem(name, len, "-", &name, &len);
df8e472c 149 negate = 1;
5621068f 150 }
df8e472c
JK
151
152 for (i = 0; i < ARRAY_SIZE(attrs); i++) {
153 if (attrs[i].len == len && !memcmp(attrs[i].name, name, len))
154 return negate ? attrs[i].neg : attrs[i].val;
7c92fe0e
JK
155 }
156 return -1;
157}
158
f6c5a296 159int color_parse(const char *value, char *dst)
2c2dc7c8 160{
f6c5a296 161 return color_parse_mem(value, strlen(value), dst);
2c2dc7c8
RS
162}
163
695d95df
JK
164/*
165 * Write the ANSI color codes for "c" to "out"; the string should
166 * already have the ANSI escape code in it. "out" should have enough
167 * space in it to fit any color.
168 */
cbc8feea 169static char *color_output(char *out, int len, const struct color *c, char type)
695d95df
JK
170{
171 switch (c->type) {
172 case COLOR_UNSPECIFIED:
173 case COLOR_NORMAL:
174 break;
175 case COLOR_ANSI:
cbc8feea
JK
176 if (len < 2)
177 die("BUG: color parsing ran out of space");
695d95df
JK
178 *out++ = type;
179 *out++ = '0' + c->value;
180 break;
181 case COLOR_256:
cbc8feea 182 out += xsnprintf(out, len, "%c8;5;%d", type, c->value);
695d95df 183 break;
17a4be26 184 case COLOR_RGB:
cbc8feea
JK
185 out += xsnprintf(out, len, "%c8;2;%d;%d;%d", type,
186 c->red, c->green, c->blue);
17a4be26 187 break;
695d95df
JK
188 }
189 return out;
190}
191
192static int color_empty(const struct color *c)
193{
194 return c->type <= COLOR_NORMAL;
195}
196
f6c5a296 197int color_parse_mem(const char *value, int value_len, char *dst)
7c92fe0e
JK
198{
199 const char *ptr = value;
2c2dc7c8 200 int len = value_len;
cbc8feea 201 char *end = dst + COLOR_MAXLEN;
8b124135 202 unsigned int attr = 0;
695d95df
JK
203 struct color fg = { COLOR_UNSPECIFIED };
204 struct color bg = { COLOR_UNSPECIFIED };
7c92fe0e 205
bc407565
NTND
206 while (len > 0 && isspace(*ptr)) {
207 ptr++;
208 len--;
209 }
210
55cccf4b
JK
211 if (!len) {
212 dst[0] = '\0';
213 return 0;
214 }
c2f41bf5 215
bc407565 216 if (!strncasecmp(ptr, "reset", len)) {
cbc8feea 217 xsnprintf(dst, end - dst, GIT_COLOR_RESET);
f6c5a296 218 return 0;
7c92fe0e
JK
219 }
220
8b124135 221 /* [fg [bg]] [attr]... */
2c2dc7c8 222 while (len > 0) {
7c92fe0e 223 const char *word = ptr;
3e1952ed 224 struct color c = { COLOR_UNSPECIFIED };
2c2dc7c8 225 int val, wordlen = 0;
7c92fe0e 226
2c2dc7c8
RS
227 while (len > 0 && !isspace(word[wordlen])) {
228 wordlen++;
229 len--;
230 }
7c92fe0e 231
2c2dc7c8
RS
232 ptr = word + wordlen;
233 while (len > 0 && isspace(*ptr)) {
7c92fe0e 234 ptr++;
2c2dc7c8
RS
235 len--;
236 }
7c92fe0e 237
695d95df
JK
238 if (!parse_color(&c, word, wordlen)) {
239 if (fg.type == COLOR_UNSPECIFIED) {
240 fg = c;
7c92fe0e
JK
241 continue;
242 }
695d95df
JK
243 if (bg.type == COLOR_UNSPECIFIED) {
244 bg = c;
7c92fe0e
JK
245 continue;
246 }
247 goto bad;
248 }
2c2dc7c8 249 val = parse_attr(word, wordlen);
8b124135
JH
250 if (0 <= val)
251 attr |= (1 << val);
252 else
7c92fe0e 253 goto bad;
7c92fe0e
JK
254 }
255
cbc8feea
JK
256#undef OUT
257#define OUT(x) do { \
258 if (dst == end) \
259 die("BUG: color parsing ran out of space"); \
260 *dst++ = (x); \
261} while(0)
262
695d95df 263 if (attr || !color_empty(&fg) || !color_empty(&bg)) {
7c92fe0e 264 int sep = 0;
8b124135 265 int i;
7c92fe0e 266
cbc8feea
JK
267 OUT('\033');
268 OUT('[');
8b124135
JH
269
270 for (i = 0; attr; i++) {
271 unsigned bit = (1 << i);
272 if (!(attr & bit))
273 continue;
274 attr &= ~bit;
275 if (sep++)
cbc8feea
JK
276 OUT(';');
277 dst += xsnprintf(dst, end - dst, "%d", i);
7c92fe0e 278 }
695d95df 279 if (!color_empty(&fg)) {
7c92fe0e 280 if (sep++)
cbc8feea 281 OUT(';');
71b59849 282 /* foreground colors are all in the 3x range */
cbc8feea 283 dst = color_output(dst, end - dst, &fg, '3');
7c92fe0e 284 }
695d95df 285 if (!color_empty(&bg)) {
7c92fe0e 286 if (sep++)
cbc8feea 287 OUT(';');
71b59849 288 /* background colors are all in the 4x range */
cbc8feea 289 dst = color_output(dst, end - dst, &bg, '4');
7c92fe0e 290 }
cbc8feea 291 OUT('m');
7c92fe0e 292 }
cbc8feea 293 OUT(0);
f6c5a296 294 return 0;
7c92fe0e 295bad:
f6c5a296 296 return error(_("invalid color value: %.*s"), value_len, value);
cbc8feea 297#undef OUT
7c92fe0e
JK
298}
299
e269eb79 300int git_config_colorbool(const char *var, const char *value)
7c92fe0e 301{
57f2b842
JH
302 if (value) {
303 if (!strcasecmp(value, "never"))
304 return 0;
305 if (!strcasecmp(value, "always"))
2c1acdf6 306 return 1;
57f2b842 307 if (!strcasecmp(value, "auto"))
daa0c3d9 308 return GIT_COLOR_AUTO;
7c92fe0e 309 }
57f2b842 310
73e9da01
ML
311 if (!var)
312 return -1;
313
57f2b842
JH
314 /* Missing or explicit false to turn off colorization */
315 if (!git_config_bool(var, value))
7c92fe0e 316 return 0;
57f2b842
JH
317
318 /* any normal truth value defaults to 'auto' */
daa0c3d9
JK
319 return GIT_COLOR_AUTO;
320}
321
322static int check_auto_color(void)
323{
e269eb79
JK
324 if (color_stdout_is_tty < 0)
325 color_stdout_is_tty = isatty(1);
326 if (color_stdout_is_tty || (pager_in_use() && pager_use_color)) {
a64f213d 327 if (!is_terminal_dumb())
57f2b842
JH
328 return 1;
329 }
330 return 0;
7c92fe0e
JK
331}
332
daa0c3d9
JK
333int want_color(int var)
334{
6cdf8a79
335 /*
336 * NEEDSWORK: This function is sometimes used from multiple threads, and
337 * we end up using want_auto racily. That "should not matter" since
338 * we always write the same value, but it's still wrong. This function
339 * is listed in .tsan-suppressions for the time being.
340 */
341
daa0c3d9
JK
342 static int want_auto = -1;
343
c9bfb953
JK
344 if (var < 0)
345 var = git_use_color_default;
346
daa0c3d9
JK
347 if (var == GIT_COLOR_AUTO) {
348 if (want_auto < 0)
349 want_auto = check_auto_color();
350 return want_auto;
351 }
c9bfb953 352 return var;
daa0c3d9
JK
353}
354
3e1dd17a 355int git_color_config(const char *var, const char *value, void *cb)
6b2f2d98
MK
356{
357 if (!strcmp(var, "color.ui")) {
e269eb79 358 git_use_color_default = git_config_colorbool(var, value);
6b2f2d98
MK
359 return 0;
360 }
361
3e1dd17a
JK
362 return 0;
363}
364
33c643bb
JK
365int git_color_default_config(const char *var, const char *value, void *cb)
366{
367 if (git_color_config(var, value, cb) < 0)
368 return -1;
369
370 return git_default_config(var, value, cb);
371}
372
becbdae8
JN
373void color_print_strbuf(FILE *fp, const char *color, const struct strbuf *sb)
374{
375 if (*color)
376 fprintf(fp, "%s", color);
377 fprintf(fp, "%s", sb->buf);
378 if (*color)
379 fprintf(fp, "%s", GIT_COLOR_RESET);
380}
381
f26a0012 382static int color_vfprintf(FILE *fp, const char *color, const char *fmt,
7c92fe0e
JK
383 va_list args, const char *trail)
384{
385 int r = 0;
386
387 if (*color)
f26a0012
KH
388 r += fprintf(fp, "%s", color);
389 r += vfprintf(fp, fmt, args);
7c92fe0e 390 if (*color)
dc6ebd4c 391 r += fprintf(fp, "%s", GIT_COLOR_RESET);
7c92fe0e 392 if (trail)
f26a0012 393 r += fprintf(fp, "%s", trail);
7c92fe0e
JK
394 return r;
395}
396
f26a0012 397int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
7c92fe0e
JK
398{
399 va_list args;
400 int r;
401 va_start(args, fmt);
f26a0012 402 r = color_vfprintf(fp, color, fmt, args, NULL);
7c92fe0e
JK
403 va_end(args);
404 return r;
405}
406
f26a0012 407int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...)
7c92fe0e
JK
408{
409 va_list args;
410 int r;
411 va_start(args, fmt);
f26a0012 412 r = color_vfprintf(fp, color, fmt, args, "\n");
7c92fe0e
JK
413 va_end(args);
414 return r;
415}
148135fc
JK
416
417int color_is_nil(const char *c)
418{
419 return !strcmp(c, "NIL");
420}