fix: re-apply color after nested reset in RenderString - #119
Conversation
When Printf receives a pre-colored string as an argument, the
inner color's reset sequence (\033[0m) kills the outer color
for the remainder of the string.
Fix by detecting reset sequences within the string and re-applying
the current color code after each one. This ensures that text
following a nested colored argument retains the outer color.
Before: \033[31mbefore \033[32mgreen\033[0m after\033[0m
^^^^^ uncolored!
After: \033[31mbefore \033[32mgreen\033[0m\033[31m after\033[0m
^^^^^^^^^ red restored!
Fixes gookit#67
There was a problem hiding this comment.
Pull request overview
Fixes issue #67 where nested colored substrings (containing \x1b[0m) prematurely reset the “outer” color, by re-applying the outer SGR code after any reset sequence inside RenderString.
Changes:
- Update
RenderStringto detectResetSetwithin the input and re-apply the current color code after each reset. - Keep existing behavior for disabled/no-color environments by still clearing codes via
ClearCode.
| open := StartSet + code + "m" | ||
| // If the string contains reset sequences, re-apply our color after each | ||
| // reset so that nested colored args don't break the outer color. | ||
| if strings.Contains(str, ResetSet) { | ||
| str = strings.ReplaceAll(str, ResetSet, ResetSet+open) | ||
| } | ||
| return open + str + ResetSet |
There was a problem hiding this comment.
The new reset-handling behavior in RenderString isn’t covered by tests. Please add a unit test exercising a nested colored string (i.e., input str containing ResetSet) and asserting that the outer code is re-applied after the inner reset, matching the issue #67 repro.
| open := StartSet + code + "m" | ||
| // If the string contains reset sequences, re-apply our color after each | ||
| // reset so that nested colored args don't break the outer color. | ||
| if strings.Contains(str, ResetSet) { | ||
| str = strings.ReplaceAll(str, ResetSet, ResetSet+open) | ||
| } | ||
| return open + str + ResetSet |
There was a problem hiding this comment.
This fix only applies to RenderString. Callers that use RenderCode/RenderWithSpaces (e.g., Color.Render/Color.Sprint) will still produce output where an inner \x1b[0m reset terminates the outer color. Consider extracting this reset-reapply logic into a shared helper and using it from RenderCode/RenderWithSpaces too (or explicitly documenting the differing behavior).
Fixes #67
Problem
When using
Printfwith a pre-colored string argument, the inner color's reset sequence (\033[0m) terminates the outer color, leaving the rest of the string uncolored:Before (broken):
Fix
In
RenderString, detect any reset sequences within the string and re-apply the current color code after each reset:After (fixed):
This is a common technique used by other color libraries (e.g., chalk in Node.js). All existing tests pass.