2023-09-23 19:42:21 +00:00
|
|
|
|
package format
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"strings"
|
|
|
|
|
|
2024-02-25 17:03:01 +00:00
|
|
|
|
"gitea.zaclys.com/bvaudour/gob/option"
|
2023-09-23 19:42:21 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Color permet de colorer une chaîne dans un terminal de type UNIX.
|
|
|
|
|
type Color struct {
|
2024-02-25 17:03:01 +00:00
|
|
|
|
option.Option[int]
|
2023-09-23 19:42:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 {
|
2024-02-25 17:03:01 +00:00
|
|
|
|
return Color{option.Some(v | light)}
|
2023-09-23 19:42:21 +00:00
|
|
|
|
}
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Dark retourne l’équivalent foncé de la couleur.
|
|
|
|
|
func (c Color) Dark() Color {
|
|
|
|
|
if v, ok := c.Get(); ok {
|
2024-02-25 17:03:01 +00:00
|
|
|
|
return Color{option.Some(v & dark)}
|
2023-09-23 19:42:21 +00:00
|
|
|
|
}
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Background retourne la couleur équivalente d’arrière-plan.
|
|
|
|
|
func (c Color) Background() Color {
|
|
|
|
|
if v, ok := c.Get(); ok {
|
2024-02-25 17:03:01 +00:00
|
|
|
|
return Color{option.Some(v | background)}
|
2023-09-23 19:42:21 +00:00
|
|
|
|
}
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Foreground retourne la couleur équivalente de police.
|
|
|
|
|
func (c Color) Foreground() Color {
|
|
|
|
|
if v, ok := c.Get(); ok {
|
2024-02-25 17:03:01 +00:00
|
|
|
|
return Color{option.Some(v & foreground)}
|
2023-09-23 19:42:21 +00:00
|
|
|
|
}
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Color retourne la composante couleur de base de la couleur.
|
|
|
|
|
func (c Color) Color() Color {
|
|
|
|
|
if v, ok := c.Get(); ok {
|
2024-02-25 17:03:01 +00:00
|
|
|
|
return Color{option.Some(v & white)}
|
2023-09-23 19:42:21 +00:00
|
|
|
|
}
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Color retourne la composante couleur foncée/claire de la couleur .
|
2024-02-25 17:03:01 +00:00
|
|
|
|
func (c Color) Base() (out option.Option[int]) {
|
2023-09-23 19:42:21 +00:00
|
|
|
|
v, ok := c.Get()
|
|
|
|
|
if !ok {
|
2024-02-25 17:03:01 +00:00
|
|
|
|
return
|
2023-09-23 19:42:21 +00:00
|
|
|
|
}
|
|
|
|
|
b := 30 + (v & white)
|
|
|
|
|
if c.IsBackground() {
|
|
|
|
|
b += 10
|
|
|
|
|
}
|
|
|
|
|
if c.IsLight() {
|
|
|
|
|
b += 60
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-25 17:03:01 +00:00
|
|
|
|
return option.Some(b)
|
2023-09-23 19:42:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-24 19:57:05 +00:00
|
|
|
|
// Esc retourne l’échappement ASCII complet.
|
|
|
|
|
func (c Color) Esc(force ...bool) string {
|
|
|
|
|
return fmt.Sprintf(escTpl, c.String(force...))
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-23 19:42:21 +00:00
|
|
|
|
// 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 {
|
2024-02-25 17:03:01 +00:00
|
|
|
|
c = Color{option.Some(v)}
|
2023-09-23 19:42:21 +00:00
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
|
}
|