From a706de8b75f1ada1ab4bc18be933f7906f6ccc23 Mon Sep 17 00:00:00 2001 From: Paul Valladares Date: Tue, 21 Jul 2026 17:05:07 -0600 Subject: [PATCH] feat: colorize help output --- src/cli.ts | 25 +++++++++++++++++++++++-- src/tui/board.ts | 3 ++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/cli.ts b/src/cli.ts index f5ba466..e122d77 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -1,5 +1,6 @@ #!/usr/bin/env node import { readFileSync } from "node:fs"; +import { styleText } from "node:util"; import { parse } from "@bomb.sh/args"; import { animateBanner } from "./banner.js"; @@ -23,6 +24,26 @@ const usage = `usage: fid --version print the version `; +// colors go in after the columns are padded, so alignment math never sees ansi +const colorUsage = (s: string) => + s + .split("\n") + .map((line) => { + if (line === "usage:") return styleText("dim", line); + const m = /^(\s+)(\S.*?)(\s{2,})(.*)$/.exec(line); + if (!m) return line; + const [, indent, left, gap, desc] = m; + const colored = left + .replace( + /^fid (?!--)(\S+)/, + (_, cmd: string) => `fid ${styleText(["green", "bold"], cmd)}`, + ) + .replace(/--[\w-]+/g, (f) => styleText("cyan", f)) + .replace(/<[^>]+>/g, (a) => styleText("magenta", a)); + return indent + colored + gap + styleText("dim", desc); + }) + .join("\n"); + if (args.version) { const pkg = JSON.parse( readFileSync(new URL("../package.json", import.meta.url), "utf8"), @@ -36,7 +57,7 @@ const [command] = args._; if (!args.json && command !== "watch") await animateBanner(); if (args.help || !command) { - console.log(usage); + console.log(colorUsage(usage)); process.exit(command ? 0 : 1); } @@ -64,6 +85,6 @@ switch (command) { break; default: console.error(`unknown command: ${command}\n`); - console.log(usage); + console.log(colorUsage(usage)); process.exit(1); } diff --git a/src/tui/board.ts b/src/tui/board.ts index c54ccb1..f4df323 100644 --- a/src/tui/board.ts +++ b/src/tui/board.ts @@ -142,7 +142,8 @@ export function buildOps( .entries()) { const index = state.offset + i; const selected = index === state.selected; - const flashedAgo = now - (state.changed.get(row.host) ?? Number.NEGATIVE_INFINITY); + const flashedAgo = + now - (state.changed.get(row.host) ?? Number.NEGATIVE_INFINITY); const flashing = flashedAgo < FLASH_MS; ops.push( open(`row-${row.host}`, { -- 2.51.2