Skip to content

text: end CSI sequences at their final byte, not only at "m" - #447

Open
simpleqt wants to merge 1 commit into
jedib0t:mainfrom
simpleqt:fix/csi-final-byte
Open

simpleqt wants to merge 1 commit into
jedib0t:mainfrom
simpleqt:fix/csi-final-byte

Conversation

@simpleqt

@simpleqt simpleqt commented Nov 4, 2026

Copy link
Copy Markdown

Proposed Changes

  • EscSeqParser now ends a CSI sequence at its final byte (0x40-0x7E, ECMA-48 section 5.4) instead of ending it at m only, so the sequences emitted by this package's own text.Cursor/text.EraseLine (\x1b[A, \x1b[5B, \x1b[K, ...) no longer consume the text that follows them.
  • It ignores the CSI sequences that are not SGR (...m) while tracking the attributes in force: their parameter bytes are not attribute codes.
  • Added TestEscSeqParser_ControlSequences, TestStripEscape_CursorSequences and TestCursorSequences.

StripEscape, StringWidthWithoutEscSequences, LongestLineLen, Trim, Pad, Snip, RuneCount, Widen and InsertEveryN all measure or strip text through EscSeqParser, so a cell holding a cursor sequence was measured as empty (width 0) and trimmed wrongly:

call before after
StripEscape(EraseLine.Sprint() + "Ghost") "" "Ghost"
StringWidthWithoutEscSequences(CursorUp.Sprintn(3) + "abc") 0 3
LongestLineLen(EraseLine.Sprint() + "abc\ndef") 0 3
Trim(EraseLine.Sprint() + "abcdef", 3) "\x1b[Kabcdef" "\x1b[Kabc"

\x1b[2;3H positions the cursor, so it must not turn on dim and must not clear the colour in force either; the parameter bytes of a non-SGR sequence are not attribute codes.

Validation: the three new tests fail on main before the change and pass after it; go test ./text/ passes; gofmt -l reports nothing for the changed files.

EscSeqParser.isEscapeStopRune() ended a CSI sequence at "m" only, so every
other CSI sequence stayed open and the text after it was consumed as part of
the sequence, even though a CSI sequence ends at its first final byte in the
range 0x40-0x7E (ECMA-48, section 5.4).

text.Cursor and text.EraseLine emit exactly such sequences ("\x1b[A",
"\x1b[5B", "\x1b[K", ...):

    StripEscape(EraseLine.Sprint() + "Ghost")                   -> "" (want "Ghost")
    StringWidthWithoutEscSequences(CursorUp.Sprintn(3) + "abc") -> 0 (want 3)
    LongestLineLen(EraseLine.Sprint() + "abc\ndef")             -> 0 (want 3)
    Trim(EraseLine.Sprint() + "abcdef", 3)                      -> "\x1b[Kabcdef"

Pad, Snip, RuneCount, Widen and InsertEveryN inherited the miscount.

A CSI sequence now ends at the first byte in 0x40-0x7E that follows the "ESC ["
introducer, and ParseSeq() ignores the CSI sequences that are not SGR
("...m"): their parameter bytes are not attribute codes, so "\x1b[2;3H"
positions the cursor instead of turning on dim, and it leaves the attributes
in force untouched.
Copilot AI balanced review requested due to automatic review settings November 4, 2026 20:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@sonarqubecloud

sonarqubecloud Bot commented Nov 4, 2026

Copy link
Copy Markdown

@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 41903829197

Coverage remained the same at 100.0%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: 7 of 7 lines across 1 file are fully covered (100%).
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 5170
Covered Lines: 5170
Line Coverage: 100.0%
Coverage Strength: 1.21 hits per line

💛 - Coveralls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants