oh-my-posh/src/colors.go
Yehor Borkov 9ecd7c09a4
feat(palette): a map of named color values
introducing a map of named standard color
values that can be referenced in theme segments
2021-11-22 15:25:56 +01:00

134 lines
3.7 KiB
Go

package main
import (
"fmt"
"github.com/gookit/color"
)
// MakeColors creates instance of AnsiColors to use in AnsiWriter according to
// environment and configuration.
func MakeColors(env environmentInfo, cfg *Config) AnsiColors {
cacheDisabled := env.getenv("OMP_CACHE_DISABLED") == "1"
return makeColors(cfg.Palette, !cacheDisabled)
}
func makeColors(palette Palette, cacheEnabled bool) (colors AnsiColors) {
colors = &DefaultColors{}
if palette != nil {
colors = &PaletteColors{ansiColors: colors, palette: palette}
}
if cacheEnabled {
colors = &CachedColors{ansiColors: colors}
}
return
}
// DefaultColors is the default AnsiColors implementation.
type DefaultColors struct{}
var (
// Map for color names and their respective foreground [0] or background [1] color codes
ansiColorCodes = map[string][2]AnsiColor{
"black": {"30", "40"},
"red": {"31", "41"},
"green": {"32", "42"},
"yellow": {"33", "43"},
"blue": {"34", "44"},
"magenta": {"35", "45"},
"cyan": {"36", "46"},
"white": {"37", "47"},
"default": {"39", "49"},
"darkGray": {"90", "100"},
"lightRed": {"91", "101"},
"lightGreen": {"92", "102"},
"lightYellow": {"93", "103"},
"lightBlue": {"94", "104"},
"lightMagenta": {"95", "105"},
"lightCyan": {"96", "106"},
"lightWhite": {"97", "107"},
}
)
const (
foregroundIndex = 0
backgroundIndex = 1
)
func (*DefaultColors) AnsiColorFromString(colorString string, isBackground bool) AnsiColor {
if len(colorString) == 0 {
return emptyAnsiColor
}
if colorString == Transparent {
return transparentAnsiColor
}
colorFromName, err := getAnsiColorFromName(colorString, isBackground)
if err == nil {
return colorFromName
}
style := color.HEX(colorString, isBackground)
if style.IsEmpty() {
return emptyAnsiColor
}
return AnsiColor(style.String())
}
// getAnsiColorFromName returns the color code for a given color name if the name is
// known ANSI color name.
func getAnsiColorFromName(colorName string, isBackground bool) (AnsiColor, error) {
if colorCodes, found := ansiColorCodes[colorName]; found {
if isBackground {
return colorCodes[backgroundIndex], nil
}
return colorCodes[foregroundIndex], nil
}
return "", fmt.Errorf("color name %s does not exist", colorName)
}
func IsAnsiColorName(colorString string) bool {
_, ok := ansiColorCodes[colorString]
return ok
}
// PaletteColors is the AnsiColors Decorator that uses the Palette to do named color
// lookups before ANSI color code generation.
type PaletteColors struct {
ansiColors AnsiColors
palette Palette
}
func (p *PaletteColors) AnsiColorFromString(colorString string, isBackground bool) AnsiColor {
paletteColor, err := p.palette.ResolveColor(colorString)
if err != nil {
return emptyAnsiColor
}
ansiColor := p.ansiColors.AnsiColorFromString(paletteColor, isBackground)
return ansiColor
}
// CachedColors is the AnsiColors Decorator that does simple color lookup caching.
// AnsiColorFromString calls are cheap, but not free, and having a simple cache in
// has measurable positive effect on performance.
type CachedColors struct {
ansiColors AnsiColors
colorCache map[cachedColorKey]AnsiColor
}
type cachedColorKey struct {
colorString string
isBackground bool
}
func (c *CachedColors) AnsiColorFromString(colorString string, isBackground bool) AnsiColor {
if c.colorCache == nil {
c.colorCache = make(map[cachedColorKey]AnsiColor)
}
key := cachedColorKey{colorString, isBackground}
if ansiColor, hit := c.colorCache[key]; hit {
return ansiColor
}
ansiColor := c.ansiColors.AnsiColorFromString(colorString, isBackground)
c.colorCache[key] = ansiColor
return ansiColor
}