hare

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

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 };