From 88993a468f307614a8eff721c5635061896d7084 Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Wed, 22 Apr 2026 14:40:54 -0500 Subject: [PATCH] =?UTF-8?q?fix(tui):=20input=20wrap=20width=20mismatch=20?= =?UTF-8?q?=E2=80=94=20last=20letter=20no=20longer=20flickers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'columns' prop passed to TextInput was cols - pw, but the actual render width is cols - pw - 2 (NoSelect's paddingX={1} on each side subtracts two cols from the composer area). cursorLayout thought it had two extra cols, so wrap-ansi wrapped at render col N while the declared cursor sat at col N+2 on the same row. The render and the declared cursor disagreed right at the wrap boundary — the last letter of a sentence spanning two lines flickered in/out as each keystroke flipped which cell the cursor claimed. Also polish the /help hotkeys panel — the !cmd / {!cmd} placeholders read as literal commands to type, so show them with angle-bracket syntax and a concrete example (blitz row 5 sub-item 4). --- ui-tui/src/components/appLayout.tsx | 9 ++++++++- ui-tui/src/content/hotkeys.ts | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ui-tui/src/components/appLayout.tsx b/ui-tui/src/components/appLayout.tsx index 6cb6de59e..171ee27f5 100644 --- a/ui-tui/src/components/appLayout.tsx +++ b/ui-tui/src/components/appLayout.tsx @@ -216,8 +216,15 @@ const ComposerPane = memo(function ComposerPane({ + {/* + 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. + */} ', 'run a shell command (e.g. !ls, !git status)'], + ['{!}', 'interpolate shell output inline (e.g. "branch is {!git branch --show-current}")'] ]