aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAivars Vaivods <aivars@vaivods.lv>2023-02-01 16:13:54 +0100
committerRobin Jarry <robin@jarry.cc>2023-02-20 14:48:42 +0100
commit420a82a356d53e4b600ba54768f7ed21a43cf85e (patch)
tree86b7ddc08cc0663b167cb678b264995c9e4239de
parent70f99085d73b3bfc9b3338c52e6df7bebc7651c7 (diff)
downloadaerc-420a82a356d53e4b600ba54768f7ed21a43cf85e.tar.gz
commands: expand template placeholders
Interpret go template constructs in all aerc command arguments based on the currently selected account, folder and message (if any). Signed-off-by: Aivars Vaivods <aivars@vaivods.lv> Signed-off-by: Robin Jarry <robin@jarry.cc> Reviewed-by: Tim Culverhouse <tim@timculverhouse.com>
-rw-r--r--CHANGELOG.md1
-rw-r--r--commands/commands.go46
-rw-r--r--doc/aerc.1.scd9
-rw-r--r--lib/state/templates.go9
4 files changed, 61 insertions, 4 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ccd714bd..67d0d264 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
the `[viewer]` section.
- The standard Usenet signature delimiter `"-- "` is now prepended to
`signature-file` and `signature-cmd` if not already present.
+- All `aerc(1)` commands now interpret `aerc-templates(7)` markup.
### Deprecated
diff --git a/commands/commands.go b/commands/commands.go
index 6fe30592..bbd03237 100644
--- a/commands/commands.go
+++ b/commands/commands.go
@@ -1,6 +1,7 @@
package commands
import (
+ "bytes"
"errors"
"sort"
"strings"
@@ -8,7 +9,11 @@ import (
"github.com/google/shlex"
+ "git.sr.ht/~rjarry/aerc/config"
+ "git.sr.ht/~rjarry/aerc/lib/state"
+ "git.sr.ht/~rjarry/aerc/lib/templates"
"git.sr.ht/~rjarry/aerc/log"
+ "git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/widgets"
)
@@ -65,13 +70,52 @@ type CommandSource interface {
Commands() *Commands
}
+func templateData(aerc *widgets.Aerc) models.TemplateData {
+ var folder string
+ var cfg *config.AccountConfig
+ var msg *models.MessageInfo
+
+ acct := aerc.SelectedAccount()
+ if acct != nil {
+ folder = acct.SelectedDirectory()
+ cfg = acct.AccountConfig()
+ msg, _ = acct.SelectedMessage()
+ }
+
+ var data state.TemplateData
+
+ data.SetAccount(cfg)
+ data.SetFolder(folder)
+ data.SetInfo(msg, 0, false)
+
+ return &data
+}
+
func (cmds *Commands) ExecuteCommand(aerc *widgets.Aerc, args []string) error {
if len(args) == 0 {
return errors.New("Expected a command.")
}
if cmd, ok := cmds.dict()[args[0]]; ok {
log.Tracef("executing command %v", args)
- return cmd.Execute(aerc, args)
+ var buf bytes.Buffer
+ data := templateData(aerc)
+
+ processedArgs := make([]string, len(args))
+ for i, arg := range args {
+ t, err := templates.ParseTemplate(arg, arg)
+ if err != nil {
+ return err
+ }
+ err = templates.Render(t, &buf, data)
+ if err != nil {
+ return err
+ }
+ arg = buf.String()
+ buf.Reset()
+ processedArgs[i] = arg
+ }
+
+ return cmd.Execute(aerc, processedArgs)
}
return NoSuchCommand(args[0])
}
diff --git a/doc/aerc.1.scd b/doc/aerc.1.scd
index aac014c9..d4376be7 100644
--- a/doc/aerc.1.scd
+++ b/doc/aerc.1.scd
@@ -54,6 +54,15 @@ as the terminal emulator, *<c-x>* is used to bring up the command interface.
Different commands work in different contexts, depending on the kind of tab you
have selected.
+Dynamic arguments are expanded following *aerc-templates*(7) depending on the
+context. For example, if you have a message selected, the following command:
+
+```
+:filter -f "{{index (.From | emails) 0}}"
+```
+
+Will filter all messages sent by the same sender.
+
Aerc stores a history of commands, which can be cycled through in command mode.
Pressing the up key cycles backwards in history, while pressing down cycles
forwards.
diff --git a/lib/state/templates.go b/lib/state/templates.go
index b199cf25..48106295 100644
--- a/lib/state/templates.go
+++ b/lib/state/templates.go
@@ -47,9 +47,12 @@ func (d *TemplateData) SetInfo(info *models.MessageInfo, num int, marked bool) {
func (d *TemplateData) SetAccount(acct *config.AccountConfig) {
d.account = acct
- d.myAddresses = map[string]bool{acct.From.Address: true}
- for _, addr := range acct.Aliases {
- d.myAddresses[addr.Address] = true
+ d.myAddresses = make(map[string]bool)
+ if acct != nil {
+ d.myAddresses[acct.From.Address] = true
+ for _, addr := range acct.Aliases {
+ d.myAddresses[addr.Address] = true
+ }
}
}