aboutsummaryrefslogtreecommitdiffstats
path: root/lib/templates
diff options
context:
space:
mode:
Diffstat (limited to 'lib/templates')
-rw-r--r--lib/templates/data.go406
-rw-r--r--lib/templates/functions.go13
-rw-r--r--lib/templates/template.go19
3 files changed, 18 insertions, 420 deletions
diff --git a/lib/templates/data.go b/lib/templates/data.go
deleted file mode 100644
index e34dc2f3..00000000
--- a/lib/templates/data.go
+++ /dev/null
@@ -1,406 +0,0 @@
-package templates
-
-import (
- "fmt"
- "strings"
- "time"
-
- "git.sr.ht/~rjarry/aerc/models"
- sortthread "github.com/emersion/go-imap-sortthread"
- "github.com/emersion/go-message/mail"
-)
-
-type TemplateData struct {
- // only available when composing/replying/forwarding
- headers *mail.Header
- // only available when replying with a quote
- parent *models.OriginalMail
- // only available for the message list
- info *models.MessageInfo
- marked bool
- msgNum int
-
- // message list threading
- ThreadSameSubject bool
- ThreadPrefix string
-
- // account config
- myAddresses map[string]bool
- account string
- folder string // selected folder name
-
- // ui config
- timeFmt string
- thisDayTimeFmt string
- thisWeekTimeFmt string
- thisYearTimeFmt string
- iconAttachment string
-}
-
-func NewTemplateData(
- from *mail.Address,
- aliases []*mail.Address,
- account string,
- folder string,
- timeFmt string,
- thisDayTimeFmt string,
- thisWeekTimeFmt string,
- thisYearTimeFmt string,
- iconAttachment string,
-) *TemplateData {
- myAddresses := map[string]bool{from.Address: true}
- for _, addr := range aliases {
- myAddresses[addr.Address] = true
- }
- return &TemplateData{
- myAddresses: myAddresses,
- account: account,
- folder: folder,
- timeFmt: timeFmt,
- thisDayTimeFmt: thisDayTimeFmt,
- thisWeekTimeFmt: thisWeekTimeFmt,
- thisYearTimeFmt: thisYearTimeFmt,
- iconAttachment: iconAttachment,
- }
-}
-
-// only used for compose/reply/forward
-func (d *TemplateData) SetHeaders(h *mail.Header, o *models.OriginalMail) {
- d.headers = h
- d.parent = o
-}
-
-// only used for message list templates
-func (d *TemplateData) SetInfo(info *models.MessageInfo, num int, marked bool) {
- d.info = info
- d.msgNum = num
- d.marked = marked
-}
-
-func (d *TemplateData) Account() string {
- return d.account
-}
-
-func (d *TemplateData) Folder() string {
- return d.folder
-}
-
-func (d *TemplateData) To() []*mail.Address {
- var to []*mail.Address
- switch {
- case d.info != nil && d.info.Envelope != nil:
- to = d.info.Envelope.To
- case d.headers != nil:
- to, _ = d.headers.AddressList("to")
- }
- return to
-}
-
-func (d *TemplateData) Cc() []*mail.Address {
- var cc []*mail.Address
- switch {
- case d.info != nil && d.info.Envelope != nil:
- cc = d.info.Envelope.Cc
- case d.headers != nil:
- cc, _ = d.headers.AddressList("cc")
- }
- return cc
-}
-
-func (d *TemplateData) Bcc() []*mail.Address {
- var bcc []*mail.Address
- switch {
- case d.info != nil && d.info.Envelope != nil:
- bcc = d.info.Envelope.Bcc
- case d.headers != nil:
- bcc, _ = d.headers.AddressList("bcc")
- }
- return bcc
-}
-
-func (d *TemplateData) From() []*mail.Address {
- var from []*mail.Address
- switch {
- case d.info != nil && d.info.Envelope != nil:
- from = d.info.Envelope.From
- case d.headers != nil:
- from, _ = d.headers.AddressList("from")
- }
- return from
-}
-
-func (d *TemplateData) Peer() []*mail.Address {
- var from, to []*mail.Address
- switch {
- case d.info != nil && d.info.Envelope != nil:
- from = d.info.Envelope.From
- to = d.info.Envelope.To
- case d.headers != nil:
- from, _ = d.headers.AddressList("from")
- to, _ = d.headers.AddressList("to")
- }
- for _, addr := range from {
- if d.myAddresses[addr.Address] {
- return to
- }
- }
- return from
-}
-
-func (d *TemplateData) ReplyTo() []*mail.Address {
- var replyTo []*mail.Address
- switch {
- case d.info != nil && d.info.Envelope != nil:
- replyTo = d.info.Envelope.ReplyTo
- case d.headers != nil:
- replyTo, _ = d.headers.AddressList("reply-to")
- }
- return replyTo
-}
-
-func (d *TemplateData) Date() time.Time {
- var date time.Time
- switch {
- case d.info != nil && d.info.Envelope != nil:
- date = d.info.Envelope.Date
- case d.info != nil:
- date = d.info.InternalDate
- default:
- date = time.Now()
- }
- return date
-}
-
-func (d *TemplateData) DateAutoFormat(date time.Time) string {
- if date.IsZero() {
- return ""
- }
- year := date.Year()
- day := date.YearDay()
- now := time.Now()
- thisYear := now.Year()
- thisDay := now.YearDay()
- fmt := d.timeFmt
- if year == thisYear {
- switch {
- case day == thisDay && d.thisDayTimeFmt != "":
- fmt = d.thisDayTimeFmt
- case day > thisDay-7 && d.thisWeekTimeFmt != "":
- fmt = d.thisWeekTimeFmt
- case d.thisYearTimeFmt != "":
- fmt = d.thisYearTimeFmt
- }
- }
- return date.Format(fmt)
-}
-
-func (d *TemplateData) Header(name string) string {
- var h *mail.Header
- switch {
- case d.headers != nil:
- h = d.headers
- case d.info != nil && d.info.RFC822Headers != nil:
- h = d.info.RFC822Headers
- default:
- return ""
- }
- text, err := h.Text(name)
- if err != nil {
- text = h.Get(name)
- }
- return text
-}
-
-func (d *TemplateData) Subject() string {
- var subject string
- switch {
- case d.info != nil && d.info.Envelope != nil:
- subject = d.info.Envelope.Subject
- case d.headers != nil:
- subject = d.Header("subject")
- }
- if d.ThreadSameSubject {
- subject = ""
- }
- return d.ThreadPrefix + subject
-}
-
-func (d *TemplateData) SubjectBase() string {
- base, _ := sortthread.GetBaseSubject(d.Subject())
- return base
-}
-
-func (d *TemplateData) Number() string {
- return fmt.Sprintf("%d", d.msgNum)
-}
-
-func (d *TemplateData) Labels() []string {
- if d.info == nil {
- return nil
- }
- return d.info.Labels
-}
-
-func (d *TemplateData) Flags() []string {
- var flags []string
- if d.info == nil {
- return flags
- }
-
- switch {
- case d.info.Flags.Has(models.SeenFlag | models.AnsweredFlag):
- flags = append(flags, "r") // message has been replied to
- case d.info.Flags.Has(models.SeenFlag):
- break
- case d.info.Flags.Has(models.RecentFlag):
- flags = append(flags, "N") // message is new
- default:
- flags = append(flags, "O") // message is old
- }
- if d.info.Flags.Has(models.DeletedFlag) {
- flags = append(flags, "D")
- }
- if d.info.BodyStructure != nil {
- for _, bS := range d.info.BodyStructure.Parts {
- if strings.ToLower(bS.Disposition) == "attachment" {
- flags = append(flags, d.iconAttachment)
- break
- }
- }
- }
- if d.info.Flags.Has(models.FlaggedFlag) {
- flags = append(flags, "!")
- }
- if d.marked {
- flags = append(flags, "*")
- }
- return flags
-}
-
-func (d *TemplateData) MessageId() string {
- if d.info == nil || d.info.Envelope == nil {
- return ""
- }
- return d.info.Envelope.MessageId
-}
-
-func (d *TemplateData) Size() uint32 {
- if d.info == nil || d.info.Envelope == nil {
- return 0
- }
- return d.info.Size
-}
-
-func (d *TemplateData) OriginalText() string {
- if d.parent == nil {
- return ""
- }
- return d.parent.Text
-}
-
-func (d *TemplateData) OriginalDate() time.Time {
- if d.parent == nil {
- return time.Time{}
- }
- return d.parent.Date
-}
-
-func (d *TemplateData) OriginalFrom() []*mail.Address {
- if d.parent == nil || d.parent.RFC822Headers == nil {
- return nil
- }
- from, _ := d.parent.RFC822Headers.AddressList("from")
- return from
-}
-
-func (d *TemplateData) OriginalMIMEType() string {
- if d.parent == nil {
- return ""
- }
- return d.parent.MIMEType
-}
-
-func (d *TemplateData) OriginalHeader(name string) string {
- if d.parent == nil || d.parent.RFC822Headers == nil {
- return ""
- }
- text, err := d.parent.RFC822Headers.Text(name)
- if err != nil {
- text = d.parent.RFC822Headers.Get(name)
- }
- return text
-}
-
-// DummyData provides dummy data to test template validity
-func DummyData() *TemplateData {
- from := &mail.Address{
- Name: "John Doe",
- Address: "john@example.com",
- }
- to := &mail.Address{
- Name: "Alice Doe",
- Address: "alice@example.com",
- }
- h := &mail.Header{}
- h.SetAddressList("from", []*mail.Address{from})
- h.SetAddressList("to", []*mail.Address{to})
-
- oh := &mail.Header{}
- oh.SetAddressList("from", []*mail.Address{to})
- oh.SetAddressList("to", []*mail.Address{from})
-
- original := models.OriginalMail{
- Date: time.Now(),
- From: from.String(),
- Text: "This is only a test text",
- MIMEType: "text/plain",
- RFC822Headers: oh,
- }
- data := NewTemplateData(
- to,
- nil,
- "account",
- "folder",
- "2006 Jan 02, 15:04 GMT-0700",
- "15:04",
- "Monday 15:04",
- "Jan 02",
- "a",
- )
- data.SetHeaders(h, &original)
-
- info := &models.MessageInfo{
- BodyStructure: &models.BodyStructure{
- MIMEType: "text",
- MIMESubType: "plain",
- Params: make(map[string]string),
- Description: "",
- Encoding: "",
- Parts: []*models.BodyStructure{},
- Disposition: "",
- DispositionParams: make(map[string]string),
- },
- Envelope: &models.Envelope{
- Date: time.Date(1981, 6, 23, 16, 52, 0, 0, time.UTC),
- Subject: "[PATCH aerc 2/3] foo: baz bar buz",
- From: []*mail.Address{from},
- ReplyTo: []*mail.Address{},
- To: []*mail.Address{to},
- Cc: []*mail.Address{},
- Bcc: []*mail.Address{},
- MessageId: "",
- InReplyTo: "",
- },
- Flags: models.FlaggedFlag,
- Labels: []string{"inbox", "patch"},
- InternalDate: time.Now(),
- RFC822Headers: nil,
- Refs: []string{},
- Size: 65512,
- Uid: 12345,
- Error: nil,
- }
- data.SetInfo(info, 42, true)
-
- return data
-}
diff --git a/lib/templates/functions.go b/lib/templates/functions.go
index 630db264..37b014f5 100644
--- a/lib/templates/functions.go
+++ b/lib/templates/functions.go
@@ -161,9 +161,14 @@ func persons(addresses []*mail.Address) []string {
var units = []string{"K", "M", "G", "T"}
-func humanReadable(value uint32) string {
+func humanReadable(value int) string {
+ sign := ""
+ if value < 0 {
+ sign = "-"
+ value = -value
+ }
if value < 1000 {
- return fmt.Sprintf("%d", value)
+ return fmt.Sprintf("%s%d", sign, value)
}
val := float64(value)
unit := ""
@@ -172,9 +177,9 @@ func humanReadable(value uint32) string {
val /= 1000.0
}
if val < 100.0 {
- return fmt.Sprintf("%.1f%s", val, unit)
+ return fmt.Sprintf("%s%.1f%s", sign, val, unit)
}
- return fmt.Sprintf("%.0f%s", val, unit)
+ return fmt.Sprintf("%s%.0f%s", sign, val, unit)
}
func cwd() string {
diff --git a/lib/templates/template.go b/lib/templates/template.go
index 28785356..bf257669 100644
--- a/lib/templates/template.go
+++ b/lib/templates/template.go
@@ -8,6 +8,7 @@ import (
"path"
"text/template"
+ "git.sr.ht/~rjarry/aerc/models"
"github.com/mitchellh/go-homedir"
)
@@ -28,19 +29,21 @@ func findTemplate(templateName string, templateDirs []string) (string, error) {
"Can't find template %q in any of %v ", templateName, templateDirs)
}
-func ParseTemplateFromFile(templateName string, templateDirs []string, data interface{}) (io.Reader, error) {
- templateFile, err := findTemplate(templateName, templateDirs)
+func ParseTemplateFromFile(
+ name string, dirs []string, data models.TemplateData,
+) (io.Reader, error) {
+ templateFile, err := findTemplate(name, dirs)
if err != nil {
return nil, err
}
- emailTemplate, err := template.New(templateName).
+ emailTemplate, err := template.New(name).
Funcs(templateFuncs).ParseFiles(templateFile)
if err != nil {
return nil, err
}
var body bytes.Buffer
- if err := emailTemplate.Execute(&body, data); err != nil {
+ if err := Render(emailTemplate, &body, data); err != nil {
return nil, err
}
return &body, nil
@@ -50,10 +53,6 @@ func ParseTemplate(name, content string) (*template.Template, error) {
return template.New(name).Funcs(templateFuncs).Parse(content)
}
-func CheckTemplate(templateName string, templateDirs []string) error {
- if templateName != "" {
- _, err := ParseTemplateFromFile(templateName, templateDirs, DummyData())
- return err
- }
- return nil
+func Render(t *template.Template, w io.Writer, data models.TemplateData) error {
+ return t.Execute(w, data)
}