gob/format/color.go

228 lines
4.4 KiB
Go
Raw Normal View History

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 cest une couleur darrière-plan.
func (c Color) IsBackground() bool {
v, ok := c.Get()
return ok && v&background != 0
}
// IsForeground retourne vrai si cest 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 darriè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
// darriè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)
}