aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Jarry <robin@jarry.cc>2023-06-08 22:16:31 +0200
committerRobin Jarry <robin@jarry.cc>2023-06-10 23:54:06 +0200
commit9479513ec138b0e4b2ad2c53a0566c00c7035845 (patch)
tree98ce844e82eeebf2151a3c0fa1ac1b530964f344
parent8162c5be8f251e985a18928ed1a8cb571df40945 (diff)
downloadaerc-9479513ec138b0e4b2ad2c53a0566c00c7035845.tar.gz
templates: add map functions
Similar to switch and .StyleSwitch, add map and .StyleMap to work on lists. An extra "exclude" item is available to filter elements out of the list. Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Inwit <inwit@sindominio.net>
-rw-r--r--commands/commands_test.go2
-rw-r--r--config/templates.go2
-rw-r--r--doc/aerc-templates.7.scd19
-rw-r--r--lib/state/templates.go20
-rw-r--r--lib/templates/functions.go30
-rw-r--r--models/templates.go2
6 files changed, 75 insertions, 0 deletions
diff --git a/commands/commands_test.go b/commands/commands_test.go
index e510ebe1..7c3ec84f 100644
--- a/commands/commands_test.go
+++ b/commands/commands_test.go
@@ -106,3 +106,5 @@ func (d *dummyData) PendingKeys() string { return "" }
func (d *dummyData) Role() string { return "inbox" }
func (d *dummyData) Style(string, string) string { return "" }
func (d *dummyData) StyleSwitch(string, ...models.Case) string { return "" }
+
+func (d *dummyData) StyleMap([]string, ...models.Case) []string { return []string{} }
diff --git a/config/templates.go b/config/templates.go
index 40e7e450..97ba89b8 100644
--- a/config/templates.go
+++ b/config/templates.go
@@ -108,3 +108,5 @@ func (d *dummyData) Role() string { return "inbox" }
func (d *dummyData) Style(string, string) string { return "" }
func (d *dummyData) StyleSwitch(string, ...models.Case) string { return "" }
+
+func (d *dummyData) StyleMap([]string, ...models.Case) []string { return []string{} }
diff --git a/doc/aerc-templates.7.scd b/doc/aerc-templates.7.scd
index 6919e5dd..394e22b6 100644
--- a/doc/aerc-templates.7.scd
+++ b/doc/aerc-templates.7.scd
@@ -402,6 +402,16 @@ aerc provides the following additional functions:
{{.StyleSwitch (.From | names | join ", ") (case `Tim` "cyan") (case `Robin` "pink-blink") (default "blue")}}
```
+*.StyleMap*
+ Apply user-defined styles (see *aerc-stylesets*(7)) to elements of
+ a string list. The logic is the same than *.StyleSwitch* but works on
+ a list of elements. An additional *exclude* option is available to
+ remove the matching elements from the list.
+
+ ```
+ {{.StyleMap .Labels (exclude .Folder) (exclude `^spam$`) (case `^inbox$` "red") (case `^Archive/.*` "green") (default "blue") | join " "}}
+ ```
+
*version*
Returns the version of aerc, which can be useful for things like X-Mailer.
@@ -426,6 +436,15 @@ aerc provides the following additional functions:
{{switch .Folder (case `^INBOX$` "📥") (case `^Archive/.*` "🗃") (default "📁")}}
```
+*map*
+ Transform a string list into another one. The logic is the same than
+ *switch* but works on a list of elements. An additional *exclude* option
+ is available to remove the matching elements from the list.
+
+ ```
+ {{map .Labels (exclude .Folder) (exclude `^spam$`) (case `^inbox$` "📥") (case `^Archive/.*` "🗃") | join " "}}
+ ```
+
*Function chaining*
All of the template functions can be chained together if needed.
diff --git a/lib/state/templates.go b/lib/state/templates.go
index 8c7df3e8..36f7b725 100644
--- a/lib/state/templates.go
+++ b/lib/state/templates.go
@@ -560,3 +560,23 @@ func (d *templateData) StyleSwitch(content string, cases ...models.Case) string
}
return content
}
+
+func (d *templateData) StyleMap(elems []string, cases ...models.Case) []string {
+ mapped := make([]string, 0, len(elems))
+top:
+ for _, e := range elems {
+ for _, c := range cases {
+ if c.Matches(e) {
+ if c.Skip() {
+ continue top
+ }
+ cfg := config.Ui.ForAccount(d.Account())
+ style := cfg.GetUserStyle(c.Value())
+ e = parse.ApplyStyle(style, e)
+ break
+ }
+ }
+ mapped = append(mapped, e)
+ }
+ return mapped
+}
diff --git a/lib/templates/functions.go b/lib/templates/functions.go
index b331dc85..9380bc7b 100644
--- a/lib/templates/functions.go
+++ b/lib/templates/functions.go
@@ -255,12 +255,18 @@ func compactDir(path string) string {
type (
Case struct{ expr, value string }
Default struct{ value string }
+ Exclude struct{ expr string }
)
func (c *Case) Matches(s string) bool { return parse.MatchCache(s, c.expr) }
func (c *Case) Value() string { return c.value }
+func (c *Case) Skip() bool { return false }
func (d *Default) Matches(s string) bool { return true }
func (d *Default) Value() string { return d.value }
+func (d *Default) Skip() bool { return false }
+func (e *Exclude) Matches(s string) bool { return parse.MatchCache(s, e.expr) }
+func (e *Exclude) Value() string { return "" }
+func (e *Exclude) Skip() bool { return true }
func switch_(value string, cases ...models.Case) string {
for _, c := range cases {
@@ -279,6 +285,28 @@ func default_(value string) models.Case {
return &Default{value: value}
}
+func exclude(expr string) models.Case {
+ return &Exclude{expr: expr}
+}
+
+func map_(elements []string, cases ...models.Case) []string {
+ mapped := make([]string, 0, len(elements))
+top:
+ for _, e := range elements {
+ for _, c := range cases {
+ if c.Matches(e) {
+ if c.Skip() {
+ continue top
+ }
+ e = c.Value()
+ break
+ }
+ }
+ mapped = append(mapped, e)
+ }
+ return mapped
+}
+
var templateFuncs = template.FuncMap{
"quote": quote,
"wrapText": wrapText,
@@ -304,4 +332,6 @@ var templateFuncs = template.FuncMap{
"switch": switch_,
"case": case_,
"default": default_,
+ "map": map_,
+ "exclude": exclude,
}
diff --git a/models/templates.go b/models/templates.go
index ae57c3fb..eb696ccc 100644
--- a/models/templates.go
+++ b/models/templates.go
@@ -51,9 +51,11 @@ type TemplateData interface {
PendingKeys() string
Style(string, string) string
StyleSwitch(string, ...Case) string
+ StyleMap([]string, ...Case) []string
}
type Case interface {
Matches(string) bool
Value() string
+ Skip() bool
}