Skip to content

Control color output with C2_COLORS environment variable #178

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 42 additions & 5 deletions ast/utils.c2
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ public type Globals struct @(opaque) {
#if AstStatistics
Stats stats;
#endif
const char*[15] colors;
}

// The only globals for AST are here, since they must be set explicitly for plugins!!
Expand All @@ -124,12 +125,26 @@ public QualType* builtins;
public fn Globals* getGlobals() { return globals; }

// only used by plugins
public fn void setGlobals(Globals* g) @(unused){
public fn void setGlobals(Globals* g) @(unused) {
globals = g;
attr.initialize(g.attr_name_indexes);
col_Normal = g.colors[0];
col_Error = g.colors[1];
col_Warning = g.colors[2];
col_Keyword = g.colors[3];
col_Identifier = g.colors[4];
col_Literal = g.colors[5];
col_Comment = g.colors[6];
col_Stmt = g.colors[7];
col_Decl = g.colors[8];
col_Expr = g.colors[9];
col_Attr = g.colors[10];
col_Template = g.colors[11];
col_Type = g.colors[12];
col_Value = g.colors[13];
col_Calc = g.colors[14];
}


// wordsize in bytes, must NOT be called from Plugin!
public fn void initialize(Context* c, string_pool.Pool* astPool, u32 wordsize, bool use_color) {
globals = stdlib.malloc(sizeof(Globals));
Expand Down Expand Up @@ -181,6 +196,22 @@ public fn void initialize(Context* c, string_pool.Pool* astPool, u32 wordsize, b

attr.register(astPool, globals.attr_name_indexes);
attr.initialize(globals.attr_name_indexes);

globals.colors[0] = col_Normal = color.getConfigColor("normal", color.Normal);
globals.colors[1] = col_Error = color.getConfigColor("error", color.Red);
globals.colors[2] = col_Warning = color.getConfigColor("warning", color.Yellow);
globals.colors[3] = col_Keyword = color.getConfigColor("keyword", color.Green);
globals.colors[4] = col_Identifier = color.getConfigColor("identifier", color.Cyan);
globals.colors[5] = col_Literal = color.getConfigColor("literal", color.Cyan);
globals.colors[6] = col_Comment = color.getConfigColor("comment", color.Cyan);
globals.colors[7] = col_Stmt = color.getConfigColor("ast.stmt", color.Bmagenta);
globals.colors[8] = col_Decl = color.getConfigColor("ast.decl", color.Bgreen);
globals.colors[9] = col_Expr = color.getConfigColor("ast.expr", color.Bmagenta);
globals.colors[10] = col_Attr = color.getConfigColor("ast.attr", color.Blue);
globals.colors[11] = col_Template = color.getConfigColor("ast.template", color.Green);
globals.colors[12] = col_Type = color.getConfigColor("ast.type", color.Green);
globals.colors[13] = col_Value = color.getConfigColor("ast.value", color.Bcyan);
globals.colors[14] = col_Calc = color.getConfigColor("ast.calc", color.Yellow); // all calculated values
}

public fn void deinit(bool print_stats) {
Expand All @@ -196,6 +227,7 @@ public fn void deinit(bool print_stats) {
globals.string_types.clear();
stdlib.free(globals);
stdlib.free(builtins);
// TODO: free allocated config colors
}

public fn u32 getWordSize() {
Expand Down Expand Up @@ -297,17 +329,22 @@ public fn QualType getNativeType() {
return builtins[kind];
}

public const char* col_Normal = color.Normal;
public const char* col_Error = color.Red;
public const char* col_Warning = color.Yellow;
public const char* col_Keyword = color.Green;
public const char* col_Identifier = color.Cyan;
public const char* col_Literal = color.Cyan;
public const char* col_Comment = color.Cyan;

const char* col_Stmt = color.Bmagenta;
const char* col_Decl = color.Bgreen;
const char* col_Expr = color.Bmagenta;
const char* col_Attr = color.Blue;
const char* col_Template = color.Green;
//const char* col_Cast = color.Red;
const char* col_Type = color.Green;
const char* col_Value = color.Bcyan;
const char* col_Error = color.Red;
const char* col_Calc = color.Yellow; // all calculated value
const char* col_Normal = color.Normal;

public type AttrHandlerFn fn bool (void* arg, Decl* d, const attr.Attr* a);

162 changes: 142 additions & 20 deletions ast_utils/color.c2
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,149 @@
*/

module color;
import unistd;

public const char[] Black = "\033[0;30m";
public const char[] Red = "\033[0;31m";
public const char[] Green = "\033[0;32m";
public const char[] Yellow = "\033[0;33m";
public const char[] Blue = "\033[0;34m";
public const char[] Magenta = "\033[0;35m";
public const char[] Cyan = "\033[0;36m";
public const char[] Grey = "\033[0;37m";
public const char[] Darkgrey = "\033[01;30m";
public const char[] Bred = "\033[01;31m";
public const char[] Bgreen = "\033[01;32m";
public const char[] Byellow = "\033[01;33m";
public const char[] Bblue = "\033[01;34m";
public const char[] Bmagenta = "\033[01;35m";
public const char[] Bcyan = "\033[01;36m";
public const char[] White = "\033[01;37m";
public const char[] Normal = "\033[0m";

import ctype local;
import stdio local;
import stdlib local;
import string local;
import unistd local;

public const char[] Black @(unused) = "\033[0;30m";
public const char[] Red @(unused) = "\033[0;31m";
public const char[] Green @(unused) = "\033[0;32m";
public const char[] Yellow @(unused) = "\033[0;33m";
public const char[] Blue @(unused) = "\033[0;34m";
public const char[] Magenta @(unused) = "\033[0;35m";
public const char[] Cyan @(unused) = "\033[0;36m";
public const char[] Grey @(unused) = "\033[0;37m";
public const char[] Darkgrey @(unused) = "\033[01;30m";
public const char[] Bred @(unused) = "\033[01;31m";
public const char[] Bgreen @(unused) = "\033[01;32m";
public const char[] Byellow @(unused) = "\033[01;33m";
public const char[] Bblue @(unused) = "\033[01;34m";
public const char[] Bmagenta @(unused) = "\033[01;35m";
public const char[] Bcyan @(unused) = "\033[01;36m";
public const char[] White @(unused) = "\033[01;37m";
public const char[] Normal @(unused) = "\033[0m";

i8 use_color = -1;
char *c2_colors;

public fn bool useColor() {
return unistd.isatty(1);
if (use_color < 0) {
use_color = isatty(1) != 0;
if (use_color) {
char *p = getenv("C2_COLORS");
if (p) {
if (!strcmp(p, "none"))
use_color = 0;
else
c2_colors = p;
}
}
}
return use_color;
}

const char*[] standardColors = {
"black", Black,
"red", Red,
"green", Green,
"yellow", Yellow,
"blue", Blue,
"magenta", Magenta,
"cyan", Cyan,
"grey", Grey,
"darkgrey", Darkgrey,
"bred", Bred,
"bgreen", Bgreen,
"byellow", Byellow,
"bblue", Bblue,
"bmagenta", Bmagenta,
"bcyan", Bcyan,
"white", White,
"normal", Normal,
}

fn bool getStyleDef(char* buf1, u32 size1, char* buf2, u32 size2, const char** pp) {
const char *p = *pp;
while (isspace(*p))
p++;
if (!*p)
return false;
u32 i = 0;
while (isalpha(*p) || *p == '.' || *p == '_') {
char c = cast<char>(tolower(*p++));
if (i + 1 < size1)
buf1[i++] = c;
}
buf1[i] = '\0';
if (*p != '=' && *p != ':')
return false;
p++;
i = 0;
while (*p && *p != ' ' && *p != ',' && *p != ';') {
char c = cast<char>(tolower(*p++));
if (i + 1 < size2 && c != '-' && c != '_')
buf2[i++] = c;
}
buf2[i] = '\0';
if (*p == ',' || *p == ';')
p++;
*pp = p;
return true;
}

fn bool matchColorName(const char *p, const char *name) {
while (*p) {
char c = *p++;
if (c == 'b' && !strncmp(p, "right", 5))
p += 5;
if (c != *name++)
return false;
}
return *name == '\0';
}

fn const char* convertColor(const char *val, const char *def) {
if (*val == '\0')
return "";

for (u32 i = 0; i < elemsof(standardColors); i += 2) {
if (matchColorName(val, standardColors[i]))
return standardColors[i + 1];
}
if (!strcasecmp(val, "default"))
return def;

char[32] buf;
i32 pal;
i32 r;
i32 g;
i32 b;
if (sscanf(val, "%*1[pP]%d", &pal) == 1) {
snprintf(buf, elemsof(buf), "\033[38;5;%dm", pal);
} else
if (sscanf(val, "#%2x%2x%2x", &r, &g, &b) == 3) {
snprintf(buf, elemsof(buf), "\033[38;2;%d;%d;%dm", r, g, b);
} else {
// TODO: complain about unknown color
return def;
}
return strdup(buf);
}

public fn const char* getConfigColor(const char* cat, const char* def) {
if (!use_color)
return "";
if (c2_colors) {
const char *p = c2_colors;
char[16] style;
char[16] val;
while (getStyleDef(style, elemsof(style), val, elemsof(val), &p)) {
if (!strcmp(style, cat))
return convertColor(val, def);
}
}
return def;
}
45 changes: 18 additions & 27 deletions common/console.c2
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,19 @@ bool show_timing = false;

const u32 BUF_SIZE = 4096;

const char* col_normal = color.Normal;
const char* col_error = color.Red;
const char* col_warning = color.Yellow;
const char* col_debug = color.Blue;
const char* col_timing = color.Blue;

public fn void init() {
use_color = color.useColor();
col_normal = color.getConfigColor("normal", color.Normal);
col_error = color.getConfigColor("error", color.Red);
col_warning = color.getConfigColor("warning", color.Yellow);
col_debug = color.getConfigColor("debug", color.Blue);
col_timing = color.getConfigColor("timing", color.Blue);
}

public fn void setDebug(bool enable) {
Expand All @@ -46,11 +57,7 @@ public fn void debug(const char* format @(printf_format), ...) {
va_start(args, format);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
if (use_color) {
printf("%s%s%s\n", color.Blue, buf, color.Normal);
} else {
printf("%s\n", buf);
}
printf("%s%s%s\n", col_debug, buf, col_normal);
}

public fn void log(const char* format @(printf_format), ...) {
Expand All @@ -68,45 +75,29 @@ public fn void warn(const char* format @(printf_format), ...) {
va_start(args, format);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
if (use_color) {
fprintf(stderr, "%swarning: %s%s\n", color.Yellow, buf, color.Normal);
} else {
fprintf(stderr, "warning: %s\n", buf);
}
fprintf(stderr, "%swarning: %s%s\n", col_warning, buf, col_normal);
}

public fn void error(const char* format @(printf_format), ...) {
char[BUF_SIZE] buf;
va_list args;
va_start(args, format);
vsprintf(buf, format, args);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
if (use_color) {
fprintf(stderr, "%serror: %s%s\n", color.Red, buf, color.Normal);
} else {
fprintf(stderr, "error: %s\n", buf);
}
fprintf(stderr, "%serror: %s%s\n", col_error, buf, col_normal);
}

public fn void error_diag(const char* loc, const char* format @(printf_format), ...) {
char[BUF_SIZE] buf;
va_list args;
va_start(args, format);
vsprintf(buf, format, args);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
if (use_color) {
fprintf(stderr, "%s%s: error: %s%s\n", color.Red, loc, buf, color.Normal);
} else {
fprintf(stderr, "%s: error: %s\n", loc, buf);
}
fprintf(stderr, "%s%s: error: %s%s\n", col_error, loc, buf, col_normal);
}

public fn void log_time(const char* item, u64 duration) {
if (!show_timing) return;
if (use_color) {
printf("%s%s took %d usec%s\n", color.Blue, item, duration, color.Normal);
} else {
printf("%s took %d usec\n", item, duration);
}
printf("%s%s took %d usec%s\n", col_timing, item, duration, col_normal);
}

16 changes: 13 additions & 3 deletions common/diagnostics.c2
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ public fn Diags* create(source_mgr.SourceMgr* sm, bool use_color, const utils.Pa
diags.sm = sm;
diags.out = string_buffer.create(512, use_color, 1);
diags.path_info = path_info;
if (use_color) {
for (u32 i = 0; i < elemsof(category_colors); i++) {
category_colors[i] = color.getConfigColor(category_names[i], category_colors[i]);
}
col_Normal = color.getConfigColor("normal", color.Normal);
col_Range = color.getConfigColor("range", color.Bgreen);
}
return diags;
}

Expand Down Expand Up @@ -75,6 +82,9 @@ const char*[] category_colors = {
color.Bred,
}

const char* col_Normal = color.Normal;
const char* col_Range = color.Bgreen;

public fn void Diags.error(Diags* diags, SrcLoc loc, const char* format @(printf_format), ...) {
va_list args;
va_start(args, format);
Expand Down Expand Up @@ -167,7 +177,7 @@ fn void Diags.internal(Diags* diags,
out.color(category_colors[category]);
out.add(category_names[category]);
out.add(": ");
out.color(color.Normal);
out.color(col_Normal);

out.vprintf(format, args);
out.newline();
Expand Down Expand Up @@ -234,12 +244,12 @@ fn void Diags.internal(Diags* diags,
char c = ' ';
if (text[col - 1] == '\t') // if a TAB was output in the soure
c = '\t'; // output a TAB at the same position
if (col == range_start_col) out.color(color.Bgreen);
if (col == range_start_col) out.color(col_Range);
if (col >= range_start_col && col < range_end_col) c = '~';
if (col == loc_col) c = '^';
out.add1(c);
}
out.color(color.Normal);
out.color(col_Normal);
out.newline();
}
fputs(out.data(), stderr);
Expand Down
Loading