import chalk from "chalk"; import type { EnrichedPlace, Place } from "../types.ts"; export function formatJson(places: readonly Place[]): string { return JSON.stringify(places, null, 2); } export function formatTable(places: readonly Place[]): string { if (places.length === 0) return chalk.yellow("No places found."); const isEnriched = "rating" in places[0]!; if (isEnriched) { return formatEnrichedTable(places as readonly EnrichedPlace[]); } return formatBasicTable(places); } function formatBasicTable(places: readonly Place[]): string { const lines: string[] = []; const header = `${chalk.bold.white(pad("Name", 40))} ${chalk.bold.white(pad("Address", 45))} ${chalk.bold.white(pad("Coordinates", 25))}`; lines.push(header); lines.push(chalk.dim("─".repeat(112))); for (const place of places) { const name = truncate(place.name, 40); const addr = truncate(place.address ?? place.fullAddress ?? "—", 45); const coords = `${place.lat.toFixed(4)}, ${place.lng.toFixed(4)}`; lines.push(`${pad(name, 40)} ${pad(addr, 45)} ${pad(coords, 25)}`); } lines.push(""); lines.push(chalk.dim(`${places.length} places`)); return lines.join("\n"); } function formatEnrichedTable(places: readonly EnrichedPlace[]): string { const lines: string[] = []; const header = `${chalk.bold.white(pad("Name", 35))} ${chalk.bold.white(pad("Rating", 8))} ${chalk.bold.white(pad("Category", 25))} ${chalk.bold.white(pad("Address", 35))}`; lines.push(header); lines.push(chalk.dim("─".repeat(105))); for (const place of places) { const name = truncate(place.name, 35); const rating = place.rating !== null ? formatRating(place.rating) : chalk.dim("—"); const category = truncate(place.categories[0] ?? "—", 25); const addr = truncate(place.address ?? "—", 35); lines.push(`${pad(name, 35)} ${pad(rating, 8)} ${pad(category, 25)} ${pad(addr, 35)}`); } lines.push(""); lines.push(chalk.dim(`${places.length} places`)); return lines.join("\n"); } function formatRating(rating: number): string { if (rating >= 4.5) return chalk.green(rating.toFixed(1).padEnd(4)); if (rating >= 4.0) return chalk.yellow(rating.toFixed(1).padEnd(4)); return chalk.red(rating.toFixed(1).padEnd(4)); } export function formatListHeader( name: string, owner: string, totalCount: number, ): string { return [ "", chalk.bold(`${name}`), chalk.dim(`by ${owner} · ${totalCount} places`), "", ].join("\n"); } function pad(str: string, width: number): string { // Strip ANSI codes for length calculation const stripped = str.replace(/\x1b\[[0-9;]*m/g, ""); if (stripped.length >= width) return str; return str + " ".repeat(width - stripped.length); } function truncate(str: string, maxLen: number): string { if (str.length <= maxLen) return str; return str.slice(0, maxLen - 1) + "…"; }