From ec6bf41efe9199714ae24edec65535308b0aca59 Mon Sep 17 00:00:00 2001 From: Matthew Breedlove Date: Fri, 8 Aug 2025 22:02:30 -0400 Subject: [PATCH] Add raw value mode for items --- src/ccstatusline.ts | 33 ++++++++++++++++++++---------- src/config.ts | 1 + src/tui.tsx | 50 ++++++++++++++++++++++++++++++++------------- 3 files changed, 59 insertions(+), 25 deletions(-) diff --git a/src/ccstatusline.ts b/src/ccstatusline.ts index 652f7f0..7f0cc42 100644 --- a/src/ccstatusline.ts +++ b/src/ccstatusline.ts @@ -326,7 +326,8 @@ function renderSingleLine(items: StatusItem[], settings: any, data: StatusJSON, case 'model': if (data.model) { const color = (chalk as any)[item.color || settings.colors.model] || chalk.cyan; - elements.push({ content: color(`Model: ${data.model.display_name}`), type: 'model' }); + const text = item.rawValue ? data.model.display_name : `Model: ${data.model.display_name}`; + elements.push({ content: color(text), type: 'model' }); } break; @@ -334,7 +335,8 @@ function renderSingleLine(items: StatusItem[], settings: any, data: StatusJSON, const branch = getGitBranch(); if (branch) { const color = (chalk as any)[item.color || settings.colors.gitBranch] || chalk.magenta; - elements.push({ content: color(`⎇ ${branch}`), type: 'git-branch' }); + const text = item.rawValue ? branch : `⎇ ${branch}`; + elements.push({ content: color(text), type: 'git-branch' }); } break; @@ -351,35 +353,40 @@ function renderSingleLine(items: StatusItem[], settings: any, data: StatusJSON, case 'tokens-input': if (tokenMetrics) { const color = (chalk as any)[item.color || 'yellow'] || chalk.yellow; - elements.push({ content: color(`In: ${formatTokens(tokenMetrics.inputTokens)}`), type: 'tokens-input' }); + const text = item.rawValue ? formatTokens(tokenMetrics.inputTokens) : `In: ${formatTokens(tokenMetrics.inputTokens)}`; + elements.push({ content: color(text), type: 'tokens-input' }); } break; case 'tokens-output': if (tokenMetrics) { const color = (chalk as any)[item.color || 'green'] || chalk.green; - elements.push({ content: color(`Out: ${formatTokens(tokenMetrics.outputTokens)}`), type: 'tokens-output' }); + const text = item.rawValue ? formatTokens(tokenMetrics.outputTokens) : `Out: ${formatTokens(tokenMetrics.outputTokens)}`; + elements.push({ content: color(text), type: 'tokens-output' }); } break; case 'tokens-cached': if (tokenMetrics) { const color = (chalk as any)[item.color || 'blue'] || chalk.blue; - elements.push({ content: color(`Cached: ${formatTokens(tokenMetrics.cachedTokens)}`), type: 'tokens-cached' }); + const text = item.rawValue ? formatTokens(tokenMetrics.cachedTokens) : `Cached: ${formatTokens(tokenMetrics.cachedTokens)}`; + elements.push({ content: color(text), type: 'tokens-cached' }); } break; case 'tokens-total': if (tokenMetrics) { const color = (chalk as any)[item.color || 'white'] || chalk.white; - elements.push({ content: color(`Total: ${formatTokens(tokenMetrics.totalTokens)}`), type: 'tokens-total' }); + const text = item.rawValue ? formatTokens(tokenMetrics.totalTokens) : `Total: ${formatTokens(tokenMetrics.totalTokens)}`; + elements.push({ content: color(text), type: 'tokens-total' }); } break; case 'context-length': if (tokenMetrics) { const color = (chalk as any)[item.color || 'cyan'] || chalk.cyan; - elements.push({ content: color(`Ctx: ${formatTokens(tokenMetrics.contextLength)}`), type: 'context-length' }); + const text = item.rawValue ? formatTokens(tokenMetrics.contextLength) : `Ctx: ${formatTokens(tokenMetrics.contextLength)}`; + elements.push({ content: color(text), type: 'context-length' }); } break; @@ -387,7 +394,8 @@ function renderSingleLine(items: StatusItem[], settings: any, data: StatusJSON, if (tokenMetrics) { const percentage = Math.min(100, (tokenMetrics.contextLength / 200000) * 100); const color = (chalk as any)[item.color || 'cyan'] || chalk.cyan; - elements.push({ content: color(`Ctx: ${percentage.toFixed(1)}%`), type: 'context-percentage' }); + const text = item.rawValue ? `${percentage.toFixed(1)}%` : `Ctx: ${percentage.toFixed(1)}%`; + elements.push({ content: color(text), type: 'context-percentage' }); } break; @@ -395,21 +403,24 @@ function renderSingleLine(items: StatusItem[], settings: any, data: StatusJSON, const detectedWidth = terminalWidth || getTerminalWidth(); if (detectedWidth) { const color = (chalk as any)[item.color || 'dim'] || chalk.dim; - elements.push({ content: color(`Term: ${detectedWidth}`), type: 'terminal-width' }); + const text = item.rawValue ? `${detectedWidth}` : `Term: ${detectedWidth}`; + elements.push({ content: color(text), type: 'terminal-width' }); } break; case 'session-clock': if (sessionDuration) { const color = (chalk as any)[item.color || 'blue'] || chalk.blue; - elements.push({ content: color(`Session: ${sessionDuration}`), type: 'session-clock' }); + const text = item.rawValue ? sessionDuration : `Session: ${sessionDuration}`; + elements.push({ content: color(text), type: 'session-clock' }); } break; case 'version': const versionString = data.version || 'Unknown'; const versionColor = (chalk as any)[item.color || 'green'] || chalk.green; - elements.push({ content: versionColor(`Version: ${versionString}`), type: 'version' }); + const text = item.rawValue ? versionString : `Version: ${versionString}`; + elements.push({ content: versionColor(text), type: 'version' }); break; case 'separator': diff --git a/src/config.ts b/src/config.ts index f479a3e..01636ac 100644 --- a/src/config.ts +++ b/src/config.ts @@ -16,6 +16,7 @@ export interface StatusItem { type: StatusItemType; color?: string; character?: string; // For separator and flex-separator types + rawValue?: boolean; // Show value without label prefix } export interface Settings { diff --git a/src/tui.tsx b/src/tui.tsx index f40d440..cfa5fe8 100644 --- a/src/tui.tsx +++ b/src/tui.tsx @@ -65,7 +65,7 @@ const renderSingleLine = (items: StatusItem[], terminalWidth: number, widthDetec switch (item.type) { case 'model': const modelColor = (chalk as any)[item.color || 'cyan'] || chalk.cyan; - elements.push(modelColor('Model: Claude')); + elements.push(modelColor(item.rawValue ? 'Claude' : 'Model: Claude')); break; case 'git-branch': const branchColor = (chalk as any)[item.color || 'magenta'] || chalk.magenta; @@ -77,40 +77,40 @@ const renderSingleLine = (items: StatusItem[], terminalWidth: number, widthDetec break; case 'tokens-input': const inputColor = (chalk as any)[item.color || 'yellow'] || chalk.yellow; - elements.push(inputColor('In: 15.2k')); + elements.push(inputColor(item.rawValue ? '15.2k' : 'In: 15.2k')); break; case 'tokens-output': const outputColor = (chalk as any)[item.color || 'green'] || chalk.green; - elements.push(outputColor('Out: 3.4k')); + elements.push(outputColor(item.rawValue ? '3.4k' : 'Out: 3.4k')); break; case 'tokens-cached': const cachedColor = (chalk as any)[item.color || 'blue'] || chalk.blue; - elements.push(cachedColor('Cached: 12k')); + elements.push(cachedColor(item.rawValue ? '12k' : 'Cached: 12k')); break; case 'tokens-total': const totalColor = (chalk as any)[item.color || 'white'] || chalk.white; - elements.push(totalColor('Total: 30.6k')); + elements.push(totalColor(item.rawValue ? '30.6k' : 'Total: 30.6k')); break; case 'context-length': const ctxColor = (chalk as any)[item.color || 'cyan'] || chalk.cyan; - elements.push(ctxColor('Ctx: 18.6k')); + elements.push(ctxColor(item.rawValue ? '18.6k' : 'Ctx: 18.6k')); break; case 'context-percentage': const ctxPctColor = (chalk as any)[item.color || 'cyan'] || chalk.cyan; - elements.push(ctxPctColor('Ctx: 9.3%')); + elements.push(ctxPctColor(item.rawValue ? '9.3%' : 'Ctx: 9.3%')); break; case 'session-clock': const sessionColor = (chalk as any)[item.color || 'blue'] || chalk.blue; - elements.push(sessionColor('Session: 2hr 15m')); + elements.push(sessionColor(item.rawValue ? '2hr 15m' : 'Session: 2hr 15m')); break; case 'version': const versionColor = (chalk as any)[item.color || 'green'] || chalk.green; - elements.push(versionColor('Version: 1.0.72')); + elements.push(versionColor(item.rawValue ? '1.0.72' : 'Version: 1.0.72')); break; case 'terminal-width': const termColor = (chalk as any)[item.color || 'dim'] || chalk.dim; const detectedWidth = canDetectTerminalWidth() ? terminalWidth : '??'; - elements.push(termColor(`Term: ${detectedWidth}`)); + elements.push(termColor(item.rawValue ? `${detectedWidth}` : `Term: ${detectedWidth}`)); break; case 'separator': const sepChar = item.character || '|'; @@ -432,6 +432,14 @@ const ItemsEditor: React.FC = ({ items, onUpdate, onBack, line newItems[selectedIndex] = { ...currentItem, character: nextChar }; onUpdate(newItems); } + } else if (input === 'r' && items.length > 0) { + // Toggle raw value for non-separator items + const currentItem = items[selectedIndex]; + if (currentItem && currentItem.type !== 'separator' && currentItem.type !== 'flex-separator') { + const newItems = [...items]; + newItems[selectedIndex] = { ...currentItem, rawValue: !currentItem.rawValue }; + onUpdate(newItems); + } } else if (key.escape) { onBack(); } @@ -477,13 +485,29 @@ const ItemsEditor: React.FC = ({ items, onUpdate, onBack, line const hasFlexSeparator = items.some(item => item.type === 'flex-separator'); const widthDetectionAvailable = canDetectTerminalWidth(); + // Build dynamic help text based on selected item + const currentItem = items[selectedIndex]; + const isSeparator = currentItem?.type === 'separator'; + const isFlexSeparator = currentItem?.type === 'flex-separator'; + const canToggleRaw = currentItem && !isSeparator && !isFlexSeparator; + + let helpText = '↑↓ select, ←→ change type'; + if (isSeparator) { + helpText += ', Space edit separator'; + } + helpText += ', Enter to move, (a)dd, (i)nsert, (d)elete, (c)lear line'; + if (canToggleRaw) { + helpText += ', (r)aw value'; + } + helpText += ', ESC back'; + return ( Edit Line {lineNumber} {moveMode && [MOVE MODE]} {moveMode ? ( ↑↓ to move item, ESC or Enter to exit move mode ) : ( - ↑↓ select, ←→ change type, Space edit separator, Enter to move, (a)dd, (i)nsert, (d)elete, (c)lear line, ESC back + {helpText} )} {hasFlexSeparator && !widthDetectionAvailable && ( @@ -500,9 +524,7 @@ const ItemsEditor: React.FC = ({ items, onUpdate, onBack, line {index === selectedIndex ? (moveMode ? '◆ ' : '▶ ') : ' '} {index + 1}. {getItemDisplay(item)} - {item.type === 'separator' && index === selectedIndex && !moveMode && ( - (Space to edit) - )} + {item.rawValue && (raw value)} ))