diff --git a/src/widgets/CompactionCounter.ts b/src/widgets/CompactionCounter.ts index 65ab6a38..5b6467be 100644 --- a/src/widgets/CompactionCounter.ts +++ b/src/widgets/CompactionCounter.ts @@ -7,6 +7,7 @@ import type { CustomKeybind, Widget, WidgetEditorDisplay, + WidgetEditorProps, WidgetItem } from '../types/Widget'; import { ZERO_COMPACTION_STATS } from '../utils/compaction'; @@ -16,6 +17,12 @@ import { isMetadataFlagEnabled, toggleMetadataFlag } from './shared/metadata'; +import { + getSlotSymbol, + getSymbolKeybind, + renderSymbolSlotsEditor, + type SymbolSlot +} from './shared/symbol-override'; const COMPACTION_ICON = '↻'; const COMPACTION_NERD_FONT_ICON = '\uF021'; @@ -32,6 +39,7 @@ const TOGGLE_TRIGGERS_ACTION = 'toggle-triggers'; const SHOW_TRIGGERS_METADATA_KEY = 'showTriggers'; const TOGGLE_RECLAIMED_ACTION = 'toggle-reclaimed'; const SHOW_RECLAIMED_METADATA_KEY = 'showReclaimed'; +const RECLAIMED_SLOT: SymbolSlot = { id: 'symbolReclaimed', label: 'Reclaimed', defaultSymbol: '↓' }; const SAMPLE_STATS: CompactionData = Object.freeze({ count: 2, byTrigger: Object.freeze({ auto: 1, manual: 1, unknown: 0 }), @@ -94,8 +102,12 @@ function toggleHideZero(item: WidgetItem): WidgetItem { }; } -function formatReclaimedSuffix(tokensReclaimed: number): string { - return tokensReclaimed > 0 ? ` ↓${formatTokens(tokensReclaimed)}` : ''; +function formatReclaimedSuffix(tokensReclaimed: number, item: WidgetItem): string { + if (tokensReclaimed <= 0) { + return ''; + } + const symbol = getSlotSymbol(item, RECLAIMED_SLOT); + return symbol.length > 0 ? ` ${symbol}${formatTokens(tokensReclaimed)}` : ` ${formatTokens(tokensReclaimed)}`; } function formatTriggerSuffix(byTrigger: CompactionData['byTrigger']): string { @@ -118,7 +130,7 @@ function formatStats(data: CompactionData, item: WidgetItem, icon: string): stri out += formatTriggerSuffix(data.byTrigger); } if (isMetadataFlagEnabled(item, SHOW_RECLAIMED_METADATA_KEY)) { - out += formatReclaimedSuffix(data.tokensReclaimed); + out += formatReclaimedSuffix(data.tokensReclaimed, item); } return out; } @@ -239,10 +251,15 @@ export class CompactionCounterWidget implements Widget { keybinds.push({ key: 's', label: '(s)plit by trigger', action: TOGGLE_TRIGGERS_ACTION }); keybinds.push({ key: 't', label: '(t)okens reclaimed', action: TOGGLE_RECLAIMED_ACTION }); keybinds.push({ key: 'h', label: '(h)ide when zero', action: TOGGLE_HIDE_ZERO_ACTION }); + keybinds.push(getSymbolKeybind()); return keybinds; } + renderEditor(props: WidgetEditorProps) { + return renderSymbolSlotsEditor(props, [RECLAIMED_SLOT]); + } + supportsRawValue(): boolean { return false; } supportsColors(item: WidgetItem): boolean { return true; } } diff --git a/src/widgets/__tests__/CompactionCounter.test.ts b/src/widgets/__tests__/CompactionCounter.test.ts index ddbea780..e3f9cef3 100644 --- a/src/widgets/__tests__/CompactionCounter.test.ts +++ b/src/widgets/__tests__/CompactionCounter.test.ts @@ -235,6 +235,20 @@ describe('CompactionCounterWidget', () => { item: { ...ITEM, metadata: { showReclaimed: 'true' } } })).toBe('↻ 2 ↓120.0k'); }); + + it('renders a custom reclaimed glyph from the symbolReclaimed override', () => { + expect(render({ + compactionData: { count: 2, tokensReclaimed: 887000 }, + item: { ...ITEM, metadata: { showReclaimed: 'true', symbolReclaimed: 'X' } } + })).toBe('↻ 2 X887.0k'); + }); + + it('drops the reclaimed glyph but keeps the space when the override is empty', () => { + expect(render({ + compactionData: { count: 2, tokensReclaimed: 887000 }, + item: { ...ITEM, metadata: { showReclaimed: 'true', symbolReclaimed: '' } } + })).toBe('↻ 2 887.0k'); + }); }); describe('editor', () => { @@ -244,7 +258,8 @@ describe('CompactionCounterWidget', () => { { key: 'n', label: '(n)erd font', action: 'toggle-nerd-font' }, { key: 's', label: '(s)plit by trigger', action: 'toggle-triggers' }, { key: 't', label: '(t)okens reclaimed', action: 'toggle-reclaimed' }, - { key: 'h', label: '(h)ide when zero', action: 'toggle-hide-zero' } + { key: 'h', label: '(h)ide when zero', action: 'toggle-hide-zero' }, + { key: 'g', label: '(g)lyph', action: 'edit-symbol-override' } ]); }); @@ -256,7 +271,8 @@ describe('CompactionCounterWidget', () => { { key: 'f', label: '(f)ormat', action: 'cycle-format' }, { key: 's', label: '(s)plit by trigger', action: 'toggle-triggers' }, { key: 't', label: '(t)okens reclaimed', action: 'toggle-reclaimed' }, - { key: 'h', label: '(h)ide when zero', action: 'toggle-hide-zero' } + { key: 'h', label: '(h)ide when zero', action: 'toggle-hide-zero' }, + { key: 'g', label: '(g)lyph', action: 'edit-symbol-override' } ]); });