EPIC: #140
Branch: feat/bun14-terminal
Depends on: #141
Blocks: #144
Context / Problem
src/render.ts contains two in-house helpers used at 15+ call sites across the file:
stripAnsi(str): limited SGR regex that misses OSC 8 hyperlinks and cursor movement sequences.
clipAnsi(str, maxVisible): manual character loop that miscounts emoji and CJK characters (each code point is treated as 1 column).
renderHelpOverlay() contains a third inline variant: s.replace(/\x1b\[[0-9;]*m/g, "").length.
After #141, src/render/terminal.ts provides visibleWidth and clipToWidth as drop-in replacements backed by Bun 1.4 native APIs.
Additionally, renderGroups passes fragmentMaxChars (computed as termWidth - FRAGMENT_INDENT - 1) to highlightFragment. This migration is an opportunity to verify that highlightFragment interprets this budget as a terminal column limit, not a byte or code-unit limit.
Solution
Replace every usage of the in-house helpers with calls to src/render/terminal.ts:
| Before |
After |
stripAnsi(str).length |
visibleWidth(str) |
clipAnsi(str, n) |
clipToWidth(str, n) |
inline s.replace(...).length in renderHelpOverlay |
visibleWidth(s) |
Delete stripAnsi and clipAnsi from src/render.ts once all call sites are migrated.
src/render.ts imports from src/render/terminal.ts only - it does not call Bun.stringWidth, Bun.sliceAnsi, or Bun.stripANSI directly.
Acceptance Criteria
Definition of Done
- PR reviewed and merged into
feat/bun14-terminal.
- Zero lint errors, zero format diff, test suite green.
EPIC: #140
Branch:
feat/bun14-terminalDepends on: #141
Blocks: #144
Context / Problem
src/render.tscontains two in-house helpers used at 15+ call sites across the file:stripAnsi(str): limited SGR regex that misses OSC 8 hyperlinks and cursor movement sequences.clipAnsi(str, maxVisible): manual character loop that miscounts emoji and CJK characters (each code point is treated as 1 column).renderHelpOverlay()contains a third inline variant:s.replace(/\x1b\[[0-9;]*m/g, "").length.After #141,
src/render/terminal.tsprovidesvisibleWidthandclipToWidthas drop-in replacements backed by Bun 1.4 native APIs.Additionally,
renderGroupspassesfragmentMaxChars(computed astermWidth - FRAGMENT_INDENT - 1) tohighlightFragment. This migration is an opportunity to verify thathighlightFragmentinterprets this budget as a terminal column limit, not a byte or code-unit limit.Solution
Replace every usage of the in-house helpers with calls to
src/render/terminal.ts:stripAnsi(str).lengthvisibleWidth(str)clipAnsi(str, n)clipToWidth(str, n)s.replace(...).lengthinrenderHelpOverlayvisibleWidth(s)Delete
stripAnsiandclipAnsifromsrc/render.tsonce all call sites are migrated.src/render.tsimports fromsrc/render/terminal.tsonly - it does not callBun.stringWidth,Bun.sliceAnsi, orBun.stripANSIdirectly.Acceptance Criteria
src/render.tsno longer definesstripAnsiorclipAnsi.src/render.tsdoes not callBun.stringWidth,Bun.sliceAnsi, orBun.stripANSIdirectly."right-aligns match count to termWidth"insrc/render.test.tsstill passes."org/\u524D\u7AEF-service") withtermWidth=60;visibleWidth(stripAnsi(repoLine)) <= 60.termWidth.termWidth.bun test src/render.test.tspasses.bun run lintandbun run format:checkare clean.bun run knipis clean.Definition of Done
feat/bun14-terminal.