aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSrivathsan Murali <sri@vathsan.com>2019-11-03 13:51:14 +0100
committerDrew DeVault <sir@cmpwn.com>2019-11-10 10:15:49 -0500
commit3ba69edab5f0c787424dac9649e43a7743da13ca (patch)
treebccbdd4e1844cc89f011839f0d6557012a14d1d0 /lib
parentad68a9e4e471eb708893ad16601ab14a4672a2da (diff)
Add Templates with Parsing
+ Changes NewComposer to return error. + Add lib to handle templates using "text/template". + Add -T option to following commands - compose. - reply - forward + Quoted replies using templates. + Forwards as body using templates + Default templates are installed similar to filters. + Templates Config in aerc.conf. - Required templates are parsed while loading config. + Add aerc-templates.7 manual for using template data.
Diffstat (limited to 'lib')
-rw-r--r--lib/templates/template.go160
1 files changed, 160 insertions, 0 deletions
diff --git a/lib/templates/template.go b/lib/templates/template.go
new file mode 100644
index 0000000..c09bf4d
--- /dev/null
+++ b/lib/templates/template.go
@@ -0,0 +1,160 @@
+package templates
+
+import (
+ "bytes"
+ "errors"
+ "net/mail"
+ "os"
+ "path"
+ "strings"
+ "text/template"
+ "time"
+
+ "github.com/mitchellh/go-homedir"
+)
+
+type TemplateData struct {
+ To []*mail.Address
+ Cc []*mail.Address
+ Bcc []*mail.Address
+ From []*mail.Address
+ Date time.Time
+ Subject string
+ // Only available when replying with a quote
+ OriginalText string
+ OriginalFrom []*mail.Address
+ OriginalDate time.Time
+}
+
+func TestTemplateData() TemplateData {
+ defaults := map[string]string{
+ "To": "John Doe <john@example.com>",
+ "Cc": "Josh Doe <josh@example.com>",
+ "From": "Jane Smith <jane@example.com>",
+ "Subject": "This is only a test",
+ "OriginalText": "This is only a test text",
+ "OriginalFrom": "John Doe <john@example.com>",
+ "OriginalDate": time.Now().Format("Mon Jan 2, 2006 at 3:04 PM"),
+ }
+
+ return ParseTemplateData(defaults)
+}
+
+func ParseTemplateData(defaults map[string]string) TemplateData {
+ originalDate, _ := time.Parse("Mon Jan 2, 2006 at 3:04 PM", defaults["OriginalDate"])
+ td := TemplateData{
+ To: parseAddressList(defaults["To"]),
+ Cc: parseAddressList(defaults["Cc"]),
+ Bcc: parseAddressList(defaults["Bcc"]),
+ From: parseAddressList(defaults["From"]),
+ Date: time.Now(),
+ Subject: defaults["Subject"],
+ OriginalText: defaults["Original"],
+ OriginalFrom: parseAddressList(defaults["OriginalFrom"]),
+ OriginalDate: originalDate,
+ }
+ return td
+}
+
+func parseAddressList(list string) []*mail.Address {
+ addrs, err := mail.ParseAddressList(list)
+ if err != nil {
+ return nil
+ }
+
+ return addrs
+}
+
+func wrapLine(text string, lineWidth int) string {
+ words := strings.Fields(text)
+ if len(words) == 0 {
+ return text
+ }
+ wrapped := words[0]
+ spaceLeft := lineWidth - len(wrapped)
+ for _, word := range words[1:] {
+ if len(word)+1 > spaceLeft {
+ wrapped += "\n" + word
+ spaceLeft = lineWidth - len(word)
+ } else {
+ wrapped += " " + word
+ spaceLeft -= 1 + len(word)
+ }
+ }
+
+ return wrapped
+}
+
+func wrapText(text string, lineWidth int) string {
+ text = strings.ReplaceAll(text, "\r\n", "\n")
+ lines := strings.Split(text, "\n")
+ var wrapped string
+
+ for _, line := range lines {
+ wrapped += wrapLine(line, lineWidth) + "\n"
+ }
+ return wrapped
+}
+
+// Wraping lines at 70 so that with the "> " of the quote it is under 72
+func quote(text string) string {
+ text = strings.ReplaceAll(text, "\r\n", "\n")
+
+ quoted := "> " + wrapText(text, 70)
+ quoted = strings.ReplaceAll(quoted, "\n", "\n> ")
+ return quoted
+}
+
+var templateFuncs = template.FuncMap{
+ "quote": quote,
+ "wrapText": wrapText,
+ "dateFormat": time.Time.Format,
+}
+
+func findTemplate(templateName string, templateDirs []string) (string, error) {
+ for _, dir := range templateDirs {
+ templateFile, err := homedir.Expand(path.Join(dir, templateName))
+ if err != nil {
+ return "", err
+ }
+
+ if _, err := os.Stat(templateFile); os.IsNotExist(err) {
+ continue
+ }
+ return templateFile, nil
+ }
+
+ return "", errors.New("Can't find template - " + templateName)
+}
+
+func ParseTemplateFromFile(templateName string, templateDirs []string, data interface{}) ([]byte, error) {
+ templateFile, err := findTemplate(templateName, templateDirs)
+ if err != nil {
+ return nil, err
+ }
+ emailTemplate, err :=
+ template.New(templateName).Funcs(templateFuncs).ParseFiles(templateFile)
+ if err != nil {
+ return nil, err
+ }
+
+ var outString bytes.Buffer
+ if err := emailTemplate.Execute(&outString, data); err != nil {
+ return nil, err
+ }
+ return outString.Bytes(), nil
+}
+
+func ParseTemplate(templateText string, data interface{}) ([]byte, error) {
+ emailTemplate, err :=
+ template.New("email_template").Funcs(templateFuncs).Parse(templateText)
+ if err != nil {
+ return nil, err
+ }
+
+ var outString bytes.Buffer
+ if err := emailTemplate.Execute(&outString, data); err != nil {
+ return nil, err
+ }
+ return outString.Bytes(), nil
+}