fix: emit ANSI reset when truncation drops it (#778) - #956
Open
MsfPablo wants to merge 2 commits into
Open
Conversation
truncate() cuts the string at the first character exceeding the target width and discards the remainder, including the trailing reset emitted by apply_color/apply_style. Both display paths hit this: ansi_trim_end() truncates to drop trailing column padding, and every row is then truncated to the terminal width. As a result nearly every emitted row ends with an open style, leaving the terminal bold/colored after procs exits. Append a reset in truncate() when the retained output contains an escape sequence, so both call sites are covered. Plain (--color=never) output is untouched.
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.
Fixes #778.
Root cause
apply_color/apply_stylewrap each column in a style + trailing\x1b[0m.util::truncate()then cuts the string at the first character that would exceed the target width and returns only what it accumulated so far — everything after the cut point is discarded, including that trailing reset.Both display paths in
view.rsgo through it, back to back:So whenever the last visible column has padding (content shorter than the column) or the row is wider than the terminal, the reset is dropped and the row ends mid-style. That is what leaves the terminal bold/white after
procsexits, as reported in the issue.Fix
Append the reset inside
truncate()when the retained output contains an escape sequence. Fixing it there covers both call sites rather than only theansi_trim_endone, and plain output is untouched: with--color=never(and foradjust(), which truncates pre-colorization content) the buffer contains no\x1b, so nothing is appended. Un-truncated strings still take theCow::Borrowedpath unchanged.Note this is a different, narrower fix than the earlier self-closed draft #908, which patched only
ansi_trim_end— that leaves the terminal-widthtruncateon the very next line still able to drop the reset on narrow terminals.Verification
Comparing a baseline build (
git stash) with the fixed build, counting emitted lines that contain ANSI codes but do not end in a reset:Header and unit rows are byte-identical after stripping ANSI codes at all three widths, so no visible output changed.
Added four unit tests in
src/util.rscovering truncation of styled and plain text, andansi_trim_endwith and without trailing padding.clippyoutput is byte-identical to thegit stashbaseline on this machine — the 12 pre-existing errors are all in macOS-specific code untouched by this change (unsafe_op_in_unsafe_fn,collapsible_if, etc.).Written with assistance from Claude Code; reviewed and verified by me before submitting.