mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
Fixes #10925. ## Problem `splitIntoTokensWithAnsi()` attaches pending escape codes to the next visible character. The code that closes a styled word therefore lands on the following space: `**commodo** consequat` tokenizes as `\x1b[1mcommodo`, `\x1b[22m `, `consequat`. `wrapSingleLine()` detected whitespace with `token.trim() === ""`, which is false for `"\x1b[22m "`. When the styled word ended exactly at the wrap width, that space was treated as a word and moved to the next line: ``` before: ["aaaa \x1b[1mbold", "\x1b[1m\x1b[22m next", "word"] (width 9) after: ["aaaa \x1b[1mbold\x1b[22m", "next word"] ``` Because the closing code moved to the next line, the style also stayed open into the right padding of the wrapped line. Separately, `getLineEndReset()` closed only underline at line end, so strikethrough that spans a wrap continued into the padding. ## Fix - Detect whitespace tokens after stripping escape codes. - When a whitespace token is dropped at a wrap, append its escape codes to the wrapped line and update the tracker, so the style closes there and is not re-opened on the next line. - Close strikethrough (`\x1b[29m`) at line end, like underline. `getActiveCodes()` re-opens it on the next line. Background is unaffected. - Whitespace wider than an empty line that carries codes (e.g. background spaces followed by a trailing reset) keeps only the codes. Without this, treating it as whitespace skipped the long-token path, and the trailing reset blocked the final `trimEnd()`, leaving a line wider than `width`. - When a long word follows, the line before it is now trimmed before the line-end reset is added. Otherwise the reset (now also emitted for strikethrough) blocks the final `trimEnd()` and leaves trailing spaces. ## Tests - `wrap-ansi.test.ts`: boundary closing code, dropped space with a color reset, strikethrough reset and restore across a wrap, strikethrough reset with background preserved. - `markdown.test.ts`: padded Markdown with a background at an exact boundary for bold and strikethrough. - The new tests fail without the fix. With the old code, rendering the issue text through `UserMessageComponent` (dark theme, padding 1) at widths 40-120 produced 5 bad lines at width 78. With the fix it produces none. - Fuzzing over 1.2M random styled inputs with SGR and OSC 8 codes found no line wider than `width`, and no case where the old wrapper laid out text the same as the unstyled input but the new one does not. - Benchmark (`wrapTextWithAnsi`, width 77, about 5-18k chars, median of 6 processes) against `main`: plain -5%, light styling -0.5%, heavy styling +1%, long strikethrough +0%, all within noise. The whitespace check scans character codes and stops at the first visible text instead of allocating a stripped copy. - `npm run check` passes. All `packages/tui` tests pass. `./test.sh` shows no new failures; the remaining failures are environment-specific: the clipboard tests also fail on `main` here, and the durable, env (ssh), and chord failures are in packages that do not depend on `pi-tui`. |
||
|---|---|---|
| .. | ||
| fixtures | ||
| alt-screen-large-transcript-bench.ts | ||
| autocomplete-skill-slash.test.ts | ||
| autocomplete.test.ts | ||
| bug-regression-isimageline-startswith-bug.test.ts | ||
| chat-simple.ts | ||
| colors.test.ts | ||
| editor-history-keybindings.test.ts | ||
| editor.test.ts | ||
| exit-restore.test.ts | ||
| fuzzy.test.ts | ||
| image-test.ts | ||
| input.test.ts | ||
| key-tester.ts | ||
| keybindings.test.ts | ||
| keys.test.ts | ||
| latex.test.ts | ||
| layout.test.ts | ||
| markdown.test.ts | ||
| mouse-components.test.ts | ||
| native-clipboard-linux.test.ts | ||
| native-module-path.test.ts | ||
| native-platform.test.ts | ||
| overlay-non-capturing.test.ts | ||
| overlay-options.test.ts | ||
| overlay-short-content.test.ts | ||
| program-status.test.ts | ||
| regression-overlay-cjk-boundary.test.ts | ||
| regression-regional-indicator-width.test.ts | ||
| regression-sigwinch-kill-eacces.test.ts | ||
| regression-slice-by-column-ansi-order.test.ts | ||
| render-churn-bench.ts | ||
| select-list.test.ts | ||
| settings-list.test.ts | ||
| stdin-buffer.test.ts | ||
| tab-width.test.ts | ||
| terminal-colors.test.ts | ||
| terminal-image.test.ts | ||
| terminal.test.ts | ||
| test-themes.ts | ||
| truncate-to-width.test.ts | ||
| truncated-text.test.ts | ||
| tui-alt-screen.test.ts | ||
| tui-cell-size-input.test.ts | ||
| tui-overlay-style-leak.test.ts | ||
| tui-render.test.ts | ||
| tui-shrink.test.ts | ||
| viewport-overwrite-repro.ts | ||
| virtual-terminal.ts | ||
| visible-width.test.ts | ||
| wheel-scroll.test.ts | ||
| word-navigation.test.ts | ||
| wrap-ansi.test.ts | ||