Skip to content

Commit bdbd6c8

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 f398974 commit bdbd6c8

File tree

10 files changed

+225
-92
lines changed

10 files changed

+225
-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: 137 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,138 @@ 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+
if (!usecolors) {
165+
color.normal = getConfigColor("normal", color.Normal);
166+
color.keyword = getConfigColor("keyword", color.Green);
167+
color.identifier = getConfigColor("identifier", color.Cyan);
168+
color.literal = getConfigColor("literal", color.Cyan);
169+
color.comment = getConfigColor("comment", color.Cyan);
170+
color.warning = getConfigColor("warning", color.Yellow);
171+
color.error = getConfigColor("error", color.Red);
172+
}
173+
}
174+
return usecolors;
39175
}
40176

common/console.c2

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,22 @@ 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

26+
const char* col_debug = color.Blue;
27+
const char* col_warning = color.Yellow;
28+
const char* col_error = color.Red;
29+
const char* col_timing = color.Blue;
30+
const char* col_normal = color.Normal;
31+
2732
public fn void init() {
28-
use_color = color.useColor();
33+
color.useColor();
34+
col_debug = color.getConfigColor("debug", color.Blue);
35+
col_warning = color.getConfigColor("warning", color.Yellow);
36+
col_error = color.getConfigColor("error", color.Red);
37+
col_timing = color.getConfigColor("timing", color.Blue);
38+
col_normal = color.normal;
2939
}
3040

3141
public fn void setDebug(bool enable) {
@@ -44,11 +54,7 @@ public fn void debug(const char* format @(printf_format), ...) {
4454
va_start(args, format);
4555
vsnprintf(buf, sizeof(buf), format, args);
4656
va_end(args);
47-
if (use_color) {
48-
printf("%s%s%s\n", color.Blue, buf, color.Normal);
49-
} else {
50-
printf("%s\n", buf);
51-
}
57+
printf("%s%s%s\n", col_debug, buf, col_normal);
5258
}
5359

5460
public fn void log(const char* format @(printf_format), ...) {
@@ -66,11 +72,7 @@ public fn void warn(const char* format @(printf_format), ...) {
6672
va_start(args, format);
6773
vsnprintf(buf, sizeof(buf), format, args);
6874
va_end(args);
69-
if (use_color) {
70-
fprintf(stderr, "%swarning: %s%s\n", color.Yellow, buf, color.Normal);
71-
} else {
72-
fprintf(stderr, "warning: %s\n", buf);
73-
}
75+
fprintf(stderr, "%swarning: %s%s\n", col_warning, buf, col_normal);
7476
}
7577

7678
public fn void error(const char* format @(printf_format), ...) {
@@ -79,11 +81,7 @@ public fn void error(const char* format @(printf_format), ...) {
7981
va_start(args, format);
8082
vsprintf(buf, format, args);
8183
va_end(args);
82-
if (use_color) {
83-
fprintf(stderr, "%serror: %s%s\n", color.Red, buf, color.Normal);
84-
} else {
85-
fprintf(stderr, "error: %s\n", buf);
86-
}
84+
fprintf(stderr, "%serror: %s%s\n", col_error, buf, col_normal);
8785
}
8886

8987
public fn void error_diag(const char* loc, const char* format @(printf_format), ...) {
@@ -92,19 +90,11 @@ public fn void error_diag(const char* loc, const char* format @(printf_format),
9290
va_start(args, format);
9391
vsprintf(buf, format, args);
9492
va_end(args);
95-
if (use_color) {
96-
fprintf(stderr, "%s%s: error: %s%s\n", color.Red, loc, buf, color.Normal);
97-
} else {
98-
fprintf(stderr, "%s: error: %s\n", loc, buf);
99-
}
93+
fprintf(stderr, "%s%s: error: %s%s\n", col_error, loc, buf, col_normal);
10094
}
10195

10296
public fn void log_time(const char* item, u64 duration) {
10397
if (!show_timing) return;
104-
if (use_color) {
105-
printf("%s%s took %d usec%s\n", color.Blue, item, duration, color.Normal);
106-
} else {
107-
printf("%s took %d usec\n", item, duration);
108-
}
98+
printf("%s%s took %d usec%s\n", col_timing, item, duration, col_normal);
10999
}
110100

common/source_mgr.c2

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -210,20 +210,13 @@ fn file_utils.Reader SourceMgr.openInternal(SourceMgr* sm, const char* filename,
210210
} else {
211211
char[256] error_msg;
212212
if (file.errno == file_utils.Err_not_a_file) {
213-
stdio.sprintf(error_msg, "cannot open %s: %s\n",
214-
filename, "not a regular file");
213+
string.strcpy(error_msg, "not a regular file");
215214
} else {
216-
stdio.sprintf(error_msg, "cannot open %s: %s\n",
217-
filename, string.strerror(file.errno));
218-
}
219-
// TODO only color if enabled (cannot use console since we need source loc first)
220-
if (loc) {
221-
stdio.fprintf(stdio.stderr, "%s: %serror:%s %s\n",
222-
sm.loc2str(loc), color.Red, color.Normal, error_msg);
223-
} else {
224-
stdio.fprintf(stdio.stderr, "%serror%s: %s\n",
225-
color.Red, color.Normal, error_msg);
215+
string.strcpy(error_msg, string.strerror(file.errno));
226216
}
217+
// cannot use console since we need source loc first
218+
stdio.fprintf(stdio.stderr, "%s: %serror%s: cannot open %s: %s\n",
219+
sm.loc2str(loc), color.error, color.normal, filename, error_msg);
227220
}
228221
return file;
229222
}
@@ -283,7 +276,7 @@ public fn i32 SourceMgr.open(SourceMgr* sm, u32 filename, SrcLoc loc, bool is_so
283276
if (!sm.close_oldest()) {
284277
// TODO use diags (color)
285278
stdio.fprintf(stdio.stderr, "%serror%s: too many files open\n",
286-
color.Red, color.Normal);
279+
color.error, color.normal);
287280
return -1;
288281
}
289282
}
@@ -333,7 +326,7 @@ fn void SourceMgr.checkOpen(SourceMgr* sm, i32 handle) {
333326
if (!sm.close_oldest()) {
334327
// TODO use diags (color)
335328
stdio.fprintf(stdio.stderr, "%serror%s: too many files open\n",
336-
color.Red, color.Normal);
329+
color.error, color.normal);
337330
stdlib.exit(-1);
338331
}
339332
}

compiler/c2recipe_parser.c2

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

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

0 commit comments

Comments
 (0)