bugfix: restore ITU T.416 colon-format colors with colon separators - #239
Open
dylanpulver wants to merge 1 commit into
Open
bugfix: restore ITU T.416 colon-format colors with colon separators#239dylanpulver wants to merge 1 commit into
dylanpulver wants to merge 1 commit into
Conversation
_sgr_state_to_sequence() joined the parsed color parameters with ';'.
A colon-format color carries the T.416 colour space element
(38:2:<cs>:R:G:B) that the legacy 38;2;R;G;B form has no slot for, so
the restored sequence shifted R, G and B one position and left a
trailing parameter, which reads as SGR 0.
>>> wcwidth.wrap('\x1b[38:2::255:0:0mred text', width=4)[1]
'\x1b[38;2;0;255;0;0mtext\x1b[0m'
Feeding that prefix back to _sgr_state_update() yields foreground=None:
the color is lost, and the trailing 0 also clears any bold/underline in
the same restoration sequence.
Co-authored-by: Claude <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
_sgr_state_to_sequence()joins the parsed color parameters with;. A colon-format color carries the ITU-T T.416 (ISO/IEC 8613-6) §13.1.8 colour space id element —38:2:<cs>:R:G:B— which the legacy38;2;R;G;Bform has no slot for, so the restored sequence shifts R, G and B one position and leaves a trailing parameter.before this change:
after:
The
Noneis the second half of it: under ECMA-48 §8.3.117 the parameters are applied in order, so the extra0at the end is aRESET— the restoration sequence also clears any bold/underline it was carrying for that line.clip()shares the same call site.38:5:Nis unaffected (;and:are interchangeable there), so the change is scoped to the RGB tuple that actually has the extra element._parse_sgr_params()knows about the colon form and documents the 6-tuple it returns;_sgr_state_to_sequence()does not. The existing coverage matches that split:test_sgr_state_parse_colors_colon_formatasserts the parsed tuple and never re-serializes it, andtest_clip_sgr_result_is_self_contained— exactly the invariant that would catch this — is parametrized only over basic30–39colors. Not from a real workload; found reading escape-sequence handling for values parsed by one path and re-emitted by another.Alternative I rejected: normalizing the colour space element away at parse time (so
38:2::R:G:Band38;2;R;G;Bproduce the same 5-tuple) also fixes it and needs no serializer change — but it changes the documented return of_parse_sgr_params()and failstest_sgr_state_parse_colors_colon_format. Happy to switch if you'd rather have the canonical form.Verified:
pytest tests/ --ignore=tests/test_benchmarks.py— 1262 passed / 4 skipped before, 1263 passed / 4 skipped after (the one new test). Reverting onlywcwidth/sgr_state.pyand keeping the new test: 1 failed, 24 passed intest_sgr_state.py,foreground: None != (38, 2, 0, 255, 0, 0). Fulltox -e lintchain run locally: flake8, pylint 10.00/10, mypy --strict, pydocstyle, codespell, isort all clean.Not tested: no real terminal was driven. The claim above is about what the emitted sequence denotes under T.416/ECMA-48 and under this library's own parser; how a given emulator resolves a 6-parameter
38;2;…is not something I measured.AI assistance: this change was written with Claude Code (model Claude Opus 5). I reviewed the diff and ran everything reported above.