aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--commands/commands_test.go2
-rw-r--r--config/aerc.conf2
-rw-r--r--config/templates.go2
-rw-r--r--config/ui.go3
-rw-r--r--doc/aerc-config.5.scd2
-rw-r--r--doc/aerc-templates.7.scd17
-rw-r--r--lib/state/templates.go34
-rw-r--r--models/templates.go2
-rw-r--r--widgets/msglist.go17
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)
}