Skip to content

fix: re-apply color after nested reset in RenderString - #119

Merged
inhere merged 1 commit into
gookit:masterfrom
Yanhu007:fix/printf-nested-color-reset
Apr 16, 2026
Merged

fix: re-apply color after nested reset in RenderString#119
inhere merged 1 commit into
gookit:masterfrom
Yanhu007:fix/printf-nested-color-reset

Conversation

@Yanhu007

Copy link
Copy Markdown
Contributor

Fixes #67

Problem

When using Printf with a pre-colored string argument, the inner color's reset sequence (\033[0m) terminates the outer color, leaving the rest of the string uncolored:

green := color.Green.Sprint("green")
color.Red.Printf("before %s after", green)
// "after" appears uncolored instead of red

Before (broken):

\033[31mbefore \033[32mgreen\033[0m after\033[0m
                                    ^^^^^ not red!

Fix

In RenderString, detect any reset sequences within the string and re-apply the current color code after each reset:

After (fixed):

\033[31mbefore \033[32mgreen\033[0m\033[31m after\033[0m
                                   ^^^^^^^^^ red restored!

This is a common technique used by other color libraries (e.g., chalk in Node.js). All existing tests pass.

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

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.

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 RenderString to detect ResetSet within 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.

Comment thread color.go
Comment on lines +230 to +236
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

Copilot AI Apr 15, 2026

Copy link

Choose a reason for hiding this comment

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

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.

Copilot generated this review using guidance from repository custom instructions.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot apply changes based on this feedback

Comment thread color.go
Comment on lines +230 to +236
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

Copilot AI Apr 15, 2026

Copy link

Choose a reason for hiding this comment

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

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).

Copilot uses AI. Check for mistakes.
@inhere
inhere merged commit e58a899 into gookit:master Apr 16, 2026
9 of 51 checks passed
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.

Printf does not color the entire string

3 participants