tty.ha (3762B)
1 // SPDX-License-Identifier: GPL-3.0-only 2 // (c) Hare authors <https://harelang.org> 3 4 use bufio; 5 use fmt; 6 use hare::ast; 7 use hare::unparse; 8 use io; 9 use memio; 10 use os; 11 use strings; 12 13 let no_color: bool = false; 14 15 // Formats output as Hare source code (prototypes) with syntax highlighting 16 export fn emit_tty(ctx: *context) (void | error) = { 17 if (os::tryenv("NO_COLOR", "") == "") { 18 init_colors()?; 19 } else { 20 no_color = true; 21 }; 22 const summary = ctx.summary; 23 24 if (ctx.ambiguous) { 25 const id = unparse::identstr(ctx.ident); 26 defer free(id); 27 28 if (!no_color) fmt::fprintf(ctx.out, "\x1b[{}m", 29 color(unparse::synkind::COMMENT))?; 30 fmt::fprint(ctx.out, "// ")?; 31 if (!no_color) fmt::fprint(ctx.out, "\x1b[93m")?; 32 fmt::fprint(ctx.out, "NOTE")?; 33 if (!no_color) fmt::fprintf(ctx.out, "\x1b[m" "\x1b[{}m", 34 color(unparse::synkind::COMMENT))?; 35 fmt::fprintf(ctx.out, ": {} also refers to module [[{}::]]", 36 id, id)?; 37 if (!no_color) fmt::fprint(ctx.out, "\x1b[m")?; 38 fmt::fprintln(ctx.out, "\n")?; 39 }; 40 41 match (ctx.readme) { 42 case let readme: io::file => 43 let rbuf: [os::BUFSZ]u8 = [0...]; 44 let readme = bufio::init(readme, rbuf, []); 45 let sc = bufio::newscanner(&readme); 46 defer bufio::finish(&sc); 47 for (let line => bufio::scan_line(&sc)?) { 48 firstline = false; 49 if (!no_color) fmt::fprintf(ctx.out, "\x1b[{}m", 50 color(unparse::synkind::COMMENT))?; 51 fmt::fprint(ctx.out, "//", line)?; 52 if (!no_color) fmt::fprint(ctx.out, "\x1b[m")?; 53 fmt::fprintln(ctx.out)?; 54 }; 55 case void => void; 56 }; 57 58 emit_submodules_tty(ctx)?; 59 60 // XXX: Should we emit the dependencies, too? 61 let printed = false; 62 for (let t &.. summary.types) { 63 if (details_tty(ctx, t)?) { 64 printed = true; 65 }; 66 }; 67 for (let c &.. summary.constants) { 68 if (details_tty(ctx, c)?) { 69 printed = true; 70 }; 71 }; 72 for (let e &.. summary.errors) { 73 if (details_tty(ctx, e)?) { 74 printed = true; 75 }; 76 }; 77 for (let g &.. summary.globals) { 78 if (details_tty(ctx, g)?) { 79 printed = true; 80 }; 81 }; 82 for (let f &.. summary.funcs) { 83 if (details_tty(ctx, f)?) { 84 printed = true; 85 }; 86 }; 87 88 if (!printed) { 89 if (!firstline) { 90 fmt::fprintln(ctx.out)?; 91 }; 92 if (!no_color) fmt::fprintf(ctx.out, "\x1b[{}m", 93 color(unparse::synkind::COMMENT))?; 94 fmt::fprint(ctx.out, "// No exported declarations")?; 95 if (!no_color) fmt::fprint(ctx.out, "\x1b[m")?; 96 fmt::fprintln(ctx.out)?; 97 }; 98 }; 99 100 fn emit_submodules_tty(ctx: *context) (void | error) = { 101 if (len(ctx.submods) != 0) { 102 if (!firstline) { 103 fmt::fprintln(ctx.out)?; 104 }; 105 firstline = false; 106 if (!no_color) fmt::fprintf(ctx.out, "\x1b[{}m", 107 color(unparse::synkind::COMMENT))?; 108 if (len(ctx.ident) == 0) { 109 fmt::fprintln(ctx.out, "// Modules")?; 110 } else { 111 fmt::fprintln(ctx.out, "// Submodules")?; 112 }; 113 for (let submodule .. ctx.submods) { 114 let submodule = if (len(ctx.ident) != 0) { 115 const s = unparse::identstr(ctx.ident); 116 defer free(s); 117 yield strings::concat(s, "::", submodule); 118 } else { 119 yield strings::dup(submodule); 120 }; 121 defer free(submodule); 122 123 fmt::fprintfln(ctx.out, "// - [[{}]]", submodule)?; 124 }; 125 }; 126 }; 127 128 fn details_tty(ctx: *context, decl: *ast::decl) (bool | error) = { 129 if (len(decl.docs) == 0 && !ctx.show_undocumented) { 130 return false; 131 }; 132 133 if (!no_color) fmt::fprint(ctx.out, "\x1b[m")?; // reset styling 134 if (!firstline) { 135 fmt::fprintln(ctx.out)?; 136 }; 137 firstline = false; 138 139 unparse::decl(ctx.out, &syn_tty, decl)?; 140 fmt::fprintln(ctx.out)?; 141 return true; 142 }; 143 144 fn syn_tty( 145 ctx: *unparse::context, 146 s: str, 147 kind: unparse::synkind, 148 ) (size | io::error) = { 149 let z = 0z; 150 if (!no_color) z += fmt::fprintf(ctx.out, "\x1b[{}m", color(kind))?; 151 z += unparse::syn_wrap(ctx, s, kind)?; 152 if (!no_color) z += fmt::fprint(ctx.out, "\x1b[m")?; 153 return z; 154 };