You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
1.2 KiB

4 years ago
package formatter
import (
"bytes"
"context"
"regexp"
"gitoa.ru/go-4devs/console/output/style"
)
//nolint: gochecknoglobals
var re = regexp.MustCompile(`<(([a-z][^<>]+)|/([a-z][^<>]+)?)>`)
func WithStyle(styles func(string) (style.Style, error)) func(*Formatter) {
return func(f *Formatter) {
f.styles = styles
}
}
func New(opts ...func(*Formatter)) *Formatter {
f := &Formatter{
styles: style.Find,
}
for _, opt := range opts {
opt(f)
}
return f
}
type Formatter struct {
styles func(string) (style.Style, error)
}
func (a *Formatter) Format(ctx context.Context, msg string) string {
var (
out bytes.Buffer
cur int
)
for _, idx := range re.FindAllStringIndex(msg, -1) {
tag := msg[idx[0]+1 : idx[1]-1]
if cur < idx[0] {
out.WriteString(msg[cur:idx[0]])
}
var (
st style.Style
err error
)
switch {
case tag[0:1] == "/":
st, err = a.styles(tag[1:])
if err == nil {
out.WriteString(st.Set(style.ActionUnset))
}
default:
st, err = a.styles(tag)
if err == nil {
out.WriteString(st.Set(style.ActionSet))
}
}
if err != nil {
cur = idx[0]
} else {
cur = idx[1]
}
}
if len(msg) > cur {
out.WriteString(msg[cur:])
}
return out.String()
}