viewMarkdown

tcmts.cli.mcp.viewMarkdown · #fjafxber · term · runs anywhere

tcm view's output as Markdown, for clients that render it: what it said first (the names it didn't find), then for each definition a line with its names, hash and where it runs, and its code (or a file's content) as a highlighted block.

import { fence, LANG } from "#codebase/tcmts/cli/mcp";

export function viewMarkdown(out: string): string {
  const header = /^\/\/ (\S+(?:, \S+)*) (#[a-z2-7]{8,}) ?(.*)$/;
  const before: string[] = [];
  const blocks: { names: string; hash: string; rest: string; lines: string[] }[] = [];
  // (said on stderr, so it may come in among the code)
  const said = /^'[^']+' (not found|is a namespace, not a definition)/;
  for (const line of out.split("\n")) {
    const m = header.exec(line);
    if (m) blocks.push({ names: m[1]!, hash: m[2]!, rest: m[3]!, lines: [] });
    else if (said.test(line) || (!blocks.length && line.trim())) before.push(line);
    else if (blocks.length) blocks.at(-1)!.lines.push(line);
  }
  if (!blocks.length) return out;
  return [
    ...(before.length ? [before.join("\n")] : []),
    ...blocks.map((b) => {
      while (b.lines.length && !b.lines.at(-1)!.trim()) b.lines.pop();
      // code says its type after a colon; a file, its format
      const file = !b.rest.startsWith(":");
      const runs =
        !file && b.lines[0]?.startsWith("// runs ") ? b.lines.shift()!.slice(3) : undefined;
      const about = file ? `${b.rest || "text"} file` : runs;
      return `**${b.names}** \`${b.hash}\`${about ? ` · ${about}` : ""}\n\n${fence(b.lines.join("\n"), file ? (LANG[b.rest] ?? "") : "ts")}`;
    }),
  ].join("\n\n");
}

uses

used by