aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--commands/commands.go52
-rw-r--r--lib/templates/template.go52
-rw-r--r--main.go3
3 files changed, 107 insertions, 0 deletions
diff --git a/commands/commands.go b/commands/commands.go
index f50a1e8a..c6f95aaa 100644
--- a/commands/commands.go
+++ b/commands/commands.go
@@ -141,6 +141,58 @@ func (cmds *Commands) ExecuteCommand(
return NoSuchCommand(args[0])
}
+func GetTemplateCompletion(
+ aerc *widgets.Aerc, cmd string,
+) ([]string, string, bool) {
+ args, err := splitCmd(cmd)
+ if err != nil || len(args) == 0 {
+ return nil, "", false
+ }
+
+ countLeft := strings.Count(cmd, "{{")
+ if countLeft == 0 {
+ return nil, "", false
+ }
+ countRight := strings.Count(cmd, "}}")
+
+ switch {
+ case countLeft > countRight:
+ // complete template terms
+ var i int
+ for i = len(cmd) - 1; i >= 0; i-- {
+ if strings.ContainsRune("{()| ", rune(cmd[i])) {
+ break
+ }
+ }
+ search, prefix := cmd[i+1:], cmd[:i+1]
+ padding := strings.Repeat(" ",
+ len(search)-len(strings.TrimLeft(search, " ")))
+ options := FilterList(
+ templates.Terms(),
+ strings.TrimSpace(search),
+ "",
+ aerc.SelectedAccountUiConfig().FuzzyComplete,
+ )
+ return options, prefix + padding, true
+ case countLeft == countRight:
+ // expand template
+ data := templateData(aerc, nil, nil)
+ t, err := templates.ParseTemplate("", cmd)
+ if err != nil {
+ log.Warnf("template parsing failed: %v", err)
+ return nil, "", false
+ }
+ var sb strings.Builder
+ if err = templates.Render(t, &sb, data); err != nil {
+ log.Warnf("template rendering failed: %v", err)
+ return nil, "", false
+ }
+ return []string{sb.String()}, "", true
+ }
+
+ return nil, "", false
+}
+
// GetCompletions returns the completion options and the command prefix
func (cmds *Commands) GetCompletions(
aerc *widgets.Aerc, cmd string,
diff --git a/lib/templates/template.go b/lib/templates/template.go
index bf257669..6eae591a 100644
--- a/lib/templates/template.go
+++ b/lib/templates/template.go
@@ -6,6 +6,7 @@ import (
"io"
"os"
"path"
+ "reflect"
"text/template"
"git.sr.ht/~rjarry/aerc/models"
@@ -56,3 +57,54 @@ func ParseTemplate(name, content string) (*template.Template, error) {
func Render(t *template.Template, w io.Writer, data models.TemplateData) error {
return t.Execute(w, data)
}
+
+// builtins is a slice of keywords and functions built into the Go standard
+// library for templates. Since they are not exported, they are hardcoded here.
+var builtins = []string{
+ // from the Go standard library: src/text/template/parse/lex.go
+ "block",
+ "break",
+ "continue",
+ "define",
+ "else",
+ "end",
+ "if",
+ "range",
+ "nil",
+ "template",
+ "with",
+
+ // from the Go standard library: src/text/template/funcs.go
+ "and",
+ "call",
+ "html",
+ "index",
+ "slice",
+ "js",
+ "len",
+ "not",
+ "or",
+ "print",
+ "printf",
+ "println",
+ "urlquery",
+ "eq",
+ "ge",
+ "gt",
+ "le",
+ "lt",
+ "ne",
+}
+
+func Terms() []string {
+ var s []string
+ t := reflect.TypeOf((*models.TemplateData)(nil)).Elem()
+ for i := 0; i < t.NumMethod(); i++ {
+ s = append(s, "."+t.Method(i).Name)
+ }
+ for fnStr := range templateFuncs {
+ s = append(s, fnStr)
+ }
+ s = append(s, builtins...)
+ return s
+}
diff --git a/main.go b/main.go
index 9dd166fe..a403c751 100644
--- a/main.go
+++ b/main.go
@@ -89,6 +89,9 @@ func execCommand(
}
func getCompletions(aerc *widgets.Aerc, cmd string) ([]string, string) {
+ if options, prefix, ok := commands.GetTemplateCompletion(aerc, cmd); ok {
+ return options, prefix
+ }
var completions []string
var prefix string
for _, set := range getCommands(aerc.SelectedTabContent()) {