package format import ( "fmt" "strings" "gitea.zaclys.com/bvaudour/gob/option" ) // Color permet de colorer une chaîne dans un terminal de type UNIX. type Color struct { option.Option[int] } const ( black int = iota red green yellow blue majenta cyan white light = 1 << 3 background = 1 << 4 dark = ^light foreground = ^dark ) var colors = map[string]int{ "black": black, "red": red, "green": green, "yellow": yellow, "blue": blue, "majenta": majenta, "cyan": cyan, "white": white, } var prefixes = []string{ "fg_l_", "fg_", "l_", "bg_l_", "bg_", } var prefixFuncs = map[string]func(string) Color{ "fg_l_": fgLightColor, "fg_": fgColor, "l_": fgLightColor, "bg_l_": bgLightColor, "bg_": bgColor, } // IsLight retourne vrai si la couleur est claire. func (c Color) IsLight() bool { v, ok := c.Get() return ok && v&light != 0 } // IsDark retourne vrai si la couleur est foncée. func (c Color) IsDark() bool { v, ok := c.Get() return ok && v&light == 0 } // IsBackground retourne vrai si c’est une couleur d’arrière-plan. func (c Color) IsBackground() bool { v, ok := c.Get() return ok && v&background != 0 } // IsForeground retourne vrai si c’est une couleur de police. func (c Color) IsForeground() bool { v, ok := c.Get() return ok && v&background == 0 } // Light retourne l’équivalent clair de la couleur. func (c Color) Light() Color { if v, ok := c.Get(); ok { return Color{option.Some(v | light)} } return c } // Dark retourne l’équivalent foncé de la couleur. func (c Color) Dark() Color { if v, ok := c.Get(); ok { return Color{option.Some(v & dark)} } return c } // Background retourne la couleur équivalente d’arrière-plan. func (c Color) Background() Color { if v, ok := c.Get(); ok { return Color{option.Some(v | background)} } return c } // Foreground retourne la couleur équivalente de police. func (c Color) Foreground() Color { if v, ok := c.Get(); ok { return Color{option.Some(v & foreground)} } return c } // Color retourne la composante couleur de base de la couleur. func (c Color) Color() Color { if v, ok := c.Get(); ok { return Color{option.Some(v & white)} } return c } // Color retourne la composante couleur foncée/claire de la couleur . func (c Color) Base() (out option.Option[int]) { v, ok := c.Get() if !ok { return } b := 30 + (v & white) if c.IsBackground() { b += 10 } if c.IsLight() { b += 60 } return option.Some(b) } // String retourne la valeur d’échappement ASCII de la couleur. func (c Color) String(force ...bool) string { b, ok := c.Base().Get() if !ok { return "" } s := fmt.Sprint(b) if len(force) > 0 && force[0] && !c.IsLight() && !c.IsBackground() { s = "2;" + s } return s } // Esc retourne l’échappement ASCII complet. func (c Color) Esc(force ...bool) string { return fmt.Sprintf(escTpl, c.String(force...)) } // Format colore la chaîne donnée selon la couleur spécifiée. func (c Color) Format(text string) string { if !c.IsDefined() { return text } return fmt.Sprintf(formatTpl, c.String(), text) } func colorOf(name string) (c Color) { if v, ok := colors[name]; ok { c = Color{option.Some(v)} } return } func fgDarkColor(name string) Color { return colorOf(name) } func fgLightColor(name string) (c Color) { return colorOf(name).Light() } func fgColor(name string) Color { if strings.HasPrefix(name, "l_") { n := strings.TrimPrefix(name, "l_") return fgLightColor(n) } return fgDarkColor(name) } func bgDarkColor(name string) Color { return colorOf(name).Background() } func bgLightColor(name string) (c Color) { return colorOf(name).Background().Light() } func bgColor(name string) Color { if strings.HasPrefix(name, "l_") { n := strings.TrimPrefix(name, "l_") return bgLightColor(n) } return bgDarkColor(name) } // ColorOf retourne la couleur au nom demandé. // Les noms possibles sont : // - white // - black // - red // - green // - blue // - yellow // - magenta // - cyan // Le préfixe l_ peut être rajouté à la couleur pour forcer le mode clair. // Le préfixe bg_ ou fg_ peut être ajouté pour forcer, respectivement la couleur // d’arrière-plan ou de police (mode par défaut). func ColorOf(name string) Color { for _, prefix := range prefixes { if strings.HasPrefix(name, prefix) { n := strings.TrimPrefix(name, prefix) return prefixFuncs[prefix](n) } } return colorOf(name) }