]>
Commit | Line | Data |
---|---|---|
7c92fe0e | 1 | #include "cache.h" |
85023577 | 2 | #include "color.h" |
7c92fe0e | 3 | |
6b2f2d98 MK |
4 | int git_use_color_default = 0; |
5 | ||
7cd52b5b DM |
6 | /* |
7 | * The list of available column colors. | |
8 | */ | |
9 | const char *column_colors_ansi[] = { | |
10 | GIT_COLOR_RED, | |
11 | GIT_COLOR_GREEN, | |
12 | GIT_COLOR_YELLOW, | |
13 | GIT_COLOR_BLUE, | |
14 | GIT_COLOR_MAGENTA, | |
15 | GIT_COLOR_CYAN, | |
16 | GIT_COLOR_BOLD_RED, | |
17 | GIT_COLOR_BOLD_GREEN, | |
18 | GIT_COLOR_BOLD_YELLOW, | |
19 | GIT_COLOR_BOLD_BLUE, | |
20 | GIT_COLOR_BOLD_MAGENTA, | |
21 | GIT_COLOR_BOLD_CYAN, | |
22 | GIT_COLOR_RESET, | |
23 | }; | |
24 | ||
25 | /* Ignore the RESET at the end when giving the size */ | |
26 | const int column_colors_ansi_max = ARRAY_SIZE(column_colors_ansi) - 1; | |
27 | ||
7c92fe0e JK |
28 | static int parse_color(const char *name, int len) |
29 | { | |
30 | static const char * const color_names[] = { | |
31 | "normal", "black", "red", "green", "yellow", | |
32 | "blue", "magenta", "cyan", "white" | |
33 | }; | |
34 | char *end; | |
35 | int i; | |
36 | for (i = 0; i < ARRAY_SIZE(color_names); i++) { | |
37 | const char *str = color_names[i]; | |
38 | if (!strncasecmp(name, str, len) && !str[len]) | |
39 | return i - 1; | |
40 | } | |
41 | i = strtol(name, &end, 10); | |
a0cf49c1 | 42 | if (end - name == len && i >= -1 && i <= 255) |
7c92fe0e JK |
43 | return i; |
44 | return -2; | |
45 | } | |
46 | ||
47 | static int parse_attr(const char *name, int len) | |
48 | { | |
49 | static const int attr_values[] = { 1, 2, 4, 5, 7 }; | |
50 | static const char * const attr_names[] = { | |
51 | "bold", "dim", "ul", "blink", "reverse" | |
52 | }; | |
53 | int i; | |
54 | for (i = 0; i < ARRAY_SIZE(attr_names); i++) { | |
55 | const char *str = attr_names[i]; | |
56 | if (!strncasecmp(name, str, len) && !str[len]) | |
57 | return attr_values[i]; | |
58 | } | |
59 | return -1; | |
60 | } | |
61 | ||
62 | void color_parse(const char *value, const char *var, char *dst) | |
2c2dc7c8 RS |
63 | { |
64 | color_parse_mem(value, strlen(value), var, dst); | |
65 | } | |
66 | ||
67 | void color_parse_mem(const char *value, int value_len, const char *var, | |
68 | char *dst) | |
7c92fe0e JK |
69 | { |
70 | const char *ptr = value; | |
2c2dc7c8 | 71 | int len = value_len; |
8b124135 | 72 | unsigned int attr = 0; |
7c92fe0e JK |
73 | int fg = -2; |
74 | int bg = -2; | |
75 | ||
2c2dc7c8 | 76 | if (!strncasecmp(value, "reset", len)) { |
dc6ebd4c | 77 | strcpy(dst, GIT_COLOR_RESET); |
7c92fe0e JK |
78 | return; |
79 | } | |
80 | ||
8b124135 | 81 | /* [fg [bg]] [attr]... */ |
2c2dc7c8 | 82 | while (len > 0) { |
7c92fe0e | 83 | const char *word = ptr; |
2c2dc7c8 | 84 | int val, wordlen = 0; |
7c92fe0e | 85 | |
2c2dc7c8 RS |
86 | while (len > 0 && !isspace(word[wordlen])) { |
87 | wordlen++; | |
88 | len--; | |
89 | } | |
7c92fe0e | 90 | |
2c2dc7c8 RS |
91 | ptr = word + wordlen; |
92 | while (len > 0 && isspace(*ptr)) { | |
7c92fe0e | 93 | ptr++; |
2c2dc7c8 RS |
94 | len--; |
95 | } | |
7c92fe0e | 96 | |
2c2dc7c8 | 97 | val = parse_color(word, wordlen); |
7c92fe0e JK |
98 | if (val >= -1) { |
99 | if (fg == -2) { | |
100 | fg = val; | |
101 | continue; | |
102 | } | |
103 | if (bg == -2) { | |
104 | bg = val; | |
105 | continue; | |
106 | } | |
107 | goto bad; | |
108 | } | |
2c2dc7c8 | 109 | val = parse_attr(word, wordlen); |
8b124135 JH |
110 | if (0 <= val) |
111 | attr |= (1 << val); | |
112 | else | |
7c92fe0e | 113 | goto bad; |
7c92fe0e JK |
114 | } |
115 | ||
8b124135 | 116 | if (attr || fg >= 0 || bg >= 0) { |
7c92fe0e | 117 | int sep = 0; |
8b124135 | 118 | int i; |
7c92fe0e JK |
119 | |
120 | *dst++ = '\033'; | |
121 | *dst++ = '['; | |
8b124135 JH |
122 | |
123 | for (i = 0; attr; i++) { | |
124 | unsigned bit = (1 << i); | |
125 | if (!(attr & bit)) | |
126 | continue; | |
127 | attr &= ~bit; | |
128 | if (sep++) | |
129 | *dst++ = ';'; | |
130 | *dst++ = '0' + i; | |
7c92fe0e JK |
131 | } |
132 | if (fg >= 0) { | |
133 | if (sep++) | |
134 | *dst++ = ';'; | |
135 | if (fg < 8) { | |
136 | *dst++ = '3'; | |
137 | *dst++ = '0' + fg; | |
138 | } else { | |
139 | dst += sprintf(dst, "38;5;%d", fg); | |
140 | } | |
141 | } | |
142 | if (bg >= 0) { | |
143 | if (sep++) | |
144 | *dst++ = ';'; | |
145 | if (bg < 8) { | |
146 | *dst++ = '4'; | |
147 | *dst++ = '0' + bg; | |
148 | } else { | |
149 | dst += sprintf(dst, "48;5;%d", bg); | |
150 | } | |
151 | } | |
152 | *dst++ = 'm'; | |
153 | } | |
154 | *dst = 0; | |
155 | return; | |
156 | bad: | |
2c2dc7c8 | 157 | die("bad color value '%.*s' for variable '%s'", value_len, value, var); |
7c92fe0e JK |
158 | } |
159 | ||
0f6f5a40 | 160 | int git_config_colorbool(const char *var, const char *value, int stdout_is_tty) |
7c92fe0e | 161 | { |
57f2b842 JH |
162 | if (value) { |
163 | if (!strcasecmp(value, "never")) | |
164 | return 0; | |
165 | if (!strcasecmp(value, "always")) | |
166 | return 1; | |
167 | if (!strcasecmp(value, "auto")) | |
168 | goto auto_color; | |
7c92fe0e | 169 | } |
57f2b842 | 170 | |
73e9da01 ML |
171 | if (!var) |
172 | return -1; | |
173 | ||
57f2b842 JH |
174 | /* Missing or explicit false to turn off colorization */ |
175 | if (!git_config_bool(var, value)) | |
7c92fe0e | 176 | return 0; |
57f2b842 JH |
177 | |
178 | /* any normal truth value defaults to 'auto' */ | |
179 | auto_color: | |
0f6f5a40 JH |
180 | if (stdout_is_tty < 0) |
181 | stdout_is_tty = isatty(1); | |
6e9af863 | 182 | if (stdout_is_tty || (pager_in_use() && pager_use_color)) { |
57f2b842 JH |
183 | char *term = getenv("TERM"); |
184 | if (term && strcmp(term, "dumb")) | |
185 | return 1; | |
186 | } | |
187 | return 0; | |
7c92fe0e JK |
188 | } |
189 | ||
ef90d6d4 | 190 | int git_color_default_config(const char *var, const char *value, void *cb) |
6b2f2d98 MK |
191 | { |
192 | if (!strcmp(var, "color.ui")) { | |
193 | git_use_color_default = git_config_colorbool(var, value, -1); | |
194 | return 0; | |
195 | } | |
196 | ||
ef90d6d4 | 197 | return git_default_config(var, value, cb); |
6b2f2d98 MK |
198 | } |
199 | ||
becbdae8 JN |
200 | void color_print_strbuf(FILE *fp, const char *color, const struct strbuf *sb) |
201 | { | |
202 | if (*color) | |
203 | fprintf(fp, "%s", color); | |
204 | fprintf(fp, "%s", sb->buf); | |
205 | if (*color) | |
206 | fprintf(fp, "%s", GIT_COLOR_RESET); | |
207 | } | |
208 | ||
f26a0012 | 209 | static int color_vfprintf(FILE *fp, const char *color, const char *fmt, |
7c92fe0e JK |
210 | va_list args, const char *trail) |
211 | { | |
212 | int r = 0; | |
213 | ||
214 | if (*color) | |
f26a0012 KH |
215 | r += fprintf(fp, "%s", color); |
216 | r += vfprintf(fp, fmt, args); | |
7c92fe0e | 217 | if (*color) |
dc6ebd4c | 218 | r += fprintf(fp, "%s", GIT_COLOR_RESET); |
7c92fe0e | 219 | if (trail) |
f26a0012 | 220 | r += fprintf(fp, "%s", trail); |
7c92fe0e JK |
221 | return r; |
222 | } | |
223 | ||
224 | ||
225 | ||
f26a0012 | 226 | int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) |
7c92fe0e JK |
227 | { |
228 | va_list args; | |
229 | int r; | |
230 | va_start(args, fmt); | |
f26a0012 | 231 | r = color_vfprintf(fp, color, fmt, args, NULL); |
7c92fe0e JK |
232 | va_end(args); |
233 | return r; | |
234 | } | |
235 | ||
f26a0012 | 236 | int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...) |
7c92fe0e JK |
237 | { |
238 | va_list args; | |
239 | int r; | |
240 | va_start(args, fmt); | |
f26a0012 | 241 | r = color_vfprintf(fp, color, fmt, args, "\n"); |
7c92fe0e JK |
242 | va_end(args); |
243 | return r; | |
244 | } | |
148135fc JK |
245 | |
246 | int color_is_nil(const char *c) | |
247 | { | |
248 | return !strcmp(c, "NIL"); | |
249 | } |