const RESET = '\x1b[0m' const BOLD = '\x1b[1m' const DIM = '\x1b[2m' const BRAND_BLUE = '\x1b[38;2;42;95;255m' const GREEN = '\x1b[38;5;84m' const RED = '\x1b[38;5;203m' function paint(code: string, value: string): string { if (!process.stdout.isTTY || process.env.NO_COLOR !== undefined) return value return `${code}${value}${RESET}` } export function accent(value: string): string { return paint(BRAND_BLUE, value) } export function bold(value: string): string { return paint(BOLD, value) } export function muted(value: string): string { return paint(DIM, value) } export function success(value: string): string { return paint(GREEN, value) } export function failure(value: string): string { return paint(RED, value) } export function printBrand(subtitle?: string): void { console.log() console.log(` ${accent('◤◢')} ${bold('rnx')}`) if (subtitle) console.log(` ${muted(subtitle)}`) } export function printPromptBlock(title: string, description: string[]): void { console.log(`\n ${accent('◆')} ${bold(title)}`) for (const line of description) console.log(` ${muted(line)}`) } export async function withSpinner(label: string, run: () => Promise): Promise { if (!process.stdout.isTTY) { console.log(` ${label}...`) return run() } const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'] let index = 0 const draw = () => { process.stdout.write(`\r\x1b[2K ${accent(frames[index++ % frames.length])} ${label}`) } draw() const timer = setInterval(draw, 80) try { const result = await run() clearInterval(timer) process.stdout.write(`\r\x1b[2K ${success('✓')} ${label}\n`) return result } catch (error) { clearInterval(timer) process.stdout.write(`\r\x1b[2K ${failure('×')} ${label}\n`) throw error } }