Add semantic style aliases

pull/6/head
Mickaël Menu 3 years ago
parent e47eabf421
commit 81cc8ae9a4
No known key found for this signature in database
GPG Key ID: 53D73664CD359895

@ -6,13 +6,13 @@ import (
"github.com/aymerick/raymond"
"github.com/mickael-menu/zk/adapter/handlebars/helpers"
"github.com/mickael-menu/zk/core"
"github.com/mickael-menu/zk/core/style"
"github.com/mickael-menu/zk/core/templ"
"github.com/mickael-menu/zk/util"
"github.com/mickael-menu/zk/util/errors"
)
func Init(lang string, logger util.Logger, styler core.Styler) {
func Init(lang string, logger util.Logger, styler style.Styler) {
helpers.RegisterDate(logger)
helpers.RegisterPrepend(logger)
helpers.RegisterShell(logger)

@ -5,7 +5,7 @@ import (
"testing"
"time"
"github.com/mickael-menu/zk/core"
"github.com/mickael-menu/zk/core/style"
"github.com/mickael-menu/zk/util"
"github.com/mickael-menu/zk/util/assert"
"github.com/mickael-menu/zk/util/fixtures"
@ -19,7 +19,7 @@ func init() {
// "hello", "red" -> "red(hello)"
type styler struct{}
func (s *styler) Style(text string, rules ...core.StyleRule) (string, error) {
func (s *styler) Style(text string, rules ...style.Rule) (string, error) {
for _, rule := range rules {
text = fmt.Sprintf("%s(%s)", rule, text)
}

@ -4,7 +4,7 @@ import (
"strings"
"github.com/aymerick/raymond"
"github.com/mickael-menu/zk/core"
"github.com/mickael-menu/zk/core/style"
"github.com/mickael-menu/zk/util"
)
@ -13,11 +13,11 @@ import (
//
// {{style "date" created}}
// {{#style "red"}}Hello, world{{/style}}
func RegisterStyle(styler core.Styler, logger util.Logger) {
func RegisterStyle(styler style.Styler, logger util.Logger) {
style := func(keys string, text string) string {
rules := make([]core.StyleRule, 0)
rules := make([]style.Rule, 0)
for _, key := range strings.Fields(keys) {
rules = append(rules, core.StyleRule(key))
rules = append(rules, style.Rule(key))
}
res, err := styler.Style(text, rules...)
if err != nil {

@ -4,7 +4,7 @@ import (
"fmt"
"github.com/fatih/color"
"github.com/mickael-menu/zk/core"
"github.com/mickael-menu/zk/core/style"
)
// Styler is a text styler using ANSI escape codes to be used with a TTY.
@ -14,9 +14,8 @@ func NewStyler() *Styler {
return &Styler{}
}
// FIXME: Semantic rules
func (s *Styler) Style(text string, rules ...core.StyleRule) (string, error) {
attrs, err := s.attributes(rules)
func (s *Styler) Style(text string, rules ...style.Rule) (string, error) {
attrs, err := s.attributes(expandThemeAliases(rules))
if err != nil {
return "", err
}
@ -26,7 +25,32 @@ func (s *Styler) Style(text string, rules ...core.StyleRule) (string, error) {
return color.New(attrs...).Sprint(text), nil
}
var attrsMapping = map[core.StyleRule]color.Attribute{
// FIXME: User config
var themeAliases = map[style.Rule][]style.Rule{
"title": {"bold", "yellow"},
"path": {"cyan"},
"match": {"red"},
}
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{
"reset": color.Reset,
"bold": color.Bold,
"faint": color.Faint,
@ -74,7 +98,7 @@ var attrsMapping = map[core.StyleRule]color.Attribute{
"bright-white-bg": color.BgHiWhite,
}
func (s *Styler) attributes(rules []core.StyleRule) ([]color.Attribute, error) {
func (s *Styler) attributes(rules []style.Rule) ([]color.Attribute, error) {
attrs := make([]color.Attribute, 0)
for _, rule := range rules {

@ -4,7 +4,7 @@ import (
"testing"
"github.com/fatih/color"
"github.com/mickael-menu/zk/core"
"github.com/mickael-menu/zk/core/style"
"github.com/mickael-menu/zk/util/assert"
)
@ -20,30 +20,34 @@ func TestStyleNoRule(t *testing.T) {
}
func TestStyleOneRule(t *testing.T) {
res, err := createStyler().Style("Hello", core.StyleRule("red"))
res, err := createStyler().Style("Hello", style.Rule("red"))
assert.Nil(t, err)
assert.Equal(t, res, "\033[31mHello\033[0m")
}
func TestStyleMultipleRule(t *testing.T) {
res, err := createStyler().Style("Hello", core.StyleRule("red"), core.StyleRule("bold"))
res, err := createStyler().Style("Hello", style.Rule("red"), style.Rule("bold"))
assert.Nil(t, err)
assert.Equal(t, res, "\033[31;1mHello\033[0m")
}
func TestStyleUnknownRule(t *testing.T) {
_, err := createStyler().Style("Hello", core.StyleRule("unknown"))
_, err := createStyler().Style("Hello", style.Rule("unknown"))
assert.Err(t, err, "unknown styling rule: unknown")
}
func TestStyleAllRules(t *testing.T) {
styler := createStyler()
test := func(rule string, expected string) {
res, err := styler.Style("Hello", core.StyleRule(rule))
res, err := styler.Style("Hello", style.Rule(rule))
assert.Nil(t, err)
assert.Equal(t, res, "\033["+expected+"Hello\033[0m")
}
test("title", "1;33m")
test("path", "36m")
test("match", "31m")
test("reset", "0m")
test("bold", "1m")
test("faint", "2m")

@ -7,7 +7,6 @@ import (
"strings"
"time"
"github.com/fatih/color"
"github.com/mickael-menu/zk/core/templ"
"github.com/mickael-menu/zk/util/opt"
)
@ -27,20 +26,6 @@ type Finder interface {
Find(callback func(Match) error, filters ...Filter) error
}
// Unit represents a type of component of note, for example its path or its title.
type Unit int
const (
UnitPath Unit = iota + 1
UnitTitle
UnitBody
UnitSnippet
UnitMatch
UnitWordCount
UnitDate
UnitChecksum
)
type ListOpts struct {
Format opt.String
Filters []Filter
@ -62,7 +47,7 @@ func List(opts ListOpts, deps ListDeps, callback func(formattedNote string) erro
}
return deps.Finder.Find(func(note Match) error {
ft, err := format(note, deps.BasePath)
ft, err := format(note, deps.BasePath, deps.Templates)
if err != nil {
return err
}
@ -77,27 +62,27 @@ func List(opts ListOpts, deps ListDeps, callback func(formattedNote string) erro
var templates = map[string]string{
"path": `{{path}}`,
"oneline": `{{path}} {{title}} ({{date created "elapsed"}})`,
"oneline": `{{style "path" path}} {{style "title" title}} ({{date created "elapsed"}})`,
"short": `{{path}} {{title}} ({{date created "elapsed"}})
"short": `{{style "path" path}} {{style "title" title}} ({{date created "elapsed"}})
{{prepend " " snippet}}
`,
"medium": `{{path}} {{title}}
"medium": `{{style "path" path}} {{style "title" title}}
Created: {{date created "short"}}
{{prepend " " snippet}}
`,
"long": `{{path}} {{title}}
"long": `{{style "path" path}} {{style "title" title}}
Created: {{date created "short"}}
Modified: {{date created "short"}}
{{prepend " " snippet}}
`,
"full": `{{path}} {{title}}
"full": `{{style "path" path}} {{style "title" title}}
Created: {{date created "short"}}
Modified: {{date created "short"}}
@ -116,29 +101,34 @@ func matchTemplate(format opt.String) string {
return templ
}
func format(match Match, basePath string) (*matchRenderContext, error) {
color.NoColor = false // Otherwise the colors are not displayed in `less -r`.
path := color.New(color.FgCyan).SprintFunc()
title := color.New(color.FgYellow).SprintFunc()
term := color.New(color.FgRed).SprintFunc()
func format(match Match, basePath string, templates templ.Loader) (*matchRenderContext, error) {
re := regexp.MustCompile(`<zk:match>(.*?)</zk:match>`)
wd, err := os.Getwd()
if err != nil {
return nil, err
}
pth, err := filepath.Rel(wd, filepath.Join(basePath, match.Path))
path, err := filepath.Rel(wd, filepath.Join(basePath, match.Path))
if err != nil {
return nil, err
}
snippet := strings.TrimSpace(re.ReplaceAllString(match.Snippet, `{{#style "match"}}$1{{/style}}`))
snippetTempl, err := templates.Load(snippet)
if err != nil {
return nil, err
}
snippet, err = snippetTempl.Render(nil)
if err != nil {
return nil, err
}
return &matchRenderContext{
Path: path(pth),
Title: title(match.Title),
Path: path,
Title: match.Title,
Body: match.Body,
WordCount: match.WordCount,
Snippet: strings.TrimSpace(re.ReplaceAllString(match.Snippet, term("$1"))),
Snippet: snippet,
Created: match.Created,
Modified: match.Modified,
}, err

@ -1,20 +1,20 @@
package core
package style
// Styler stylizes text according to predefined styling rules.
//
// A rule key can be either semantic, e.g. "title" or explicit, e.g. "red".
type Styler interface {
Style(text string, rules ...StyleRule) (string, error)
Style(text string, rules ...Rule) (string, error)
}
// StyleRule is a key representing a single styling rule.
type StyleRule string
// Rule is a key representing a single styling rule.
type Rule string
// NullStyler is a Styler with no styling rules.
var NullStyler = nullStyler{}
type nullStyler struct{}
func (s nullStyler) Style(text string, rule ...StyleRule) (string, error) {
func (s nullStyler) Style(text string, rule ...Rule) (string, error) {
return text, nil
}
Loading…
Cancel
Save