package style import ( "errors" "fmt" "strings" "sync" ) //nolint: gochecknoglobals var ( styles = map[string]Style{ "error": {Foreground: White, Background: Red}, "info": {Foreground: Green}, "comment": {Foreground: Yellow}, "question": {Foreground: Black, Background: Cyan}, } stylesMu sync.Mutex empty = Style{} ) var ( ErrNotFound = errors.New("console: style not found") ErrDuplicateStyle = errors.New("console: Register called twice") ) func Empty() Style { return empty } func Find(name string) (Style, error) { if st, has := styles[name]; has { return st, nil } return empty, ErrNotFound } func Register(name string, style Style) error { stylesMu.Lock() defer stylesMu.Unlock() if _, has := styles[name]; has { return fmt.Errorf("%w for style %s", ErrDuplicateStyle, name) } styles[name] = style return nil } func MustRegister(name string, style Style) { if err := Register(name, style); err != nil { panic(err) } } type Style struct { Background Color Foreground Color Options []Option } func (s Style) Apply(msg string) string { return s.Set(ActionSet) + msg + s.Set(ActionUnset) } func (s Style) Set(action int) string { style := make([]string, 0, len(s.Options)) if s.Foreground != "" { style = append(style, "3"+s.Foreground.Apply(action)) } if s.Background != "" { style = append(style, "4"+s.Background.Apply(action)) } for _, opt := range s.Options { style = append(style, opt.Apply(action)) } if len(style) == 0 { return "" } return "\033[" + strings.Join(style, ";") + "m" }