Skip to content

Commit f4b6725

Browse files
committed
Control color output with C2_COLORS environment variable
* use style names instead of hard-coded color names * customize color output via environment variable `C2_COLORS`: eg: `C2_COLORS=none`, `C2_COLORS="error:bright-blue`, `C2_COLORS="error:#d0d0d0` * use cache to multiple calls to `unix.isatty()` and `stdib.getenv()` * simplify error formating in **source_mgr.c2** * add c2cat color customisation
1 parent 73946a8 commit f4b6725

File tree

10 files changed

+223
-92
lines changed

10 files changed

+223
-92
lines changed

ast/utils.c2

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,18 @@ public fn void init(Context* c, string_pool.Pool* astPool, u32 wordsize, bool us
176176

177177
attr.register(astPool, globals.attr_name_indexes);
178178
attr.init(globals.attr_name_indexes);
179+
180+
col_Stmt = color.getConfigColor("ast.stmt", color.Bmagenta);
181+
col_Decl = color.getConfigColor("ast.decl", color.Bgreen);
182+
col_Expr = color.getConfigColor("ast.expr", color.Bmagenta);
183+
col_Attr = color.getConfigColor("ast.attr", color.Blue);
184+
col_Template = color.getConfigColor("ast.template", color.Green);
185+
//col_Cast = color.getConfigColor("ast.cast", color.Red);
186+
col_Type = color.getConfigColor("ast.type", color.Green);
187+
col_Value = color.getConfigColor("ast.value", color.Bcyan);
188+
col_Error = color.getConfigColor("ast.error", color.Red);
189+
col_Calc = color.getConfigColor("ast.calc", color.Yellow); // all calculated value
190+
col_Normal = color.getConfigColor("ast.normal", color.Normal);
179191
}
180192

181193
public fn void deinit(bool print_stats) {
@@ -191,6 +203,7 @@ public fn void deinit(bool print_stats) {
191203
globals.string_types.clear();
192204
stdlib.free(globals);
193205
stdlib.free(builtins);
206+
// TODO: free allocated config colors
194207
}
195208

196209
public fn u32 getWordSize() {

ast_utils/color.c2

Lines changed: 135 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
*/
1515

1616
module color;
17+
18+
import ctype;
19+
import stdio;
20+
import stdlib;
21+
import string;
1722
import unistd;
1823

1924
public const char[] Black = "\033[0;30m";
@@ -34,7 +39,136 @@ public const char[] Bcyan = "\033[01;36m";
3439
public const char[] White = "\033[01;37m";
3540
public const char[] Normal = "\033[0m";
3641

42+
const char*[] standardColors = {
43+
"black", Black,
44+
"red", Red,
45+
"green", Green,
46+
"yellow", Yellow,
47+
"blue", Blue,
48+
"magenta", Magenta,
49+
"cyan", Cyan,
50+
"grey", Grey,
51+
"darkgrey", Darkgrey,
52+
"bred", Bred,
53+
"bgreen", Bgreen,
54+
"byellow", Byellow,
55+
"bblue", Bblue,
56+
"bmagenta", Bmagenta,
57+
"bcyan", Bcyan,
58+
"white", White,
59+
"normal", Normal,
60+
"brightred", Bred,
61+
"brightgreen", Bgreen,
62+
"brightyellow", Byellow,
63+
"brightblue", Bblue,
64+
"brightmagenta", Bmagenta,
65+
"brightcyan", Bcyan,
66+
}
67+
68+
// colors used in the parser
69+
public const char* normal = color.Normal;
70+
public const char* keyword = color.Green;
71+
public const char* identifier = color.Cyan;
72+
public const char* literal = color.Cyan;
73+
public const char* comment = color.Cyan;
74+
public const char* warning = color.Yellow;
75+
public const char* error = color.Red;
76+
77+
i8 usecolors = -1;
78+
char *c2_colors;
79+
80+
fn bool getStyleDef(char* buf1, u32 size1, char* buf2, u32 size2, const char** pp) {
81+
const char *p = *pp;
82+
while (ctype.isspace(*p))
83+
p++;
84+
if (!*p)
85+
return false;
86+
u32 i = 0;
87+
while (ctype.isalpha(*p) || *p == '.' || *p == '_') {
88+
char c = cast<char>(ctype.tolower(*p++));
89+
if (i + 1 < size1)
90+
buf1[i++] = c;
91+
}
92+
buf1[i] = '\0';
93+
if (*p != '=' && *p != ':')
94+
return false;
95+
p++;
96+
i = 0;
97+
while (*p && *p != ' ' && *p != ',' && *p != ';') {
98+
char c = cast<char>(ctype.tolower(*p++));
99+
if (i + 1 < size2 && c != '-' && c != '_')
100+
buf2[i++] = c;
101+
}
102+
buf2[i] = '\0';
103+
if (*p == ',' || *p == ';')
104+
p++;
105+
*pp = p;
106+
return true;
107+
}
108+
109+
fn const char* convertColor(const char *val, const char *def) {
110+
if (*val == '\0')
111+
return "";
112+
113+
for (u32 i = 0; i < elemsof(standardColors); i += 2) {
114+
if (!string.strcmp(standardColors[i], val))
115+
return standardColors[i + 1];
116+
}
117+
if (!string.strcmp(val, "default"))
118+
return def;
119+
120+
char[32] buf;
121+
i32 pal;
122+
i32 r;
123+
i32 g;
124+
i32 b;
125+
if (stdio.sscanf(val, "p%d", &pal) == 1) {
126+
stdio.snprintf(buf, elemsof(buf), "\033[38;5;%dm", pal);
127+
} else
128+
if (stdio.sscanf(val, "#%2x%2x%2x", &r, &g, &b) == 3) {
129+
stdio.snprintf(buf, elemsof(buf), "\033[38;2;%d;%d;%dm", r, g, b);
130+
} else {
131+
// TODO: complain about unknown color
132+
return def;
133+
}
134+
return string.strdup(buf);
135+
}
136+
137+
public fn const char* getConfigColor(const char* cat, const char* def) {
138+
if (!usecolors)
139+
return "";
140+
if (c2_colors) {
141+
const char *p = c2_colors;
142+
char[16] style;
143+
char[16] val;
144+
while (getStyleDef(style, elemsof(style), val, elemsof(val), &p)) {
145+
if (!string.strcmp(style, cat))
146+
return convertColor(val, def);
147+
}
148+
}
149+
return def;
150+
}
151+
37152
public fn bool useColor() {
38-
return unistd.isatty(1);
153+
if (usecolors < 0) {
154+
usecolors = unistd.isatty(1) != 0;
155+
if (usecolors) {
156+
char *p = stdlib.getenv("C2_COLORS");
157+
if (p) {
158+
if (!string.strcmp(p, "none"))
159+
usecolors = 0;
160+
else
161+
c2_colors = p;
162+
}
163+
}
164+
color.normal = getConfigColor("normal", color.Normal);
165+
color.keyword = getConfigColor("keyword", color.Green);
166+
color.identifier = getConfigColor("identifier", color.Cyan);
167+
color.literal = getConfigColor("literal", color.Cyan);
168+
color.comment = getConfigColor("comment", color.Cyan);
169+
color.warning = getConfigColor("warning", color.Yellow);
170+
color.error = getConfigColor("error", color.Red);
171+
}
172+
return usecolors;
39173
}
40174

common/console.c2

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,24 @@ import stdarg local;
2020

2121
import color local;
2222

23-
bool use_color = false;
2423
bool show_debug = false;
2524
bool show_timing = false;
2625

2726
const u32 BUF_SIZE = 4096;
2827

28+
const char* col_debug = color.Blue;
29+
const char* col_warning = color.Yellow;
30+
const char* col_error = color.Red;
31+
const char* col_timing = color.Blue;
32+
const char* col_normal = color.Normal;
33+
2934
public fn void init() {
30-
use_color = color.useColor();
35+
color.useColor();
36+
col_debug = color.getConfigColor("debug", color.Blue);
37+
col_warning = color.getConfigColor("warning", color.Yellow);
38+
col_error = color.getConfigColor("error", color.Red);
39+
col_timing = color.getConfigColor("timing", color.Blue);
40+
col_normal = color.normal;
3141
}
3242

3343
public fn void setDebug(bool enable) {
@@ -46,11 +56,7 @@ public fn void debug(const char* format @(printf_format), ...) {
4656
va_start(args, format);
4757
vsnprintf(buf, sizeof(buf), format, args);
4858
va_end(args);
49-
if (use_color) {
50-
printf("%s%s%s\n", color.Blue, buf, color.Normal);
51-
} else {
52-
printf("%s\n", buf);
53-
}
59+
printf("%s%s%s\n", col_debug, buf, col_normal);
5460
}
5561

5662
public fn void log(const char* format @(printf_format), ...) {
@@ -68,11 +74,7 @@ public fn void warn(const char* format @(printf_format), ...) {
6874
va_start(args, format);
6975
vsnprintf(buf, sizeof(buf), format, args);
7076
va_end(args);
71-
if (use_color) {
72-
fprintf(stderr, "%swarning: %s%s\n", color.Yellow, buf, color.Normal);
73-
} else {
74-
fprintf(stderr, "warning: %s\n", buf);
75-
}
77+
fprintf(stderr, "%swarning: %s%s\n", col_warning, buf, col_normal);
7678
}
7779

7880
public fn void error(const char* format @(printf_format), ...) {
@@ -81,11 +83,7 @@ public fn void error(const char* format @(printf_format), ...) {
8183
va_start(args, format);
8284
vsprintf(buf, format, args);
8385
va_end(args);
84-
if (use_color) {
85-
fprintf(stderr, "%serror: %s%s\n", color.Red, buf, color.Normal);
86-
} else {
87-
fprintf(stderr, "error: %s\n", buf);
88-
}
86+
fprintf(stderr, "%serror: %s%s\n", col_error, buf, col_normal);
8987
}
9088

9189
public fn void error_diag(const char* loc, const char* format @(printf_format), ...) {
@@ -94,19 +92,11 @@ public fn void error_diag(const char* loc, const char* format @(printf_format),
9492
va_start(args, format);
9593
vsprintf(buf, format, args);
9694
va_end(args);
97-
if (use_color) {
98-
fprintf(stderr, "%s%s: error: %s%s\n", color.Red, loc, buf, color.Normal);
99-
} else {
100-
fprintf(stderr, "%s: error: %s\n", loc, buf);
101-
}
95+
fprintf(stderr, "%s%s: error: %s%s\n", col_error, loc, buf, col_normal);
10296
}
10397

10498
public fn void log_time(const char* item, u64 duration) {
10599
if (!show_timing) return;
106-
if (use_color) {
107-
printf("%s%s took %d usec%s\n", color.Blue, item, duration, color.Normal);
108-
} else {
109-
printf("%s took %d usec\n", item, duration);
110-
}
100+
printf("%s%s took %d usec%s\n", col_timing, item, duration, col_normal);
111101
}
112102

common/source_mgr.c2

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -222,20 +222,13 @@ fn file_utils.Reader SourceMgr.openInternal(SourceMgr* sm, const char* filename,
222222
} else {
223223
char[256] error_msg;
224224
if (file.errno == file_utils.Err_not_a_file) {
225-
stdio.sprintf(error_msg, "cannot open %s: %s\n",
226-
filename, "not a regular file");
225+
string.strcpy(error_msg, "not a regular file");
227226
} else {
228-
stdio.sprintf(error_msg, "cannot open %s: %s\n",
229-
filename, string.strerror(file.errno));
230-
}
231-
// TODO only color if enabled (cannot use console since we need source loc first)
232-
if (loc) {
233-
stdio.fprintf(stdio.stderr, "%s: %serror:%s %s\n",
234-
sm.loc2str(loc), color.Red, color.Normal, error_msg);
235-
} else {
236-
stdio.fprintf(stdio.stderr, "%serror%s: %s\n",
237-
color.Red, color.Normal, error_msg);
227+
string.strcpy(error_msg, string.strerror(file.errno));
238228
}
229+
// cannot use console since we need source loc first
230+
stdio.fprintf(stdio.stderr, "%s: %serror%s: cannot open %s: %s\n",
231+
sm.loc2str(loc), color.error, color.normal, filename, error_msg);
239232
}
240233
return file;
241234
}
@@ -298,7 +291,7 @@ public fn i32 SourceMgr.open(SourceMgr* sm, u32 filename, SrcLoc loc, bool is_so
298291
if (!sm.close_oldest()) {
299292
// TODO use diags (color)
300293
stdio.fprintf(stdio.stderr, "%serror%s: too many files open\n",
301-
color.Red, color.Normal);
294+
color.error, color.normal);
302295
return -1;
303296
}
304297
}
@@ -351,7 +344,7 @@ fn void SourceMgr.checkOpen(SourceMgr* sm, i32 handle) {
351344
if (!sm.close_oldest()) {
352345
// TODO use diags (color)
353346
stdio.fprintf(stdio.stderr, "%serror%s: too many files open\n",
354-
color.Red, color.Normal);
347+
color.error, color.normal);
355348
stdlib.exit(-1);
356349
}
357350
}

compiler/c2recipe_parser.c2

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,7 @@ fn void Parser.error(Parser* p, const char* format @(printf_format), ...) @(nore
142142
vsnprintf(msg, sizeof(msg)-1, format, args);
143143
va_end(args);
144144

145-
if (color.useColor()) {
146-
fprintf(stderr, "%s: %serror:%s %s\n", p.sm.loc2str(p.token.loc), color.Red, color.Normal, msg);
147-
} else {
148-
fprintf(stderr, "%s: error: %s\n", p.sm.loc2str(p.token.loc), msg);
149-
}
145+
fprintf(stderr, "%s: %serror:%s %s\n", p.sm.loc2str(p.token.loc), color.error, color.normal, msg);
150146
longjmp(&p.jmpbuf, 1);
151147
}
152148

0 commit comments

Comments
 (0)