mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-01-03 15:27:26 -08:00
103 lines
2.7 KiB
Go
103 lines
2.7 KiB
Go
package color
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
type Palette map[string]string
|
|
|
|
const (
|
|
paletteKeyPrefix = "p:"
|
|
paletteKeyError = "palette: requested color %s does not exist in palette of colors %s"
|
|
paletteMaxRecursionDepth = 3 // allows 3 or less recusive resolutions
|
|
paletteRecursiveKeyError = "palette: recursive resolution of color %s returned palette reference %s and reached recursion depth %d"
|
|
)
|
|
|
|
// ResolveColor gets a color value from the palette using given colorName.
|
|
// If colorName is not a palette reference, it is returned as is.
|
|
func (p Palette) ResolveColor(colorName string) (string, error) {
|
|
return p.resolveColor(colorName, 1, &colorName)
|
|
}
|
|
|
|
// originalColorName is a pointer to save allocations
|
|
func (p Palette) resolveColor(colorName string, depth int, originalColorName *string) (string, error) {
|
|
key, ok := asPaletteKey(colorName)
|
|
// colorName is not a palette key, return it as is
|
|
if !ok {
|
|
return colorName, nil
|
|
}
|
|
|
|
color, ok := p[key]
|
|
if !ok {
|
|
return "", &PaletteKeyError{Key: key, palette: p}
|
|
}
|
|
|
|
if _, isKey := isPaletteKey(color); isKey {
|
|
if depth > paletteMaxRecursionDepth {
|
|
return "", &PaletteRecursiveKeyError{Key: *originalColorName, Value: color, depth: depth}
|
|
}
|
|
|
|
return p.resolveColor(color, depth+1, originalColorName)
|
|
}
|
|
|
|
return color, nil
|
|
}
|
|
|
|
func asPaletteKey(colorName string) (string, bool) {
|
|
prefix, isKey := isPaletteKey(colorName)
|
|
if !isKey {
|
|
return "", false
|
|
}
|
|
|
|
key := strings.TrimPrefix(colorName, prefix)
|
|
|
|
return key, true
|
|
}
|
|
|
|
func isPaletteKey(colorName string) (string, bool) {
|
|
return paletteKeyPrefix, strings.HasPrefix(colorName, paletteKeyPrefix)
|
|
}
|
|
|
|
// PaletteKeyError records the missing Palette key.
|
|
type PaletteKeyError struct {
|
|
Key string
|
|
palette Palette
|
|
}
|
|
|
|
func (p *PaletteKeyError) Error() string {
|
|
keys := make([]string, 0, len(p.palette))
|
|
for key := range p.palette {
|
|
keys = append(keys, key)
|
|
}
|
|
sort.Strings(keys)
|
|
allColors := strings.Join(keys, ",")
|
|
errorStr := fmt.Sprintf(paletteKeyError, p.Key, allColors)
|
|
return errorStr
|
|
}
|
|
|
|
// PaletteRecursiveKeyError records the Palette key and resolved color value (which
|
|
// is also a Palette key)
|
|
type PaletteRecursiveKeyError struct {
|
|
Key string
|
|
Value string
|
|
depth int
|
|
}
|
|
|
|
func (p *PaletteRecursiveKeyError) Error() string {
|
|
errorStr := fmt.Sprintf(paletteRecursiveKeyError, p.Key, p.Value, p.depth)
|
|
return errorStr
|
|
}
|
|
|
|
// maybeResolveColor wraps resolveColor and silences possible errors, returning
|
|
// Transparent color by default, as a Block does not know how to handle color errors.
|
|
func (p Palette) MaybeResolveColor(colorName string) string {
|
|
color, err := p.ResolveColor(colorName)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
return color
|
|
}
|