From 5df1ebce35bd8e5f98ca44d7ce8f2ffc0fe99d33 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello <info@fabiomanganiello.com> Date: Sun, 6 Nov 2022 01:22:52 +0100 Subject: [PATCH] Merged patch from https://lists.sr.ht/~rjarry/aerc-devel/patches/34390 Reference: https://lists.sr.ht/~rjarry/aerc-devel/patches/34390 --- commands/compose/markup.go | 36 ++++++++++++++++++++++++++++++ config/config.go | 17 ++++++++++++++ doc/aerc-config.5.scd | 16 ++++++++++++++ doc/aerc.1.scd | 6 +++++ widgets/compose.go | 45 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+) create mode 100644 commands/compose/markup.go diff --git a/commands/compose/markup.go b/commands/compose/markup.go new file mode 100644 index 0000000..2f646c1 --- /dev/null +++ b/commands/compose/markup.go @@ -0,0 +1,36 @@ +package compose + +import ( + "fmt" + "git.sr.ht/~rjarry/aerc/widgets" +) + +type MarkUp struct{} + +func init() { + register(MarkUp{}) +} + +func (MarkUp) Aliases() []string { + return []string{"markup"} +} + +func (MarkUp) Complete(aerc *widgets.Aerc, args []string) []string { + composer, _ := aerc.SelectedTabContent().(*widgets.Composer) + return composer.GetMarkups() +} + +func (MarkUp) Execute(aerc *widgets.Aerc, args []string) error { + if len(args) != 2 { + return fmt.Errorf("Usage: :markup <label>") + } + markupKey := args[1] + composer, _ := aerc.SelectedTabContent().(*widgets.Composer) + if err := composer.GenerateMarkup(markupKey); err != nil { + aerc.PushError(err.Error()) + return err + } else { + aerc.PushSuccess(fmt.Sprintf("Markup generated")) + } + return nil +} diff --git a/config/config.go b/config/config.go index a15e1d5..adcbeef 100644 --- a/config/config.go +++ b/config/config.go @@ -253,6 +253,11 @@ type TemplateConfig struct { Forwards string `ini:"forwards"` } +type MarkupConfig struct { + Name string + Cmd string +} + type AercConfig struct { Bindings BindingConfig ContextualBinds []BindingConfigContext @@ -267,6 +272,7 @@ type AercConfig struct { ContextualUis []UIConfigContext General GeneralConfig Templates TemplateConfig + Markups []MarkupConfig Openers map[string][]string } @@ -616,6 +622,17 @@ func (config *AercConfig) LoadConfig(file *ini.File) error { } } + if markupsSec, err := file.GetSection("markups"); err == nil { + for _, markupKey := range markupsSec.KeyStrings() { + markupCmd := markupsSec.KeysHash()[markupKey] + mark := MarkupConfig{ + Name: markupKey, + Cmd: markupCmd, + } + config.Markups = append(config.Markups, mark) + } + } + // append default paths to template-dirs and styleset-dirs for _, dir := range SearchDirs { config.Ui.StyleSetDirs = append( diff --git a/doc/aerc-config.5.scd b/doc/aerc-config.5.scd index 94dfb59..fba9e9a 100644 --- a/doc/aerc-config.5.scd +++ b/doc/aerc-config.5.scd @@ -602,6 +602,22 @@ text/plain=gvim {} +125 message/rfc822=thunderbird ``` +## MARKUPS + +Markups allows you to pipe the content of a message being composed through a +shell command to generate HTML markup from the plaintext message. Markups +can be defined in *[markups]* section within aerc.conf. + +Example: +``` +[markups] +work=pandoc -f markdown -t html --template=company.tpl +``` + +The command *:markup* becomes available during the compose-review stage, and +will only append text/html part to the email if the shell command exits +successfully and content is written to standard output. + ## TRIGGERS Triggers specify commands to execute when certain events occur. diff --git a/doc/aerc.1.scd b/doc/aerc.1.scd index f3c0e52..b490e8b 100644 --- a/doc/aerc.1.scd +++ b/doc/aerc.1.scd @@ -500,6 +500,12 @@ message list, the message in the message viewer, etc). *edit* (Re-) opens your text editor to edit the message in progress. +*markup* <label> + Passes the message to external command, and appends result as text/html + message part. The label and command is defined under the *markups* section + configuration. For details on configuring markup support consult + *aerc-config*(5). + *next-field*, *prev-field* Cycles between input fields in the compose window. diff --git a/widgets/compose.go b/widgets/compose.go index 6e34365..245bd40 100644 --- a/widgets/compose.go +++ b/widgets/compose.go @@ -529,6 +529,51 @@ func (c *Composer) readSignatureFromFile() []byte { return signature } +func (c *Composer) GenerateMarkup(markupKey string) error { + markupCmd, err := c.getMarkupCmdByName(markupKey) + if err != nil { + return err + } + proc := exec.Command("sh", "-c", markupCmd) + stdin, err := proc.StdinPipe() + if err != nil { + return err + } + go func() { + defer stdin.Close() + io.Copy(stdin, c.email) + }() + outBytes, err := proc.Output() + if err != nil { + return err + } + if len(outBytes) < 1 { + return fmt.Errorf("markup %s did not generate content", markupKey) + } + ioReader := bytes.NewReader(outBytes) + return c.AppendPart("text/html", nil, ioReader) +} + +func (c *Composer) GetMarkups() []string { + if len(c.config.Markups) < 1 { + return nil + } + markupKeys := []string{} + for _, cmd := range c.config.Markups { + markupKeys = append(markupKeys, cmd.Name) + } + return markupKeys +} + +func (c *Composer) getMarkupCmdByName(markupKey string) (string, error) { + for _, markupConfig := range c.config.Markups { + if markupConfig.Name == markupKey { + return markupConfig.Cmd, nil + } + } + return "", fmt.Errorf("unknown markup label %s", markupKey) +} + func (c *Composer) FocusTerminal() *Composer { c.Lock() defer c.Unlock()