diff options
-rw-r--r-- | commands/commands_test.go | 2 | ||||
-rw-r--r-- | config/aerc.conf | 2 | ||||
-rw-r--r-- | config/templates.go | 2 | ||||
-rw-r--r-- | config/ui.go | 3 | ||||
-rw-r--r-- | doc/aerc-config.5.scd | 2 | ||||
-rw-r--r-- | doc/aerc-templates.7.scd | 17 | ||||
-rw-r--r-- | lib/state/templates.go | 34 | ||||
-rw-r--r-- | models/templates.go | 2 | ||||
-rw-r--r-- | widgets/msglist.go | 17 |
9 files changed, 67 insertions, 14 deletions
diff --git a/commands/commands_test.go b/commands/commands_test.go index 7c3ec84f..c01019d0 100644 --- a/commands/commands_test.go +++ b/commands/commands_test.go @@ -75,6 +75,8 @@ func (d *dummyData) Date() time.Time { return time.Now func (d *dummyData) DateAutoFormat(time.Time) string { return "" } func (d *dummyData) Header(string) string { return "" } func (d *dummyData) ThreadPrefix() string { return "└─>" } +func (d *dummyData) ThreadCount() int { return 0 } +func (d *dummyData) ThreadFolded() bool { return false } func (d *dummyData) Subject() string { return "Re: [PATCH] hey" } func (d *dummyData) SubjectBase() string { return "[PATCH] hey" } func (d *dummyData) Number() int { return 0 } diff --git a/config/aerc.conf b/config/aerc.conf index c6cd29d5..d6ffa389 100644 --- a/config/aerc.conf +++ b/config/aerc.conf @@ -73,7 +73,7 @@ #column-date={{.DateAutoFormat .Date.Local}} #column-name={{index (.From | names) 0}} #column-flags={{.Flags | join ""}} -#column-subject={{.ThreadPrefix}}{{.Subject}} +#column-subject={{.ThreadPrefix}}{{if .ThreadFolded}}{{printf "{%d}" .ThreadCount}}{{end}}{{.Subject}} # # String separator inserted between columns. When the column width specifier is diff --git a/config/templates.go b/config/templates.go index 97ba89b8..ef304ae2 100644 --- a/config/templates.go +++ b/config/templates.go @@ -76,6 +76,8 @@ func (d *dummyData) Date() time.Time { return time.Now() } func (d *dummyData) DateAutoFormat(time.Time) string { return "" } func (d *dummyData) Header(string) string { return "" } func (d *dummyData) ThreadPrefix() string { return "└─>" } +func (d *dummyData) ThreadCount() int { return 0 } +func (d *dummyData) ThreadFolded() bool { return false } func (d *dummyData) Subject() string { return "Re: [PATCH] hey" } func (d *dummyData) SubjectBase() string { return "[PATCH] hey" } func (d *dummyData) Number() int { return 0 } diff --git a/config/ui.go b/config/ui.go index dfd66224..ff6fbccf 100644 --- a/config/ui.go +++ b/config/ui.go @@ -303,7 +303,8 @@ func (*UIConfig) ParseIndexColumns(section *ini.Section, key *ini.Key) ([]*Colum _, _ = section.NewKey("column-flags", `{{.Flags | join ""}}`) } if !section.HasKey("column-subject") { - _, _ = section.NewKey("column-subject", `{{.ThreadPrefix}}{{.Subject}}`) + _, _ = section.NewKey("column-subject", + `{{.ThreadPrefix}}{{if .ThreadFolded}}{{printf "{%d}" .ThreadCount}}{{end}}{{.Subject}}`) } return ParseColumnDefs(key, section) } diff --git a/doc/aerc-config.5.scd b/doc/aerc-config.5.scd index 06f7c0b0..573ae557 100644 --- a/doc/aerc-config.5.scd +++ b/doc/aerc-config.5.scd @@ -116,7 +116,7 @@ These options are configured in the *[ui]* section of _aerc.conf_. column-date = {{.DateAutoFormat .Date.Local}} column-name = {{index (.From | names) 0}} column-flags = {{.Flags | join ""}} - column-subject = {{.Subject}} + column-subject = {{.ThreadPrefix}}{{if .ThreadFolded}}{{printf "{%d}" .ThreadCount}}{{end}}{{.Subject}} ``` See *aerc-templates*(7) for all available symbols and functions. diff --git a/doc/aerc-templates.7.scd b/doc/aerc-templates.7.scd index ce0b9a7c..19a7bd36 100644 --- a/doc/aerc-templates.7.scd +++ b/doc/aerc-templates.7.scd @@ -80,7 +80,7 @@ available always. is enabled). ``` - {{.ThreadPrefix}}{{.Subject}} + {{.ThreadPrefix}}{{if .ThreadFolded}}{{printf "{%d}" .ThreadCount}}{{end}}{{.Subject}} ``` The subject of the email stripped of any _Re:_ and _Fwd:_ prefixes. @@ -88,6 +88,21 @@ available always. ``` {{.SubjectBase}} ``` +*Threading* + When threading is enabled, these attributes are available in the message + list: + + _ThreadPrefix_ + If the message is part of a thread, this will contain arrows + that represent the message tree based on _In-Reply-To_ and + _References_ headers. + + _ThreadFolded_ + Will be _true_ if the message has thread children which are + hidden by *:fold*. + + _ThreadCount_ + The number of thread children. *Flags* List of message flags, not available when composing, replying nor diff --git a/lib/state/templates.go b/lib/state/templates.go index 36f7b725..7b877c76 100644 --- a/lib/state/templates.go +++ b/lib/state/templates.go @@ -16,7 +16,7 @@ type DataSetter interface { Data() models.TemplateData SetHeaders(*mail.Header, *models.OriginalMail) SetInfo(*models.MessageInfo, int, bool) - SetThreading(string, bool) + SetThreading(string, bool, int, bool) SetAccount(*config.AccountConfig) SetFolder(*models.Directory) SetRUE([]string, func(string) (int, int, int)) @@ -24,6 +24,13 @@ type DataSetter interface { SetPendingKeys([]config.KeyStroke) } +type ThreadInfo struct { + SameSubject bool + Prefix string + Count int + Folded bool +} + type templateData struct { // only available when composing/replying/forwarding headers *mail.Header @@ -35,8 +42,7 @@ type templateData struct { msgNum int // message list threading - threadSameSubject bool - threadPrefix string + threadInfo ThreadInfo // selected account account *config.AccountConfig @@ -72,9 +78,13 @@ func (d *templateData) SetInfo(info *models.MessageInfo, num int, marked bool, d.marked = marked } -func (d *templateData) SetThreading(prefix string, same bool) { - d.threadPrefix = prefix - d.threadSameSubject = same +func (d *templateData) SetThreading(prefix string, same bool, count int, + folded bool, +) { + d.threadInfo.Prefix = prefix + d.threadInfo.SameSubject = same + d.threadInfo.Count = count + d.threadInfo.Folded = folded } func (d *templateData) SetAccount(acct *config.AccountConfig) { @@ -260,7 +270,15 @@ func (d *templateData) Header(name string) string { } func (d *templateData) ThreadPrefix() string { - return d.threadPrefix + return d.threadInfo.Prefix +} + +func (d *templateData) ThreadCount() int { + return d.threadInfo.Count +} + +func (d *templateData) ThreadFolded() bool { + return d.threadInfo.Folded } func (d *templateData) Subject() string { @@ -271,7 +289,7 @@ func (d *templateData) Subject() string { case d.headers != nil: subject = d.Header("subject") } - if d.threadSameSubject { + if d.threadInfo.SameSubject { subject = "" } return subject diff --git a/models/templates.go b/models/templates.go index eb696ccc..686687cc 100644 --- a/models/templates.go +++ b/models/templates.go @@ -20,6 +20,8 @@ type TemplateData interface { DateAutoFormat(date time.Time) string Header(name string) string ThreadPrefix() string + ThreadCount() int + ThreadFolded() bool Subject() string SubjectBase() string Number() int diff --git a/widgets/msglist.go b/widgets/msglist.go index 548735d3..9ce60756 100644 --- a/widgets/msglist.go +++ b/widgets/msglist.go @@ -384,6 +384,17 @@ func (ml *MessageList) drawEmptyMessage(ctx *ui.Context) { uiConfig.GetStyle(config.STYLE_MSGLIST_DEFAULT), "%s", msg) } +func countThreads(thread *types.Thread) (ctr int) { + if thread == nil { + return + } + _ = thread.Walk(func(t *types.Thread, _ int, _ error) error { + ctr++ + return nil + }) + return +} + func threadPrefix(t *types.Thread, reverse bool, point bool) string { var arrow string if t.Parent != nil { @@ -457,7 +468,7 @@ func newThreadView(store *lib.MessageStore) *threadView { } func (t *threadView) Update(data state.DataSetter, uid uint32) { - prefix, same := "", false + prefix, same, count, folded := "", false, 0, false thread, err := t.store.Thread(uid) if thread != nil && err == nil { prefix = threadPrefix(thread, t.reverse, true) @@ -465,6 +476,8 @@ func (t *threadView) Update(data state.DataSetter, uid uint32) { same = subject == t.prevSubj && sameParent(thread, t.prev) && !isParent(thread) t.prev = thread t.prevSubj = subject + count = countThreads(thread) + folded = thread.FirstChild != nil && thread.FirstChild.Hidden } - data.SetThreading(prefix, same) + data.SetThreading(prefix, same, count, folded) } |