126 lines
3.5 KiB
Go
126 lines
3.5 KiB
Go
package style
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type Chalk struct {
|
|
enabled bool
|
|
codes []string
|
|
}
|
|
|
|
func New() Chalk {
|
|
return Chalk{enabled: true}
|
|
}
|
|
|
|
func Disabled() Chalk {
|
|
return Chalk{enabled: false}
|
|
}
|
|
|
|
func (c Chalk) WithEnabled(enabled bool) Chalk {
|
|
c.enabled = enabled
|
|
return c
|
|
}
|
|
|
|
func (c Chalk) cloneWith(code string) Chalk {
|
|
out := Chalk{enabled: c.enabled, codes: make([]string, 0, len(c.codes)+1)}
|
|
out.codes = append(out.codes, c.codes...)
|
|
out.codes = append(out.codes, code)
|
|
return out
|
|
}
|
|
|
|
func (c Chalk) code(v int) Chalk { return c.cloneWith(strconv.Itoa(v)) }
|
|
|
|
func (c Chalk) Bold() Chalk { return c.code(1) }
|
|
func (c Chalk) Dim() Chalk { return c.code(2) }
|
|
func (c Chalk) Italic() Chalk { return c.code(3) }
|
|
func (c Chalk) Underline() Chalk { return c.code(4) }
|
|
func (c Chalk) Inverse() Chalk { return c.code(7) }
|
|
func (c Chalk) Strikethrough() Chalk { return c.code(9) }
|
|
|
|
func (c Chalk) Black() Chalk { return c.code(30) }
|
|
func (c Chalk) Red() Chalk { return c.code(31) }
|
|
func (c Chalk) Green() Chalk { return c.code(32) }
|
|
func (c Chalk) Yellow() Chalk { return c.code(33) }
|
|
func (c Chalk) Blue() Chalk { return c.code(34) }
|
|
func (c Chalk) Magenta() Chalk { return c.code(35) }
|
|
func (c Chalk) Cyan() Chalk { return c.code(36) }
|
|
func (c Chalk) White() Chalk { return c.code(37) }
|
|
func (c Chalk) Gray() Chalk { return c.code(90) }
|
|
|
|
func (c Chalk) BrightBlack() Chalk { return c.code(90) }
|
|
func (c Chalk) BrightRed() Chalk { return c.code(91) }
|
|
func (c Chalk) BrightGreen() Chalk { return c.code(92) }
|
|
func (c Chalk) BrightYellow() Chalk { return c.code(93) }
|
|
func (c Chalk) BrightBlue() Chalk { return c.code(94) }
|
|
func (c Chalk) BrightMagenta() Chalk { return c.code(95) }
|
|
func (c Chalk) BrightCyan() Chalk { return c.code(96) }
|
|
func (c Chalk) BrightWhite() Chalk { return c.code(97) }
|
|
|
|
func (c Chalk) BgBlack() Chalk { return c.code(40) }
|
|
func (c Chalk) BgRed() Chalk { return c.code(41) }
|
|
func (c Chalk) BgGreen() Chalk { return c.code(42) }
|
|
func (c Chalk) BgYellow() Chalk { return c.code(43) }
|
|
func (c Chalk) BgBlue() Chalk { return c.code(44) }
|
|
func (c Chalk) BgMagenta() Chalk { return c.code(45) }
|
|
func (c Chalk) BgCyan() Chalk { return c.code(46) }
|
|
func (c Chalk) BgWhite() Chalk { return c.code(47) }
|
|
|
|
func (c Chalk) RGB(r, g, b uint8) Chalk {
|
|
return c.cloneWith(fmt.Sprintf("38;2;%d;%d;%d", r, g, b))
|
|
}
|
|
|
|
func (c Chalk) BgRGB(r, g, b uint8) Chalk {
|
|
return c.cloneWith(fmt.Sprintf("48;2;%d;%d;%d", r, g, b))
|
|
}
|
|
|
|
func (c Chalk) Hex(hex string) Chalk {
|
|
if r, g, b, ok := parseHexColor(hex); ok {
|
|
return c.RGB(r, g, b)
|
|
}
|
|
return c
|
|
}
|
|
|
|
func (c Chalk) BgHex(hex string) Chalk {
|
|
if r, g, b, ok := parseHexColor(hex); ok {
|
|
return c.BgRGB(r, g, b)
|
|
}
|
|
return c
|
|
}
|
|
|
|
func (c Chalk) Wrap(text string) string {
|
|
if !c.enabled || len(c.codes) == 0 || text == "" {
|
|
return text
|
|
}
|
|
return "\x1b[" + strings.Join(c.codes, ";") + "m" + text + "\x1b[0m"
|
|
}
|
|
|
|
func (c Chalk) Sprint(v ...any) string {
|
|
return c.Wrap(fmt.Sprint(v...))
|
|
}
|
|
|
|
func (c Chalk) Sprintf(format string, v ...any) string {
|
|
return c.Wrap(fmt.Sprintf(format, v...))
|
|
}
|
|
|
|
var ansiPattern = regexp.MustCompile(`\x1b\[[0-9;]*m`)
|
|
|
|
func StripANSI(s string) string {
|
|
return ansiPattern.ReplaceAllString(s, "")
|
|
}
|
|
|
|
func parseHexColor(hex string) (uint8, uint8, uint8, bool) {
|
|
h := strings.TrimSpace(strings.TrimPrefix(hex, "#"))
|
|
if len(h) != 6 {
|
|
return 0, 0, 0, false
|
|
}
|
|
v, err := strconv.ParseUint(h, 16, 32)
|
|
if err != nil {
|
|
return 0, 0, 0, false
|
|
}
|
|
return uint8(v >> 16), uint8((v >> 8) & 0xff), uint8(v & 0xff), true
|
|
}
|