refactor(tui): /clean pass on blitz closeout — trim comments, flatten logic

- normalizeStatusBar collapses to one ternary expression
- /statusbar slash hoists the toggle value and flattens the branch tree
- shift-tab yolo comment reduced to one line
- cursorLayout/offsetFromPosition lose paragraph-length comments
- appLayout collapses the three {!overlay.agents && …} into one fragment
- StatusRule drops redundant flexShrink={0} (Yoga default)
- server.py uses a walrus + frozenset and trims the compat helper

Net -43 LoC. 237 vitest + 46 pytest green, layouts unchanged.
This commit is contained in:
Brooklyn Nicholson 2026-04-22 14:54:42 -05:00
parent 1e8cfa9092
commit 48f2ac3352
8 changed files with 40 additions and 83 deletions

View file

@ -50,17 +50,8 @@ export default function wrapText(text: string, maxWidth: number, wrapType: Style
})
}
// Char-granularity wrap: break at exact column boundaries regardless of
// whitespace. Used for text inputs where the cursor position must track
// the wrap boundary deterministically — word-wrap's whitespace-preferring
// reshuffle causes visible cursor flicker as each keystroke can push a
// word across a line break.
if (wrapType === 'wrap-char') {
return wrapAnsi(text, maxWidth, {
trim: false,
hard: true,
wordWrap: false
})
return wrapAnsi(text, maxWidth, { trim: false, hard: true, wordWrap: false })
}
if (wrapType === 'wrap-trim') {

View file

@ -310,23 +310,18 @@ export const coreCommands: SlashCommand[] = [
name: 'statusbar',
run: (arg, ctx) => {
const mode = arg.trim().toLowerCase()
const current = ctx.ui.statusBar
const toggle: StatusBarMode = ctx.ui.statusBar === 'off' ? 'top' : 'off'
// 'on' is a legacy alias for 'top' — the inline position above the
// input where the bar originally lived. No-arg / `toggle` flips
// visibility and defaults to 'top' when reappearing.
const next: null | StatusBarMode =
mode === '' || mode === 'toggle'
? current === 'off'
? 'top'
: 'off'
!mode || mode === 'toggle'
? toggle
: mode === 'on' || mode === 'top'
? 'top'
: mode === 'off' || mode === 'bottom'
? mode
: null
if (next === null) {
if (!next) {
return ctx.transcript.sys('usage: /statusbar [on|off|top|bottom|toggle]')
}

View file

@ -16,17 +16,12 @@ import { patchUiState } from './uiStore.js'
const STATUSBAR_MODES = new Set<StatusBarMode>(['bottom', 'off', 'top'])
// Legacy configs stored tui_statusbar as a bool; the short-lived 4-mode
// variant wrote 'on'. Both map to 'top' (inline above the input) — the
// original feature's default — so users keep their preference without
// manual migration.
export const normalizeStatusBar = (raw: unknown): StatusBarMode => {
if (raw === false) return 'off'
if (raw === true || raw == null || raw === 'on') return 'top'
if (typeof raw === 'string' && STATUSBAR_MODES.has(raw as StatusBarMode)) return raw as StatusBarMode
return 'top'
}
export const normalizeStatusBar = (raw: unknown): StatusBarMode =>
raw === false
? 'off'
: typeof raw === 'string' && STATUSBAR_MODES.has(raw as StatusBarMode)
? (raw as StatusBarMode)
: 'top'
const MTIME_POLL_MS = 5000

View file

@ -378,10 +378,7 @@ export function useInputHandlers(ctx: InputHandlerContext): InputHandlerResult {
return cActions.openEditor()
}
// Shift-Tab toggles per-session yolo without submitting a turn — mirrors
// Claude Code's in-place dangerously-approve toggle. Slash /yolo keeps
// working for discoverability; this just skips the inference round-trip
// when you only want to flip the flag mid-flow (blitz #5 sub-item 11).
// shift-tab flips yolo without spending a turn (claude-code parity)
if (key.shift && key.tab && !cState.completions.length) {
return void gateway
.rpc<ConfigSetResponse>('config.set', { key: 'yolo', session_id: live.sid })

View file

@ -191,7 +191,7 @@ export function StatusRule({
const leftWidth = Math.max(12, cols - cwdLabel.length - 3)
return (
<Box flexShrink={0} height={1}>
<Box height={1}>
<Box flexShrink={1} width={leftWidth}>
<Text color={t.color.bronze} wrap="truncate-end">
{'─ '}

View file

@ -216,13 +216,7 @@ const ComposerPane = memo(function ComposerPane({
</Box>
<Box flexGrow={1} position="relative">
{/*
Subtract the NoSelect paddingX={1} (2 cols total) and the
prompt-glyph column (pw) so cursorLayout agrees with the
width wrap-ansi actually uses at render time. Off-by-one/
two here manifests as the final letter flickering
in/out when a sentence crosses the wrap boundary.
*/}
{/* subtract NoSelect paddingX={1} (2 cols) + pw so wrap-ansi and cursorLayout agree */}
<TextInput
columns={Math.max(20, composer.cols - pw - 2)}
onChange={composer.updateInput}
@ -271,12 +265,8 @@ const StatusRulePane = memo(function StatusRulePane({
return null
}
// 'top' sits inline above the input; give it one row of breathing
// space above so the transcript (or queue) doesn't butt directly
// against the status row. 'bottom' lives at the last row of the
// viewport so it needs no margin.
return (
<Box flexShrink={0} marginTop={at === 'top' ? 1 : 0}>
<Box marginTop={at === 'top' ? 1 : 0}>
<StatusRule
bgCount={ui.bgTasks.size}
busy={ui.busy}
@ -318,18 +308,20 @@ export const AppLayout = memo(function AppLayout({
</Box>
{!overlay.agents && (
<PromptZone
cols={composer.cols}
onApprovalChoice={actions.answerApproval}
onClarifyAnswer={actions.answerClarify}
onSecretSubmit={actions.answerSecret}
onSudoSubmit={actions.answerSudo}
/>
<>
<PromptZone
cols={composer.cols}
onApprovalChoice={actions.answerApproval}
onClarifyAnswer={actions.answerClarify}
onSecretSubmit={actions.answerSecret}
onSudoSubmit={actions.answerSudo}
/>
<ComposerPane actions={actions} composer={composer} status={status} />
<StatusRulePane at="bottom" composer={composer} status={status} />
</>
)}
{!overlay.agents && <ComposerPane actions={actions} composer={composer} status={status} />}
{!overlay.agents && <StatusRulePane at="bottom" composer={composer} status={status} />}
</Box>
</AlternateScreen>
)

View file

@ -167,11 +167,8 @@ export function lineNav(s: string, p: number, dir: -1 | 1): null | number {
return snapPos(s, Math.min(nextBreak + 1 + col, lineEnd))
}
// Cursor layout mirrors `wrap-ansi(text, cols, { wordWrap: false, hard: true })`
// which is what `<Text wrap="wrap-char">` ends up feeding to the renderer.
// Char-granularity wrap keeps wrap boundaries deterministic as the user
// types — word-wrap's whitespace-preferring reshuffle causes the cursor
// to flicker as each keystroke moves a word across a line break (blitz #9).
// mirrors wrap-ansi(..., { wordWrap: false, hard: true }) so the declared
// cursor lines up with what <Text wrap="wrap-char"> actually renders
export function cursorLayout(value: string, cursor: number, cols: number) {
const pos = Math.max(0, Math.min(cursor, value.length))
const w = Math.max(1, cols)
@ -205,11 +202,7 @@ export function cursorLayout(value: string, cursor: number, cols: number) {
col += sw
}
// The cursor renders as an inverted cell AFTER the character at `pos`
// (or as a standalone trailing cell when `pos === value.length`). If
// col has reached the wrap column, that cell overflows to the next row
// — match wrap-ansi's behavior so the declared cursor doesn't sit past
// the visual edge.
// trailing cursor-cell overflows to the next row at the wrap column
if (col >= w) {
line++
col = 0