commit 412ad586ea524346a3cf0d3d94b18811854f1dec
parent 888f8043c0903eed3d01da9411d872aab90edd8f
Author: Byron Torres <b@torresjrjr.com>
Date: Tue, 21 Jun 2022 22:10:05 +0100
haredoc: tty: fully implement $HAREDOC_COLORS
Signed-off-by: Byron Torres <b@torresjrjr.com>
Diffstat:
M | cmd/haredoc/tty.ha | | | 197 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ |
1 file changed, 137 insertions(+), 60 deletions(-)
diff --git a/cmd/haredoc/tty.ha b/cmd/haredoc/tty.ha
@@ -18,6 +18,7 @@ let firstline: bool = true;
// Formats output as Hare source code (prototypes) with syntax highlighting
fn emit_tty(ctx: *context) (void | error) = {
+ init_colors();
const summary = ctx.summary;
match (ctx.readme) {
@@ -60,11 +61,13 @@ fn emit_submodules_tty(ctx: *context) (void | error) = {
if (len(submodules) != 0) {
fmt::fprintln(ctx.out)?;
if (len(ctx.ident) == 0) {
- fmt::fprintln(ctx.out,
- "\x1b[1m" "// Modules" "\x1b[0m")?;
+ render(ctx.out, syn::COMMENT)?;
+ fmt::fprintln(ctx.out, "// Modules")?;
+ render(ctx.out, syn::NORMAL)?;
} else {
- fmt::fprintln(ctx.out,
- "\x1b[1m" "// Submodules" "\x1b[0m")?;
+ render(ctx.out, syn::COMMENT)?;
+ fmt::fprintln(ctx.out, "// Submodules")?;
+ render(ctx.out, syn::NORMAL)?;
};
for (let i = 0z; i < len(submodules); i += 1) {
let submodule = if (len(ctx.ident) != 0) {
@@ -76,14 +79,19 @@ fn emit_submodules_tty(ctx: *context) (void | error) = {
};
defer free(submodule);
- fmt::fprintfln(ctx.out,
- "\x1b[1m" "// - [[{}]]" "\x1b[0m", submodule)?;
+ render(ctx.out, syn::COMMENT)?;
+ fmt::fprintfln(ctx.out, "// - [[{}]]", submodule)?;
+ render(ctx.out, syn::NORMAL)?;
};
};
};
fn comment_tty(out: io::handle, s: str) (size | io::error) = {
- return fmt::fprintfln(out, "\x1b[1m" "//{}" "\x1b[0m", s)?;
+ let n = 0z;
+ n += render(out, syn::COMMENT)?;
+ n += fmt::fprintfln(out, "//{}", s)?;
+ n += render(out, syn::NORMAL)?;
+ return n;
};
fn docs_tty(out: io::handle, s: str, indent: size) (size | io::error) = {
@@ -137,45 +145,59 @@ fn unparse_tty(out: io::handle, d: ast::decl) (size | io::error) = {
let n = 0z;
match (d.decl) {
case let g: []ast::decl_global =>
- n += fmt::fprint(out, "\x1b[34m")?;
- n += fmt::fprint(out,
- if (g[0].is_const) "const " else "let ")?;
- n += fmt::fprint(out, "\x1b[0m")?;
+ n += render(out, syn::KEYWORD)?;
+ n += fmt::fprint(out, if (g[0].is_const) "const " else "let ")?;
for (let i = 0z; i < len(g); i += 1) {
if (len(g[i].symbol) != 0) {
- n += fmt::fprintf(out,
- "\x1b[33m" "@symbol(\"{}\") " "\x1b[0m",
- g[i].symbol)?;
+ n += render(out, syn::ATTRIBUTE)?;
+ n += fmt::fprintf(out, "@symbol(")?;
+ n += render(out, syn::STRING)?;
+ n += fmt::fprintf(out, `"{}"`, g[i].symbol)?;
+ n += render(out, syn::ATTRIBUTE)?;
+ n += fmt::fprintf(out, ") ")?;
+ n += render(out, syn::NORMAL)?;
};
+ n += render(out, syn::PRIMARY)?;
n += unparse::ident(out, g[i].ident)?;
+ n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, ": ")?;
n += type_tty(out, 0, g[i]._type)?;
if (i + 1 < len(g)) {
+ n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, ", ")?;
};
+ n += render(out, syn::NORMAL)?;
};
case let c: []ast::decl_const =>
- n += fmt::fprintf(out, "\x1b[34m" "def " "\x1b[0m")?;
+ n += render(out, syn::KEYWORD)?;
+ n += fmt::fprintf(out, "def ")?;
for (let i = 0z; i < len(c); i += 1) {
+ n += render(out, syn::PRIMARY)?;
n += unparse::ident(out, c[i].ident)?;
+ n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, ": ")?;
n += type_tty(out, 0, c[i]._type)?;
if (i + 1 < len(c)) {
+ n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, ", ")?;
};
};
case let t: []ast::decl_type =>
- n += fmt::fprint(out, "\x1b[34m" "type " "\x1b[0m")?;
+ n += render(out, syn::KEYWORD)?;
+ n += fmt::fprint(out, "type ")?;
for (let i = 0z; i < len(t); i += 1) {
+ n += render(out, syn::PRIMARY)?;
n += unparse::ident(out, t[i].ident)?;
+ n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, " = ")?;
n += type_tty(out, 0, t[i]._type)?;
if (i + 1 < len(t)) {
+ n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, ", ")?;
};
};
case let f: ast::decl_func =>
- n += fmt::fprint(out, "\x1b[33m")?;
+ n += render(out, syn::ATTRIBUTE)?;
n += fmt::fprint(out, switch (f.attrs) {
case ast::fndecl_attrs::NONE =>
yield "";
@@ -186,23 +208,31 @@ fn unparse_tty(out: io::handle, d: ast::decl) (size | io::error) = {
case ast::fndecl_attrs::TEST =>
yield "@test ";
})?;
- n += fmt::fprint(out, "\x1b[0m")?;
+ n += render(out, syn::NORMAL)?;
let p = f.prototype.repr as ast::func_type;
if (p.attrs & ast::func_attrs::NORETURN != 0) {
- n += fmt::fprint(out,
- "\x1b[33m" "@noreturn " "\x1b[0m")?;
+ n += render(out, syn::ATTRIBUTE)?;
+ n += fmt::fprint(out, "@noreturn ")?;
+ n += render(out, syn::NORMAL)?;
};
if (len(f.symbol) != 0) {
- n += fmt::fprintf(out,
- "\x1b[33m" "@symbol(\"{}\") " "\x1b[0m",
- f.symbol)?;
+ n += render(out, syn::ATTRIBUTE)?;
+ n += fmt::fprintf(out, "@symbol(")?;
+ n += render(out, syn::STRING)?;
+ n += fmt::fprintf(out, `"{}"`, f.symbol)?;
+ n += render(out, syn::ATTRIBUTE)?;
+ n += fmt::fprintf(out, ") ")?;
+ n += render(out, syn::NORMAL)?;
};
- n += fmt::fprint(out, "\x1b[34m" "fn " "\x1b[0m")?;
+ n += render(out, syn::KEYWORD)?;
+ n += fmt::fprint(out, "fn ")?;
+ n += render(out, syn::PRIMARY)?;
n += unparse::ident(out, f.ident)?;
n += prototype_tty(out, 0,
f.prototype.repr as ast::func_type)?;
};
+ n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, ";")?;
return n;
};
@@ -213,6 +243,7 @@ fn prototype_tty(
t: ast::func_type,
) (size | io::error) = {
let n = 0z;
+ n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, "(")?;
let typenames: []str = [];
@@ -262,42 +293,57 @@ fn prototype_tty(
for (let i = 0z; i < len(t.params); i += 1) {
const param = t.params[i];
n += newline(out, indent)?;
- n += fmt::fprintf(out, "{}: ",
+ n += render(out, syn::SECONDARY)?;
+ n += fmt::fprint(out,
if (param.name == "") "_" else param.name)?;
+ n += render(out, syn::PUNCTUATION)?;
+ n += fmt::fprint(out, ": ")?;
+ n += render(out, syn::TYPE)?;
n += fmt::fprint(out, typenames[i])?;
if (i + 1 == len(t.params)
&& t.variadism == variadism::HARE) {
+ n += render(out, syn::OPERATOR)?;
n += fmt::fprint(out, "...")?;
} else {
+ n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, ",")?;
};
};
if (t.variadism == variadism::C) {
n += newline(out, indent)?;
+ n += render(out, syn::OPERATOR)?;
n += fmt::fprint(out, "...")?;
};
indent -= 1;
n += newline(out, indent)?;
} else for (let i = 0z; i < len(t.params); i += 1) {
const param = t.params[i];
- n += fmt::fprintf(out, "{}" "\x1b[0m" ": ",
+ n += render(out, syn::SECONDARY)?;
+ n += fmt::fprint(out,
if (param.name == "") "_" else param.name)?;
- n += fmt::fprint(out, "\x1b[36m")?;
+ n += render(out, syn::PUNCTUATION)?;
+ n += fmt::fprint(out, ": ")?;
+ n += render(out, syn::TYPE)?;
n += fmt::fprint(out, typenames[i])?;
- n += fmt::fprint(out, "\x1b[0m")?;
if (i + 1 == len(t.params)) {
switch (t.variadism) {
case variadism::NONE => void;
case variadism::HARE =>
+ n += render(out, syn::OPERATOR)?;
n += fmt::fprint(out, "...")?;
case variadism::C =>
- n += fmt::fprint(out, ", ...")?;
+ n += render(out, syn::PUNCTUATION)?;
+ n += fmt::fprint(out, ", ")?;
+ n += render(out, syn::OPERATOR)?;
+ n += fmt::fprint(out, "...")?;
};
} else {
+ n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, ", ")?;
};
};
+ n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, ")", retname)?;
return n;
};
@@ -308,50 +354,63 @@ fn struct_union_type_tty(
indent: size,
t: ast::_type,
) (size | io::error) = {
- let z = 0z;
+ let n = 0z;
let membs = match (t.repr) {
case let st: ast::struct_type =>
- z += fmt::fprint(out,
- "\x1b[36m" "struct" "\x1b[0m" " {")?;
+ n += render(out, syn::TYPE)?;
+ n += fmt::fprint(out, "struct")?;
+ n += render(out, syn::PUNCTUATION)?;
+ n += fmt::fprint(out, " {")?;
yield st: []ast::struct_member;
case let ut: ast::union_type =>
- z += fmt::fprint(out,
- "\x1b[36m" "union" "\x1b[0m" " {")?;
+ n += render(out, syn::TYPE)?;
+ n += fmt::fprint(out, "union")?;
+ n += render(out, syn::PUNCTUATION)?;
+ n += fmt::fprint(out, " {")?;
yield ut: []ast::struct_member;
};
indent += 1z;
for (let i = 0z; i < len(membs); i += 1) {
- z += newline(out, indent)?;
+ n += newline(out, indent)?;
if (membs[i].docs != "") {
- z += docs_tty(out, membs[i].docs, indent)?;
+ n += docs_tty(out, membs[i].docs, indent)?;
};
match (membs[i]._offset) {
case null => void;
case let ex: *ast::expr =>
- z += fmt::fprint(out, "\x1b[33m" "@offset(")?;
- z += unparse::expr(out, indent, *ex)?;
- z += fmt::fprint(out, ") \x1b[0m")?;
+ n += render(out, syn::ATTRIBUTE)?;
+ n += fmt::fprint(out, "@offset(")?;
+ n += render(out, syn::NUMBER)?;
+ n += unparse::expr(out, indent, *ex)?;
+ n += render(out, syn::ATTRIBUTE)?;
+ n += fmt::fprint(out, ")")?;
+ n += render(out, syn::NORMAL)?;
};
match (membs[i].member) {
case let se: ast::struct_embedded =>
- z += type_tty(out, indent, *se)?;
+ n += type_tty(out, indent, *se)?;
case let sa: ast::struct_alias =>
- z += unparse::ident(out, sa)?;
+ n += unparse::ident(out, sa)?;
case let sf: ast::struct_field =>
- z += fmt::fprintf(out, "{}: ", sf.name)?;
- z += type_tty(out, indent, *sf._type)?;
+ n += render(out, syn::SECONDARY)?;
+ n += fmt::fprint(out, sf.name)?;
+ n += render(out, syn::PUNCTUATION)?;
+ n += fmt::fprint(out, ": ")?;
+ n += type_tty(out, indent, *sf._type)?;
};
- z += fmt::fprint(out, ",")?;
+ n += render(out, syn::PUNCTUATION)?;
+ n += fmt::fprint(out, ",")?;
};
indent -= 1;
- z += newline(out, indent)?;
- z += fmt::fprint(out, "}")?;
- return z;
+ n += newline(out, indent)?;
+ n += render(out, syn::PUNCTUATION)?;
+ n += fmt::fprint(out, "}")?;
+ return n;
};
// Forked from [[hare::unparse]]
@@ -363,30 +422,33 @@ fn type_tty(
let n = 0z;
if (t.flags & ast::type_flags::CONST != 0
&& !(t.repr is ast::func_type)) {
- n += fmt::fprint(out, "\x1b[36m" "const " "\x1b[0m")?;
+ n += render(out, syn::TYPE)?;
+ n += fmt::fprint(out, "const ")?;
};
if (t.flags & ast::type_flags::ERROR != 0) {
+ n += render(out, syn::OPERATOR)?;
n += fmt::fprint(out, "!")?;
};
match (t.repr) {
case let a: ast::alias_type =>
- n += fmt::fprint(out, "\x1b[36m")?;
if (a.unwrap) {
+ n += render(out, syn::OPERATOR)?;
n += fmt::fprint(out, "...")?;
};
+ n += render(out, syn::TYPE)?;
n += unparse::ident(out, a.ident)?;
- n += fmt::fprint(out, "\x1b[0m")?;
case let b: ast::builtin_type =>
- n += fmt::fprintf(out, "\x1b[36m" "{}" "\x1b[0m",
- unparse::builtin_type(b))?;
+ n += render(out, syn::TYPE)?;
+ n += fmt::fprintf(out, "{}", unparse::builtin_type(b))?;
case let e: ast::enum_type =>
- n += fmt::fprint(out, "\x1b[36m" "enum " "\x1b[0m")?;
+ n += render(out, syn::TYPE)?;
+ n += fmt::fprint(out, "enum ")?;
if (e.storage != ast::builtin_type::INT) {
n += fmt::fprintf(out,
- "\x1b[36m" "{} " "\x1b[0m",
- unparse::builtin_type(e.storage))?;
+ "{} ", unparse::builtin_type(e.storage))?;
};
+ n += render(out, syn::PUNCTUATION)?;
n += fmt::fprintln(out, "{")?;
indent += 1;
for (let i = 0z; i < len(e.values); i += 1) {
@@ -403,13 +465,17 @@ fn type_tty(
wrotedocs = true;
};
};
+ n += render(out, syn::SECONDARY)?;
n += fmt::fprint(out, value.name)?;
match (value.value) {
case null => void;
case let e: *ast::expr =>
+ n += render(out, syn::OPERATOR)?;
n += fmt::fprint(out, " = ")?;
+ n += render(out, syn::NORMAL)?;
n += unparse::expr(out, indent, *e)?;
};
+ n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, ",")?;
if (value.docs != "" && !wrotedocs) {
n += fmt::fprint(out, " ")?;
@@ -422,15 +488,18 @@ fn type_tty(
for (let i = 0z; i < indent; i += 1) {
n += fmt::fprint(out, "\t")?;
};
+ n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, "}")?;
case let f: ast::func_type =>
if (f.attrs & ast::func_attrs::NORETURN != 0) {
- n += fmt::fprint(out,
- "\x1b[33m" "@noreturn " "\x1b[0m")?;
+ n += render(out, syn::ATTRIBUTE)?;
+ n += fmt::fprint(out, "@noreturn ")?;
};
- n += fmt::fprint(out, "\x1b[34m" "fn" "\x1b[0m")?;
+ n += render(out, syn::TYPE)?;
+ n += fmt::fprint(out, "fn")?;
n += prototype_tty(out, indent, f)?;
case let l: ast::list_type =>
+ n += render(out, syn::OPERATOR)?;
n += fmt::fprint(out, "[")?;
match (l.length) {
case ast::len_slice => void;
@@ -441,13 +510,15 @@ fn type_tty(
case let e: *ast::expr =>
n += unparse::expr(out, indent, *e)?;
};
+ n += render(out, syn::OPERATOR)?;
n += fmt::fprint(out, "]")?;
n += type_tty(out, indent, *l.members)?;
case let p: ast::pointer_type =>
if (p.flags & ast::pointer_flags::NULLABLE != 0) {
- n += fmt::fprint(out,
- "\x1b[36m" "nullable " "\x1b[0m")?;
+ n += render(out, syn::TYPE)?;
+ n += fmt::fprint(out, "nullable ")?;
};
+ n += render(out, syn::OPERATOR)?;
n += fmt::fprint(out, "*")?;
n += type_tty(out, indent, *p.referent)?;
case ast::struct_type =>
@@ -458,10 +529,12 @@ fn type_tty(
// rough estimate of current line length
let linelen: size = n + (indent + 1) * 8;
n = 0;
+ n += render(out, syn::PUNCTUATION)?;
linelen += fmt::fprint(out, "(")?;
for (let i = 0z; i < len(t); i += 1) {
linelen += type_tty(out, indent, *t[i])?;
if (i + 1 == len(t)) break;
+ n += render(out, syn::PUNCTUATION)?;
linelen += fmt::fprint(out, " |")?;
// use 72 instead of 80 to give a bit of leeway for long
// type names
@@ -477,15 +550,18 @@ fn type_tty(
};
};
n += linelen;
+ n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, ")")?;
case let t: ast::tuple_type =>
// rough estimate of current line length
let linelen: size = n + (indent + 1) * 8;
n = 0;
+ n += render(out, syn::PUNCTUATION)?;
linelen += fmt::fprint(out, "(")?;
for (let i = 0z; i < len(t); i += 1) {
linelen += type_tty(out, indent, *t[i])?;
if (i + 1 == len(t)) break;
+ n += render(out, syn::PUNCTUATION)?;
linelen += fmt::fprint(out, ",")?;
// use 72 instead of 80 to give a bit of leeway for long
// type names
@@ -501,6 +577,7 @@ fn type_tty(
};
};
n += linelen;
+ n += render(out, syn::PUNCTUATION)?;
n += fmt::fprint(out, ")")?;
};
return n;