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`. |
||
|---|---|---|
| .. | ||
| agent | ||
| ai | ||
| chord | ||
| codemode | ||
| coding-agent | ||
| durable | ||
| env | ||
| evals | ||
| mcp | ||
| telemetry | ||
| tui | ||