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() }