/** * Prompt Preview - Shows a live preview of the custom terminal prompt */ import type { ReactNode } from 'react'; import { cn } from '@/lib/utils'; import type { ThemeMode } from '@automaker/types'; import { getTerminalTheme } from '@/config/terminal-themes'; interface PromptPreviewProps { format: 'standard' | 'minimal' | 'powerline' | 'starship'; theme: ThemeMode; showGitBranch: boolean; showGitStatus: boolean; showUserHost: boolean; showPath: boolean; pathStyle: 'full' | 'short' | 'basename'; pathDepth: number; showTime: boolean; showExitStatus: boolean; isOmpTheme?: boolean; promptThemeLabel?: string; className?: string; } export function PromptPreview({ format, theme, showGitBranch, showGitStatus, showUserHost, showPath, pathStyle, pathDepth, showTime, showExitStatus, isOmpTheme = false, promptThemeLabel, className, }: PromptPreviewProps) { const terminalTheme = getTerminalTheme(theme); const formatPath = (inputPath: string) => { let displayPath = inputPath; let prefix = ''; if (displayPath.startsWith('~/')) { prefix = '~/'; displayPath = displayPath.slice(2); } else if (displayPath.startsWith('/')) { prefix = '/'; displayPath = displayPath.slice(1); } const segments = displayPath.split('/').filter((segment) => segment.length > 0); const depth = Math.max(0, pathDepth); const trimmedSegments = depth > 0 ? segments.slice(-depth) : segments; let formattedSegments = trimmedSegments; if (pathStyle === 'basename' && trimmedSegments.length > 0) { formattedSegments = [trimmedSegments[trimmedSegments.length - 1]]; } else if (pathStyle === 'short') { formattedSegments = trimmedSegments.map((segment, index) => { if (index < trimmedSegments.length - 1) { return segment.slice(0, 1); } return segment; }); } const joined = formattedSegments.join('/'); if (prefix === '/' && joined.length === 0) { return '/'; } if (prefix === '~/' && joined.length === 0) { return '~'; } return `${prefix}${joined}`; }; // Generate preview text based on format const renderPrompt = () => { if (isOmpTheme) { return (
{promptThemeLabel ?? 'Oh My Posh theme'}
Rendered by the oh-my-posh CLI in the terminal.
Preview here stays generic to avoid misleading output.
); } const user = 'user'; const host = 'automaker'; const path = formatPath('~/projects/automaker'); const branch = showGitBranch ? 'main' : null; const dirty = showGitStatus && showGitBranch ? '*' : ''; const time = showTime ? '[14:32]' : ''; const status = showExitStatus ? '✗ 1' : ''; const gitInfo = branch ? ` (${branch}${dirty})` : ''; switch (format) { case 'minimal': { return (
{showTime && {time} } {showUserHost && ( {user} @ {host}{' '} )} {showPath && {path}} {gitInfo && {gitInfo}} {showExitStatus && {status}} $
); } case 'powerline': { const powerlineSegments: ReactNode[] = []; if (showUserHost) { powerlineSegments.push( [{user} @ {host}] ); } if (showPath) { powerlineSegments.push( [{path}] ); } const powerlineCore = powerlineSegments.flatMap((segment, index) => index === 0 ? [segment] : [ , segment, ] ); const powerlineExtras: ReactNode[] = []; if (gitInfo) { powerlineExtras.push( {gitInfo} ); } if (showTime) { powerlineExtras.push( {time} ); } if (showExitStatus) { powerlineExtras.push( {status} ); } const powerlineLine: ReactNode[] = [...powerlineCore]; if (powerlineExtras.length > 0) { if (powerlineLine.length > 0) { powerlineLine.push(' '); } powerlineLine.push(...powerlineExtras); } return (
┌─ {powerlineLine}
└─ $
); } case 'starship': { return (
{showTime && {time} } {showUserHost && ( <> {user} @ {host} )} {showPath && ( <> in {path} )} {branch && ( <> on {branch} {dirty} )} {showExitStatus && {status}}
); } case 'standard': default: { return (
{showTime && {time} } {showUserHost && ( <> [{user} @ {host} ] )} {showPath && {path}} {gitInfo && {gitInfo}} {showExitStatus && {status}} $
); } } }; return (
Preview
{renderPrompt()}
); }