hare

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

tty.ha (4443B)


      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::lex;
      8 use hare::unparse;
      9 use io;
     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 	if (len(ctx.parse_errs) > 0) {
     42 		if (!no_color) fmt::fprintf(ctx.out, "\x1b[{}m",
     43 			color(unparse::synkind::COMMENT))?;
     44 		fmt::fprint(ctx.out, "// ")?;
     45 		if (!no_color) fmt::fprint(ctx.out, "\x1b[93m")?;
     46 		fmt::fprint(ctx.out, "WARNING")?;
     47 		if (!no_color) fmt::fprintf(ctx.out, "\x1b[m" "\x1b[{}m",
     48 			color(unparse::synkind::COMMENT))?;
     49 		fmt::fprintln(ctx.out,
     50 			": parsing errors occurred; documentation may be incomplete")?;
     51 		if (!no_color) fmt::fprint(ctx.out, "\x1b[m")?;
     52 	};
     53 	for (let i = 0z; i < len(ctx.parse_errs); i += 1) {
     54 		fmt::fprintln(ctx.out, "//", lex::strerror(ctx.parse_errs[i]))?;
     55 	};
     56 	if (len(ctx.parse_errs) > 0) {
     57 		fmt::fprintln(ctx.out)?;
     58 	};
     59 
     60 	match (ctx.readme) {
     61 	case let readme: io::file =>
     62 		let rbuf: [os::BUFSZ]u8 = [0...];
     63 		let readme = bufio::init(readme, rbuf, []);
     64 		let sc = bufio::newscanner(&readme);
     65 		defer bufio::finish(&sc);
     66 		for (let line => bufio::scan_line(&sc)?) {
     67 			firstline = false;
     68 			if (!no_color) fmt::fprintf(ctx.out, "\x1b[{}m",
     69 				color(unparse::synkind::COMMENT))?;
     70 			fmt::fprint(ctx.out, "//", line)?;
     71 			if (!no_color) fmt::fprint(ctx.out, "\x1b[m")?;
     72 			fmt::fprintln(ctx.out)?;
     73 		};
     74 	case void => void;
     75 	};
     76 
     77 	emit_submodules_tty(ctx)?;
     78 
     79 	// XXX: Should we emit the dependencies, too?
     80 	let printed = false;
     81 	for (let t &.. summary.types) {
     82 		if (details_tty(ctx, t)?) {
     83 			printed = true;
     84 		};
     85 	};
     86 	for (let c &.. summary.constants) {
     87 		if (details_tty(ctx, c)?) {
     88 			printed = true;
     89 		};
     90 	};
     91 	for (let e &.. summary.errors) {
     92 		if (details_tty(ctx, e)?) {
     93 			printed = true;
     94 		};
     95 	};
     96 	for (let g &.. summary.globals) {
     97 		if (details_tty(ctx, g)?) {
     98 			printed = true;
     99 		};
    100 	};
    101 	for (let f &.. summary.funcs) {
    102 		if (details_tty(ctx, f)?) {
    103 			printed = true;
    104 		};
    105 	};
    106 
    107 	if (!printed) {
    108 		if (!firstline) {
    109 			fmt::fprintln(ctx.out)?;
    110 		};
    111 		if (!no_color) fmt::fprintf(ctx.out, "\x1b[{}m",
    112 			color(unparse::synkind::COMMENT))?;
    113 		fmt::fprint(ctx.out, "// No exported declarations")?;
    114 		if (!no_color) fmt::fprint(ctx.out, "\x1b[m")?;
    115 		fmt::fprintln(ctx.out)?;
    116 	};
    117 };
    118 
    119 fn emit_submodules_tty(ctx: *context) (void | error) = {
    120 	if (len(ctx.submods) != 0) {
    121 		if (!firstline) {
    122 			fmt::fprintln(ctx.out)?;
    123 		};
    124 		firstline = false;
    125 		if (!no_color) fmt::fprintf(ctx.out, "\x1b[{}m",
    126 			color(unparse::synkind::COMMENT))?;
    127 		if (len(ctx.ident) == 0) {
    128 			fmt::fprintln(ctx.out, "// Modules")?;
    129 		} else {
    130 			fmt::fprintln(ctx.out, "// Submodules")?;
    131 		};
    132 		for (let submodule .. ctx.submods) {
    133 			let submodule = if (len(ctx.ident) != 0) {
    134 				const s = unparse::identstr(ctx.ident);
    135 				defer free(s);
    136 				yield strings::concat(s, "::", submodule);
    137 			} else {
    138 				yield strings::dup(submodule);
    139 			};
    140 			defer free(submodule);
    141 
    142 			fmt::fprintfln(ctx.out, "// - [[{}::]]", submodule)?;
    143 		};
    144 	};
    145 };
    146 
    147 fn details_tty(ctx: *context, decl: *ast::decl) (bool | error) = {
    148 	if (len(decl.docs) == 0 && !ctx.show_undocumented) {
    149 		return false;
    150 	};
    151 
    152 	if (!no_color) fmt::fprint(ctx.out, "\x1b[m")?; // reset styling
    153 	if (!firstline) {
    154 		fmt::fprintln(ctx.out)?;
    155 	};
    156 	firstline = false;
    157 
    158 	unparse::decl(ctx.out, &syn_tty, decl)?;
    159 	fmt::fprintln(ctx.out)?;
    160 	return true;
    161 };
    162 
    163 fn syn_tty(
    164 	ctx: *unparse::context,
    165 	s: str,
    166 	kind: unparse::synkind,
    167 ) (size | io::error) = {
    168 	let z = 0z;
    169 	if (!no_color) z += fmt::fprintf(ctx.out, "\x1b[{}m", color(kind))?;
    170 	z += unparse::syn_wrap(ctx, s, kind)?;
    171 	if (!no_color) z += fmt::fprint(ctx.out, "\x1b[m")?;
    172 	return z;
    173 };