diff options
author | Tim Culverhouse <tim@timculverhouse.com> | 2023-02-03 13:23:08 -0600 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2023-02-12 00:39:21 +0100 |
commit | 2a0da301c51a8862c4e8a73b141adc0f416833a5 (patch) | |
tree | dabf9adbef3a4732daae91acb11be941ff3c47f9 | |
parent | 2df3a079a060bb56aaa4d94df066936cb7b73f9d (diff) | |
download | aerc-2a0da301c51a8862c4e8a73b141adc0f416833a5.tar.gz |
tabs: use template for compose tabs
Use a template for compose tabs.
Other available values:
Account string
Subject string
To []*mail.Address
From []*mail.Address
Cc []*mail.Address
Bcc []*mail.Address
OriginalFrom []*mail.Address
When you use To, From, CC, BCC, or OriginalFrom the title will only be
updated when an editing field has lost focus. This is so we don't end up
calling "PrepareHeader" on every keystroke, which will likely error out
anyways since it will be an invalid header.
Subject still updates every keystroke.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
-rw-r--r-- | commands/account/compose.go | 11 | ||||
-rw-r--r-- | commands/account/recover.go | 7 | ||||
-rw-r--r-- | commands/msg/forward.go | 11 | ||||
-rw-r--r-- | commands/msg/invite.go | 11 | ||||
-rw-r--r-- | commands/msg/recall.go | 11 | ||||
-rw-r--r-- | commands/msg/reply.go | 11 | ||||
-rw-r--r-- | commands/msg/unsubscribe.go | 11 | ||||
-rw-r--r-- | config/ui.go | 13 | ||||
-rw-r--r-- | doc/aerc-config.5.scd | 6 | ||||
-rw-r--r-- | widgets/aerc.go | 10 | ||||
-rw-r--r-- | widgets/compose.go | 54 |
11 files changed, 80 insertions, 76 deletions
diff --git a/commands/account/compose.go b/commands/account/compose.go index 5695bb7d..a8b16791 100644 --- a/commands/account/compose.go +++ b/commands/account/compose.go @@ -11,7 +11,6 @@ import ( "github.com/emersion/go-message/mail" "git.sr.ht/~rjarry/aerc/config" - "git.sr.ht/~rjarry/aerc/lib/ui" "git.sr.ht/~rjarry/aerc/log" "git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~sircmpwn/getopt" @@ -58,15 +57,7 @@ func (Compose) Execute(aerc *widgets.Aerc, args []string) error { if err != nil { return err } - tab := aerc.NewTab(composer, "New email") - composer.OnHeaderChange("Subject", func(subject string) { - if subject == "" { - tab.Name = "New email" - } else { - tab.Name = subject - } - ui.Invalidate() - }) + composer.Tab = aerc.NewTab(composer, "New email") go func() { defer log.PanicHandler() diff --git a/commands/account/recover.go b/commands/account/recover.go index cef0720f..cccadf8d 100644 --- a/commands/account/recover.go +++ b/commands/account/recover.go @@ -8,7 +8,6 @@ import ( "path/filepath" "git.sr.ht/~rjarry/aerc/commands" - "git.sr.ht/~rjarry/aerc/lib/ui" "git.sr.ht/~rjarry/aerc/log" "git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~sircmpwn/getopt" @@ -107,11 +106,7 @@ func (Recover) Execute(aerc *widgets.Aerc, args []string) error { return err } - tab := aerc.NewTab(composer, "Recovered") - composer.OnHeaderChange("Subject", func(subject string) { - tab.Name = subject - ui.Invalidate() - }) + composer.Tab = aerc.NewTab(composer, "Recovered") go func() { defer log.PanicHandler() diff --git a/commands/msg/forward.go b/commands/msg/forward.go index 90c32ec2..92575abd 100644 --- a/commands/msg/forward.go +++ b/commands/msg/forward.go @@ -15,7 +15,6 @@ import ( "git.sr.ht/~rjarry/aerc/config" "git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/lib/format" - "git.sr.ht/~rjarry/aerc/lib/ui" "git.sr.ht/~rjarry/aerc/log" "git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/widgets" @@ -107,20 +106,12 @@ func (forward) Execute(aerc *widgets.Aerc, args []string) error { return nil, err } - tab := aerc.NewTab(composer, subject) + composer.Tab = aerc.NewTab(composer, subject) if !h.Has("to") { composer.FocusEditor("to") } else { composer.FocusTerminal() } - composer.OnHeaderChange("Subject", func(subject string) { - if subject == "" { - tab.Name = "New email" - } else { - tab.Name = subject - } - ui.Invalidate() - }) return composer, nil } diff --git a/commands/msg/invite.go b/commands/msg/invite.go index 1528abea..774c4a69 100644 --- a/commands/msg/invite.go +++ b/commands/msg/invite.go @@ -9,7 +9,6 @@ import ( "git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/lib/calendar" "git.sr.ht/~rjarry/aerc/lib/format" - "git.sr.ht/~rjarry/aerc/lib/ui" "git.sr.ht/~rjarry/aerc/log" "git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/widgets" @@ -152,15 +151,7 @@ func (invite) Execute(aerc *widgets.Aerc, args []string) error { } composer.FocusTerminal() - tab := aerc.NewTab(composer, subject) - composer.OnHeaderChange("Subject", func(subject string) { - if subject == "" { - tab.Name = "New email" - } else { - tab.Name = subject - } - ui.Invalidate() - }) + composer.Tab = aerc.NewTab(composer, subject) composer.OnClose(func(c *widgets.Composer) { if c.Sent() { diff --git a/commands/msg/recall.go b/commands/msg/recall.go index 2ef468e0..4eda8339 100644 --- a/commands/msg/recall.go +++ b/commands/msg/recall.go @@ -13,7 +13,6 @@ import ( "github.com/pkg/errors" "git.sr.ht/~rjarry/aerc/lib" - "git.sr.ht/~rjarry/aerc/lib/ui" "git.sr.ht/~rjarry/aerc/log" "git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/widgets" @@ -87,15 +86,7 @@ func (Recall) Execute(aerc *widgets.Aerc, args []string) error { if subject == "" { subject = "Recalled email" } - tab := aerc.NewTab(composer, subject) - composer.OnHeaderChange("Subject", func(subject string) { - if subject == "" { - tab.Name = "New email" - } else { - tab.Name = subject - } - ui.Invalidate() - }) + composer.Tab = aerc.NewTab(composer, subject) composer.OnClose(func(composer *widgets.Composer) { worker := composer.Worker() uids := []uint32{msgInfo.Uid} diff --git a/commands/msg/reply.go b/commands/msg/reply.go index f8cde644..8a244fed 100644 --- a/commands/msg/reply.go +++ b/commands/msg/reply.go @@ -16,7 +16,6 @@ import ( "git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/lib/crypto" "git.sr.ht/~rjarry/aerc/lib/format" - "git.sr.ht/~rjarry/aerc/lib/ui" "git.sr.ht/~rjarry/aerc/log" "git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/widgets" @@ -190,15 +189,7 @@ func (reply) Execute(aerc *widgets.Aerc, args []string) error { composer.FocusTerminal() } - tab := aerc.NewTab(composer, subject) - composer.OnHeaderChange("Subject", func(subject string) { - if subject == "" { - tab.Name = "New email" - } else { - tab.Name = subject - } - ui.Invalidate() - }) + composer.Tab = aerc.NewTab(composer, subject) composer.OnClose(func(c *widgets.Composer) { switch { diff --git a/commands/msg/unsubscribe.go b/commands/msg/unsubscribe.go index 37ed707f..46ff5d1f 100644 --- a/commands/msg/unsubscribe.go +++ b/commands/msg/unsubscribe.go @@ -9,7 +9,6 @@ import ( "time" "git.sr.ht/~rjarry/aerc/lib" - "git.sr.ht/~rjarry/aerc/lib/ui" "git.sr.ht/~rjarry/aerc/log" "git.sr.ht/~rjarry/aerc/widgets" "github.com/emersion/go-message/mail" @@ -160,15 +159,7 @@ func unsubscribeMailto(aerc *widgets.Aerc, u *url.URL) error { return err } composer.SetContents(strings.NewReader(u.Query().Get("body"))) - tab := aerc.NewTab(composer, "unsubscribe") - composer.OnHeaderChange("Subject", func(subject string) { - if subject == "" { - tab.Name = "unsubscribe" - } else { - tab.Name = subject - } - ui.Invalidate() - }) + composer.Tab = aerc.NewTab(composer, "unsubscribe") composer.FocusTerminal() return nil } diff --git a/config/ui.go b/config/ui.go index 6c880293..db596d97 100644 --- a/config/ui.go +++ b/config/ui.go @@ -73,7 +73,8 @@ type UIConfig struct { SortThreadSiblings bool `ini:"sort-thread-siblings"` // Tab Templates - TabTitleAccount *template.Template `ini:"-"` + TabTitleAccount *template.Template `ini:"-"` + TabTitleComposer *template.Template `ini:"-"` // private contextualUis []*UiConfigContext @@ -106,6 +107,7 @@ func defaultUiConfig() *UIConfig { flags, _ := templates.ParseTemplate("column-flags", `{{.Flags | join ""}}`) subject, _ := templates.ParseTemplate("column-subject", "{{.Subject}}") tabTitleAccount, _ := templates.ParseTemplate("tab-title-account", "{{.Account}}") + tabTitleComposer, _ := templates.ParseTemplate("tab-title-composer", "{{.Subject}}") return &UIConfig{ IndexFormat: "", // deprecated IndexColumns: []*ColumnDef{ @@ -148,6 +150,7 @@ func defaultUiConfig() *UIConfig { ClientThreadsDelay: 50 * time.Millisecond, NewMessageBell: true, TabTitleAccount: tabTitleAccount, + TabTitleComposer: tabTitleComposer, FuzzyComplete: false, Spinner: "[..] , [..] , [..] , [..] , [..], [..] , [..] , [..] ", SpinnerDelimiter: ",", @@ -362,6 +365,14 @@ index-format will be removed in aerc 0.17. } config.TabTitleAccount = tmpl } + if key, err := section.GetKey("tab-title-composer"); err == nil { + val := key.Value() + tmpl, err := templates.ParseTemplate("tab-title-composer", val) + if err != nil { + return err + } + config.TabTitleComposer = tmpl + } return nil } diff --git a/doc/aerc-config.5.scd b/doc/aerc-config.5.scd index 4939cf3d..3669d26e 100644 --- a/doc/aerc-config.5.scd +++ b/doc/aerc-config.5.scd @@ -172,6 +172,12 @@ These options are configured in the *[ui]* section of _aerc.conf_. Default: _{{.Account}}_ +*tab-title-composer* = _<go_template>_ + The template to use for composer tab titles. See *aerc-templates*(7) for + available field names. + + Default: _{{.Subject}}_ + *pinned-tab-marker* = _"<string>"_ Marker to show before a pinned tab's name. diff --git a/widgets/aerc.go b/widgets/aerc.go index e8d65539..8eec8823 100644 --- a/widgets/aerc.go +++ b/widgets/aerc.go @@ -748,15 +748,7 @@ func (aerc *Aerc) Mailto(addr *url.URL) error { if to == nil { composer.FocusEditor("to") } - tab := aerc.NewTab(composer, title) - composer.OnHeaderChange("Subject", func(subject string) { - if subject == "" { - tab.Name = "New email" - } else { - tab.Name = subject - } - ui.Invalidate() - }) + composer.Tab = aerc.NewTab(composer, title) for _, file := range attachments { composer.AddAttachment(file) diff --git a/widgets/compose.go b/widgets/compose.go index 5795ccba..94fd79d5 100644 --- a/widgets/compose.go +++ b/widgets/compose.go @@ -63,6 +63,7 @@ type Composer struct { width int textParts []*lib.Part + Tab *ui.Tab } func NewComposer( @@ -235,6 +236,15 @@ func (c *Composer) buildComposeHeader(aerc *Aerc, cmpl *completer.Completer) { default: c.focusable = append(c.focusable, e) } + e.OnChange(func() { + c.setTitle() + ui.Invalidate() + }) + e.OnFocusLost(func() { + c.PrepareHeader() //nolint:errcheck // tab title only, fine if it's not valid yet + c.setTitle() + ui.Invalidate() + }) } } @@ -606,6 +616,7 @@ func (c *Composer) OnClose(fn func(composer *Composer)) { } func (c *Composer) Draw(ctx *ui.Context) { + c.setTitle() c.width = ctx.Width() c.grid.Draw(ctx) } @@ -1517,3 +1528,46 @@ func (c *Composer) checkEncryptionKeys(_ string) bool { } return true } + +// setTitle executes the title template and sets the tab title +func (c *Composer) setTitle() { + if c.Tab == nil { + return + } + data := struct { + Account string + Subject string + To []*mail.Address + From []*mail.Address + Cc []*mail.Address + Bcc []*mail.Address + OriginalFrom []*mail.Address + }{} + data.Account = c.acct.Name() + // Get subject direct from the textinput + subject, ok := c.editors["subject"] + if ok { + data.Subject = subject.input.String() + } + if data.Subject == "" { + data.Subject = "New Email" + } + // Get address fields from header, which gets updated on focus lost of + // any headerEditor field + data.From, _ = c.header.AddressList("from") + data.To, _ = c.header.AddressList("to") + data.Cc, _ = c.header.AddressList("cc") + data.Bcc, _ = c.header.AddressList("bcc") + + if c.parent != nil && c.parent.RFC822Headers != nil { + data.OriginalFrom, _ = c.parent.RFC822Headers.AddressList("from") + } + + buf := bytes.NewBuffer(nil) + err := c.acct.UiConfig().TabTitleComposer.Execute(buf, data) + if err != nil { + c.acct.PushError(err) + return + } + c.Tab.SetTitle(buf.String()) +} |