zk/adapter/term/styler.go

121 lines
3.2 KiB
Go

package term
import (
"fmt"
"github.com/fatih/color"
"github.com/mickael-menu/zk/core/style"
)
// Style implements style.Styler using ANSI escape codes to be used with a terminal.
func (t *Terminal) Style(text string, rules ...style.Rule) (string, error) {
if text == "" {
return text, nil
}
attrs, err := attributes(expandThemeAliases(rules))
if err != nil {
return "", err
}
if len(attrs) == 0 {
return text, nil
}
return color.New(attrs...).Sprint(text), nil
}
func (t *Terminal) MustStyle(text string, rules ...style.Rule) string {
text, err := t.Style(text, rules...)
if err != nil {
panic(err.Error())
}
return text
}
// FIXME: User config
var themeAliases = map[style.Rule][]style.Rule{
"title": {"bold", "yellow"},
"path": {"underline", "cyan"},
"term": {"red"},
"emphasis": {"bold", "cyan"},
"understate": {"faint"},
}
func expandThemeAliases(rules []style.Rule) []style.Rule {
expanded := make([]style.Rule, 0)
for _, rule := range rules {
aliases, ok := themeAliases[rule]
if ok {
aliases = expandThemeAliases(aliases)
for _, alias := range aliases {
expanded = append(expanded, alias)
}
} else {
expanded = append(expanded, rule)
}
}
return expanded
}
var attrsMapping = map[style.Rule]color.Attribute{
style.RuleBold: color.Bold,
style.RuleFaint: color.Faint,
style.RuleItalic: color.Italic,
style.RuleUnderline: color.Underline,
style.RuleBlink: color.BlinkSlow,
style.RuleReverse: color.ReverseVideo,
style.RuleHidden: color.Concealed,
style.RuleStrikethrough: color.CrossedOut,
style.RuleBlack: color.FgBlack,
style.RuleRed: color.FgRed,
style.RuleGreen: color.FgGreen,
style.RuleYellow: color.FgYellow,
style.RuleBlue: color.FgBlue,
style.RuleMagenta: color.FgMagenta,
style.RuleCyan: color.FgCyan,
style.RuleWhite: color.FgWhite,
style.RuleBlackBg: color.BgBlack,
style.RuleRedBg: color.BgRed,
style.RuleGreenBg: color.BgGreen,
style.RuleYellowBg: color.BgYellow,
style.RuleBlueBg: color.BgBlue,
style.RuleMagentaBg: color.BgMagenta,
style.RuleCyanBg: color.BgCyan,
style.RuleWhiteBg: color.BgWhite,
style.RuleBrightBlack: color.FgHiBlack,
style.RuleBrightRed: color.FgHiRed,
style.RuleBrightGreen: color.FgHiGreen,
style.RuleBrightYellow: color.FgHiYellow,
style.RuleBrightBlue: color.FgHiBlue,
style.RuleBrightMagenta: color.FgHiMagenta,
style.RuleBrightCyan: color.FgHiCyan,
style.RuleBrightWhite: color.FgHiWhite,
style.RuleBrightBlackBg: color.BgHiBlack,
style.RuleBrightRedBg: color.BgHiRed,
style.RuleBrightGreenBg: color.BgHiGreen,
style.RuleBrightYellowBg: color.BgHiYellow,
style.RuleBrightBlueBg: color.BgHiBlue,
style.RuleBrightMagentaBg: color.BgHiMagenta,
style.RuleBrightCyanBg: color.BgHiCyan,
style.RuleBrightWhiteBg: color.BgHiWhite,
}
func attributes(rules []style.Rule) ([]color.Attribute, error) {
attrs := make([]color.Attribute, 0)
for _, rule := range rules {
attr, ok := attrsMapping[rule]
if !ok {
return attrs, fmt.Errorf("unknown styling rule: %v", rule)
} else {
attrs = append(attrs, attr)
}
}
return attrs, nil
}