hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit a6931bcc11f490b39142c2d31d2d33cb9264f1b8
parent 9acf605c7d172a4017cf5022b6a5d7f9232e2896
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu,  4 Nov 2021 10:29:41 +0100

cmd/haredoc: add 'out' to context

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Mcmd/haredoc/hare.ha | 19++++++++++---------
Mcmd/haredoc/html.ha | 176++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Mcmd/haredoc/main.ha | 13++++++++-----
Mcmd/haredoc/tty.ha | 11++++++-----
4 files changed, 117 insertions(+), 102 deletions(-)

diff --git a/cmd/haredoc/hare.ha b/cmd/haredoc/hare.ha @@ -20,7 +20,8 @@ fn emit_hare(ctx: *context) (void | error) = { match (bufio::scanline(readme)?) { case io::EOF => break; case b: []u8 => - fmt::printfln("// {}", strings::fromutf8(b))?; + fmt::fprintfln(ctx.out, + "// {}", strings::fromutf8(b))?; free(b); }; }; @@ -30,35 +31,35 @@ fn emit_hare(ctx: *context) (void | error) = { // XXX: Should we emit the dependencies, too? for (let i = 0z; i < len(summary.types); i += 1) { if (!first) { - fmt::println()?; + fmt::fprintln(ctx.out)?; }; first = false; details_hare(ctx, summary.types[i])?; }; for (let i = 0z; i < len(summary.constants); i += 1) { if (!first) { - fmt::println()?; + fmt::fprintln(ctx.out)?; }; first = false; details_hare(ctx, summary.constants[i])?; }; for (let i = 0z; i < len(summary.errors); i += 1) { if (!first) { - fmt::println()?; + fmt::fprintln(ctx.out)?; }; first = false; details_hare(ctx, summary.errors[i])?; }; for (let i = 0z; i < len(summary.globals); i += 1) { if (!first) { - fmt::println()?; + fmt::fprintln(ctx.out)?; }; first = false; details_hare(ctx, summary.globals[i])?; }; for (let i = 0z; i < len(summary.funcs); i += 1) { if (!first) { - fmt::println()?; + fmt::fprintln(ctx.out)?; }; first = false; details_hare(ctx, summary.funcs[i])?; @@ -76,13 +77,13 @@ fn details_hare(ctx: *context, decl: ast::decl) (void | error) = { case void => break; case s: str => if (len(s) != 0) { - fmt::printfln("//{}", s)?; + fmt::fprintfln(ctx.out, "//{}", s)?; }; }; }; - unparse_hare(os::stdout, decl)?; - fmt::println()?; + unparse_hare(ctx.out, decl)?; + fmt::fprintln(ctx.out)?; return; }; diff --git a/cmd/haredoc/html.ha b/cmd/haredoc/html.ha @@ -66,9 +66,13 @@ fn emit_html(ctx: *context) (void | error) = { if (ctx.template) head(ctx.ident)?; if (len(ident) == 0) { - fmt::printf("<h2>The Hare standard library <span class='heading-extra'>", ident)?; + fmt::fprintf(ctx.out, + "<h2>The Hare standard library <span class='heading-extra'>", + ident)?; } else { - fmt::printf("<h2>{} <span class='heading-extra'>", ident)?; + fmt::fprintf(ctx.out, + "<h2>{} <span class='heading-extra'>", + ident)?; }; for (let i = 0z; i < len(ctx.tags); i += 1) { const mode = switch (ctx.tags[i].mode) { @@ -77,26 +81,26 @@ fn emit_html(ctx: *context) (void | error) = { case module::tag_mode::EXCLUSIVE => yield '-'; }; - fmt::printf("{}{} ", mode, ctx.tags[i].name)?; + fmt::fprintf(ctx.out, "{}{} ", mode, ctx.tags[i].name)?; }; - fmt::println("</span></h2>")?; + fmt::fprintln(ctx.out, "</span></h2>")?; match (ctx.readme) { case void => void; case f: io::file => - fmt::println("<div class='readme'>")?; + fmt::fprintln(ctx.out, "<div class='readme'>")?; markup_html(ctx, f)?; - fmt::println("</div>")?; + fmt::fprintln(ctx.out, "</div>")?; }; if (len(ctx.version.subdirs) != 0) { // TODO: Verify that these are actually modules if (len(ctx.ident) == 0) { - fmt::println("<h3>Modules</h3>")?; + fmt::fprintln(ctx.out, "<h3>Modules</h3>")?; } else { - fmt::println("<h3>Submodules</h3>")?; + fmt::fprintln(ctx.out, "<h3>Submodules</h3>")?; }; - fmt::println("<ul class='submodules'>")?; + fmt::fprintln(ctx.out, "<ul class='submodules'>")?; for (let i = 0z; i < len(ctx.version.subdirs); i += 1) { let dir = ctx.version.subdirs[i]; if (dir == "cmd") continue; @@ -108,13 +112,13 @@ fn emit_html(ctx: *context) (void | error) = { let path = path::join("/", path, dir); defer free(path); - fmt::printf("<li><a href='")?; - html_escape(os::stdout, path)?; - fmt::printf("'>")?; - html_escape(os::stdout, dir)?; - fmt::printfln("</a></li>")?; + fmt::fprintf(ctx.out, "<li><a href='")?; + html_escape(ctx.out, path)?; + fmt::fprintf(ctx.out, "'>")?; + html_escape(ctx.out, dir)?; + fmt::fprintfln(ctx.out, "</a></li>")?; }; - fmt::println("</ul>")?; + fmt::fprintln(ctx.out, "</ul>")?; }; if (len(decls.types) == 0 @@ -125,72 +129,78 @@ fn emit_html(ctx: *context) (void | error) = { return; }; - fmt::println("<h3>Index</h3>")?; - tocentries(decls.types, "Types", "types")?; - tocentries(decls.errors, "Errors", "Errors")?; - tocentries(decls.constants, "Constants", "constants")?; - tocentries(decls.globals, "Globals", "globals")?; - tocentries(decls.funcs, "Functions", "functions")?; + fmt::fprintln(ctx.out, "<h3>Index</h3>")?; + tocentries(ctx.out, decls.types, "Types", "types")?; + tocentries(ctx.out, decls.errors, "Errors", "Errors")?; + tocentries(ctx.out, decls.constants, "Constants", "constants")?; + tocentries(ctx.out, decls.globals, "Globals", "globals")?; + tocentries(ctx.out, decls.funcs, "Functions", "functions")?; if (len(decls.types) != 0) { - fmt::println("<h3>Types</h3>")?; + fmt::fprintln(ctx.out, "<h3>Types</h3>")?; for (let i = 0z; i < len(decls.types); i += 1) { details(ctx, decls.types[i])?; }; }; if (len(decls.errors) != 0) { - fmt::println("<h3>Errors</h3>")?; + fmt::fprintln(ctx.out, "<h3>Errors</h3>")?; for (let i = 0z; i < len(decls.errors); i += 1) { details(ctx, decls.errors[i])?; }; }; if (len(decls.constants) != 0) { - fmt::println("<h3>Constants</h3>")?; + fmt::fprintln(ctx.out, "<h3>Constants</h3>")?; for (let i = 0z; i < len(decls.constants); i += 1) { details(ctx, decls.constants[i])?; }; }; if (len(decls.globals) != 0) { - fmt::println("<h3>Globals</h3>")?; + fmt::fprintln(ctx.out, "<h3>Globals</h3>")?; for (let i = 0z; i < len(decls.globals); i += 1) { details(ctx, decls.globals[i])?; }; }; if (len(decls.funcs) != 0) { - fmt::println("<h3>Functions</h3>")?; + fmt::fprintln(ctx.out, "<h3>Functions</h3>")?; for (let i = 0z; i < len(decls.funcs); i += 1) { details(ctx, decls.funcs[i])?; }; }; }; -fn tocentries(decls: []ast::decl, name: str, lname: str) (void | error) = { +fn tocentries( + out: io::handle, + decls: []ast::decl, + name: str, + lname: str, +) (void | error) = { if (len(decls) == 0) { return; }; - fmt::printfln("<h4>{}</h4>", name)?; - fmt::println("<pre>")?; + fmt::fprintfln(out, "<h4>{}</h4>", name)?; + fmt::fprintln(out, "<pre>")?; let undoc = false; for (let i = 0z; i < len(decls); i += 1) { if (!undoc && decls[i].docs == "") { - fmt::printfln( + fmt::fprintfln( + out, "{}<span style='color: #444'>// Undocumented {}:</span>", if (i == 0) "" else "\n", lname)?; undoc = true; }; - tocentry(decls[i])?; + tocentry(out, decls[i])?; }; - fmt::print("</pre>")?; + fmt::fprint(out, "</pre>")?; return; }; -fn tocentry(decl: ast::decl) (void | error) = { - fmt::printf("{} ", +fn tocentry(out: io::handle, decl: ast::decl) (void | error) = { + fmt::fprintf(out, "{} ", match (decl.decl) { case ast::decl_func => yield "fn"; @@ -201,37 +211,37 @@ fn tocentry(decl: ast::decl) (void | error) = { case []ast::decl_global => yield "let"; })?; - fmt::printf("<a href='#")?; - unparse::ident(os::stdout, decl_ident(decl))?; - fmt::printf("'>")?; - unparse::ident(os::stdout, decl_ident(decl))?; - fmt::print("</a>")?; + fmt::fprintf(out, "<a href='#")?; + unparse::ident(out, decl_ident(decl))?; + fmt::fprintf(out, "'>")?; + unparse::ident(out, decl_ident(decl))?; + fmt::fprint(out, "</a>")?; match (decl.decl) { case t: []ast::decl_type => void; case g: []ast::decl_global => let g = g[0]; - fmt::print(": ")?; - type_html(os::stdout, 0, g._type, true)?; + fmt::fprint(out, ": ")?; + type_html(out, 0, g._type, true)?; case c: []ast::decl_const => let c = c[0]; - fmt::print(": ")?; - type_html(os::stdout, 0, c._type, true)?; + fmt::fprint(out, ": ")?; + type_html(out, 0, c._type, true)?; case f: ast::decl_func => - prototype_html(os::stdout, 0, + prototype_html(out, 0, f.prototype.repr as ast::func_type, true)?; }; - fmt::println(";")?; + fmt::fprintln(out, ";")?; return; }; fn details(ctx: *context, decl: ast::decl) (void | error) = { - fmt::println("<section class='member'>")?; - fmt::print("<h4 id='")?; - unparse::ident(os::stdout, decl_ident(decl))?; - fmt::print("'>")?; - fmt::printf("{} ", match (decl.decl) { + fmt::fprintln(ctx.out, "<section class='member'>")?; + fmt::fprint(ctx.out, "<h4 id='")?; + unparse::ident(ctx.out, decl_ident(decl))?; + fmt::fprint(ctx.out, "'>")?; + fmt::fprintf(ctx.out, "{} ", match (decl.decl) { case ast::decl_func => yield "fn"; case []ast::decl_type => @@ -241,31 +251,31 @@ fn details(ctx: *context, decl: ast::decl) (void | error) = { case []ast::decl_global => yield "let"; })?; - unparse::ident(os::stdout, decl_ident(decl))?; + unparse::ident(ctx.out, decl_ident(decl))?; // TODO: Add source URL - fmt::print("<span class='heading-extra'><a href='#")?; - unparse::ident(os::stdout, decl_ident(decl))?; - fmt::print("'>[link]</a> + fmt::fprint(ctx.out, "<span class='heading-extra'><a href='#")?; + unparse::ident(ctx.out, decl_ident(decl))?; + fmt::fprint(ctx.out, "'>[link]</a> </span>")?; - fmt::println("</h4>")?; + fmt::fprintln(ctx.out, "</h4>")?; if (len(decl.docs) == 0) { - fmt::println("<details>")?; - fmt::println("<summary>Show undocumented member</summary>")?; + fmt::fprintln(ctx.out, "<details>")?; + fmt::fprintln(ctx.out, "<summary>Show undocumented member</summary>")?; }; - fmt::println("<pre class='decl'>")?; - unparse_html(os::stdout, decl)?; - fmt::println("</pre>")?; + fmt::fprintln(ctx.out, "<pre class='decl'>")?; + unparse_html(ctx.out, decl)?; + fmt::fprintln(ctx.out, "</pre>")?; if (len(decl.docs) != 0) { const buf = strings::toutf8(decl.docs); markup_html(ctx, bufio::fixed(buf, io::mode::READ))?; } else { - fmt::println("</details>")?; + fmt::fprintln(ctx.out, "</details>")?; }; - fmt::println("</section>")?; + fmt::fprintln(ctx.out, "</section>")?; return; }; @@ -277,7 +287,7 @@ fn htmlref(ctx: *context, ref: ast::ident) (void | io::error) = { case void => const ident = unparse::identstr(ref); fmt::errorfln("Warning: Unresolved reference: {}", ident)?; - fmt::printf("<a href='#' " + fmt::fprintf(ctx.out, "<a href='#' " "class='ref invalid' " "title='This reference could not be found'>{}</a>", ident)?; @@ -290,16 +300,16 @@ fn htmlref(ctx: *context, ref: ast::ident) (void | io::error) = { const ident = unparse::identstr(id); switch (kind) { case symkind::LOCAL => - fmt::printf("<a href='#{0}' class='ref'>{0}</a>", ident)?; + fmt::fprintf(ctx.out, "<a href='#{0}' class='ref'>{0}</a>", ident)?; case symkind::MODULE => let ipath = module::identpath(id); defer free(ipath); - fmt::printf("<a href='/{}' class='ref'>{}</a>", + fmt::fprintf(ctx.out, "<a href='/{}' class='ref'>{}</a>", ipath, ident)?; case symkind::SYMBOL => let ipath = module::identpath(id[..len(id) - 1]); defer free(ipath); - fmt::printf("<a href='/{}#{}' class='ref'>{}</a>", + fmt::fprintf(ctx.out, "<a href='/{}#{}' class='ref'>{}</a>", ipath, id[len(id) - 1], ident)?; }; free(ident); @@ -315,39 +325,39 @@ fn markup_html(ctx: *context, in: io::handle) (void | io::error) = { }; match (tok) { case paragraph => - fmt::println()?; - fmt::print("<p>")?; + fmt::fprintln(ctx.out)?; + fmt::fprint(ctx.out, "<p>")?; case tx: text => if (strings::has_prefix(tx, "https://")) { // Temporary hack - fmt::print("<a rel='nofollow noopener' href='")?; - html_escape(os::stdout, tx)?; - fmt::print("'>")?; - html_escape(os::stdout, tx)?; - fmt::print("</a>")?; + fmt::fprint(ctx.out, "<a rel='nofollow noopener' href='")?; + html_escape(ctx.out, tx)?; + fmt::fprint(ctx.out, "'>")?; + html_escape(ctx.out, tx)?; + fmt::fprint(ctx.out, "</a>")?; free(tx); } else { - html_escape(os::stdout, tx)?; + html_escape(ctx.out, tx)?; free(tx); }; case re: reference => htmlref(ctx, re)?; case sa: sample => - fmt::print("<pre class='sample'>")?; - html_escape(os::stdout, sa)?; - fmt::print("</pre>")?; + fmt::fprint(ctx.out, "<pre class='sample'>")?; + html_escape(ctx.out, sa)?; + fmt::fprint(ctx.out, "</pre>")?; free(sa); case li: list => - fmt::println("<ul>")?; + fmt::fprintln(ctx.out, "<ul>")?; for (let i = 0z; i < len(li); i += 1) { - fmt::println("<li>")?; - html_escape(os::stdout, li[i])?; - fmt::println("</li>")?; + fmt::fprintln(ctx.out, "<li>")?; + html_escape(ctx.out, li[i])?; + fmt::fprintln(ctx.out, "</li>")?; }; - fmt::println("</ul>")?; + fmt::fprintln(ctx.out, "</ul>")?; }; }; - fmt::println()?; + fmt::fprintln(ctx.out)?; return; }; diff --git a/cmd/haredoc/main.ha b/cmd/haredoc/main.ha @@ -29,14 +29,15 @@ type context = struct { template: bool, show_undocumented: bool, readme: (io::file | void), + out: io::handle, }; export fn main() void = { - let fmt = - if (tty::isatty(os::stdout_file)) - format::TTY - else - format::HARE; + let fmt = if (tty::isatty(os::stdout_file)) { + yield format::TTY; + } else { + yield format::HARE; + }; let template = true; let show_undocumented = false; const help: [_]getopt::help = [ @@ -175,7 +176,9 @@ export fn main() void = { template = template, readme = readme, show_undocumented = show_undocumented, + out = os::stdout, }; + match (emit(&ctx)) { case void => void; case err: error => diff --git a/cmd/haredoc/tty.ha b/cmd/haredoc/tty.ha @@ -21,7 +21,7 @@ fn emit_tty(ctx: *context) (void | error) = { case io::EOF => break; case b: []u8 => firstline = false; - fmt::printfln( + fmt::fprintfln(ctx.out, "\x1b[1m" "// {}" "\x1b[0m", strings::fromutf8(b))?; free(b); @@ -67,7 +67,7 @@ fn details_tty(ctx: *context, decl: ast::decl) (void | error) = { }; if (!firstline) { - fmt::println()?; + fmt::fprintln(ctx.out)?; }; firstline = false; @@ -76,14 +76,15 @@ fn details_tty(ctx: *context, decl: ast::decl) (void | error) = { match (strings::next_token(&iter)) { case s: str => if (!(strings::peek_token(&iter) is void)) { - fmt::printfln("\x1b[1m" "//{}" "\x1b[0m", s)?; + fmt::fprintfln(ctx.out, + "\x1b[1m" "//{}" "\x1b[0m", s)?; }; case void => break; }; }; - unparse_tty(os::stdout, decl)?; - fmt::println()?; + unparse_tty(ctx.out, decl)?; + fmt::fprintln(ctx.out)?; return; };