fix(color): resolve palette before ANSI conversion

resolves #5790
This commit is contained in:
Jan De Dobbeleer 2024-11-03 16:41:48 +01:00 committed by Jan De Dobbeleer
parent 4ac1033706
commit 6a8cecb73b
2 changed files with 29 additions and 9 deletions

View file

@ -21,6 +21,7 @@ var TrueColor = true
// but also a name of one of the first 16 ANSI colors like `lightBlue`.
type String interface {
ToAnsi(colorString Ansi, isBackground bool) Ansi
Resolve(colorString Ansi) (Ansi, error)
}
type Set struct {
@ -150,12 +151,15 @@ func MakeColors(palette Palette, cacheEnabled bool, accentColor Ansi, env runtim
defaultColors := &Defaults{}
defaultColors.SetAccentColor(env, accentColor)
colors = defaultColors
if palette != nil {
colors = &PaletteColors{ansiColors: colors, palette: palette}
}
if cacheEnabled {
colors = &Cached{ansiColors: colors}
}
return
}
@ -288,6 +292,10 @@ func (d *Defaults) ToAnsi(ansiColor Ansi, isBackground bool) Ansi {
return emptyColor
}
func (d *Defaults) Resolve(colorString Ansi) (Ansi, error) {
return colorString, nil
}
// getAnsiColorFromName returns the color code for a given color name if the name is
// known ANSI color name.
func getAnsiColorFromName(colorValue Ansi, isBackground bool) (Ansi, error) {
@ -325,6 +333,10 @@ func (p *PaletteColors) ToAnsi(colorString Ansi, isBackground bool) Ansi {
return ansiColor
}
func (p *PaletteColors) Resolve(colorString Ansi) (Ansi, error) {
return p.palette.ResolveColor(colorString)
}
// Cached is the AnsiColors Decorator that does simple color lookup caching.
// ToColor calls are cheap, but not free, and having a simple cache in
// has measurable positive effect on performance.
@ -350,3 +362,7 @@ func (c *Cached) ToAnsi(colorString Ansi, isBackground bool) Ansi {
c.colorCache[key] = ansiColor
return ansiColor
}
func (c *Cached) Resolve(colorString Ansi) (Ansi, error) {
return c.ansiColors.Resolve(colorString)
}

View file

@ -382,10 +382,6 @@ func writeEscapedAnsiString(text string) {
builder.WriteString(text)
}
func getAnsiFromColorString(colorString color.Ansi, isBackground bool) color.Ansi {
return Colors.ToAnsi(colorString, isBackground)
}
func write(s rune) {
if isInvisible {
return
@ -430,7 +426,7 @@ func writeSegmentColors() {
switch {
case fg.IsTransparent() && len(BackgroundColor) != 0:
background := getAnsiFromColorString(BackgroundColor, false)
background := Colors.ToAnsi(BackgroundColor, false)
writeEscapedAnsiString(fmt.Sprintf(colorise, background))
writeEscapedAnsiString(fmt.Sprintf(colorise, bg.ToForeground()))
case fg.IsTransparent() && !bg.IsEmpty():
@ -496,7 +492,7 @@ func writeArchorOverride(match map[string]string, background color.Ansi, i int)
currentColor.Add(bg, fg)
if currentColor.Foreground().IsTransparent() && len(BackgroundColor) != 0 {
background := getAnsiFromColorString(BackgroundColor, false)
background := Colors.ToAnsi(BackgroundColor, false)
writeEscapedAnsiString(fmt.Sprintf(colorise, background))
writeEscapedAnsiString(fmt.Sprintf(colorise, currentColor.Background().ToForeground()))
return position
@ -606,12 +602,20 @@ func asAnsiColors(background, foreground color.Ansi) (color.Ansi, color.Ansi) {
background = background.Resolve(CurrentColors, ParentColors)
foreground = foreground.Resolve(CurrentColors, ParentColors)
if bg, err := Colors.Resolve(background); err == nil {
background = bg
}
if fg, err := Colors.Resolve(foreground); err == nil {
foreground = fg
}
inverted := foreground == color.Transparent && len(background) != 0
backgroundAnsi := getAnsiFromColorString(background, !inverted)
foregroundAnsi := getAnsiFromColorString(foreground, false)
background = Colors.ToAnsi(background, !inverted)
foreground = Colors.ToAnsi(foreground, false)
return backgroundAnsi, foregroundAnsi
return background, foreground
}
func trimAnsi(text string) string {