aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--worker/lib/sort.go210
1 files changed, 55 insertions, 155 deletions
diff --git a/worker/lib/sort.go b/worker/lib/sort.go
index 36c0924..ac8ed07 100644
--- a/worker/lib/sort.go
+++ b/worker/lib/sort.go
@@ -4,7 +4,6 @@ import (
"fmt"
"sort"
"strings"
- "time"
"git.sr.ht/~sircmpwn/aerc/models"
"git.sr.ht/~sircmpwn/aerc/worker/types"
@@ -15,51 +14,44 @@ func Sort(messageInfos []*models.MessageInfo,
// loop through in reverse to ensure we sort by non-primary fields first
for i := len(criteria) - 1; i >= 0; i-- {
criterion := criteria[i]
- var err error
switch criterion.Field {
case types.SortArrival:
- err = sortDate(messageInfos, criterion,
- func(msgInfo *models.MessageInfo) time.Time {
- return msgInfo.InternalDate
- })
+ sortSlice(criterion, messageInfos, func(i, j int) bool {
+ return messageInfos[i].InternalDate.Before(messageInfos[j].InternalDate)
+ })
case types.SortCc:
- err = sortAddresses(messageInfos, criterion,
+ sortAddresses(messageInfos, criterion,
func(msgInfo *models.MessageInfo) []*models.Address {
return msgInfo.Envelope.Cc
})
case types.SortDate:
- err = sortDate(messageInfos, criterion,
- func(msgInfo *models.MessageInfo) time.Time {
- return msgInfo.Envelope.Date
- })
+ sortSlice(criterion, messageInfos, func(i, j int) bool {
+ return messageInfos[i].Envelope.Date.Before(messageInfos[j].Envelope.Date)
+ })
case types.SortFrom:
- err = sortAddresses(messageInfos, criterion,
+ sortAddresses(messageInfos, criterion,
func(msgInfo *models.MessageInfo) []*models.Address {
return msgInfo.Envelope.From
})
case types.SortRead:
- err = sortFlags(messageInfos, criterion, models.SeenFlag)
+ sortFlags(messageInfos, criterion, models.SeenFlag)
case types.SortSize:
- err = sortInts(messageInfos, criterion,
- func(msgInfo *models.MessageInfo) uint32 {
- return msgInfo.Size
- })
+ sortSlice(criterion, messageInfos, func(i, j int) bool {
+ return messageInfos[i].Size < messageInfos[j].Size
+ })
case types.SortSubject:
- err = sortStrings(messageInfos, criterion,
+ sortStrings(messageInfos, criterion,
func(msgInfo *models.MessageInfo) string {
subject := strings.ToLower(msgInfo.Envelope.Subject)
subject = strings.TrimPrefix(subject, "re: ")
return strings.TrimPrefix(subject, "fwd: ")
})
case types.SortTo:
- err = sortAddresses(messageInfos, criterion,
+ sortAddresses(messageInfos, criterion,
func(msgInfo *models.MessageInfo) []*models.Address {
return msgInfo.Envelope.To
})
}
- if err != nil {
- return nil, err
- }
}
var uids []uint32
// copy in reverse as msgList displays backwards
@@ -69,40 +61,38 @@ func Sort(messageInfos []*models.MessageInfo,
return uids, nil
}
-func sortDate(messageInfos []*models.MessageInfo, criterion *types.SortCriterion,
- getValue func(*models.MessageInfo) time.Time) error {
- var slice []*dateStore
- for _, msgInfo := range messageInfos {
- slice = append(slice, &dateStore{
- Value: getValue(msgInfo),
- MsgInfo: msgInfo,
- })
- }
- sortSlice(criterion, dateSlice{slice})
- for i := 0; i < len(messageInfos); i++ {
- messageInfos[i] = slice[i].MsgInfo
- }
- return nil
-}
-
func sortAddresses(messageInfos []*models.MessageInfo, criterion *types.SortCriterion,
- getValue func(*models.MessageInfo) []*models.Address) error {
- var slice []*addressStore
- for _, msgInfo := range messageInfos {
- slice = append(slice, &addressStore{
- Value: getValue(msgInfo),
- MsgInfo: msgInfo,
- })
- }
- sortSlice(criterion, addressSlice{slice})
- for i := 0; i < len(messageInfos); i++ {
- messageInfos[i] = slice[i].MsgInfo
- }
- return nil
+ getValue func(*models.MessageInfo) []*models.Address) {
+ sortSlice(criterion, messageInfos, func(i, j int) bool {
+ addressI, addressJ := getValue(messageInfos[i]), getValue(messageInfos[j])
+ var firstI, firstJ *models.Address
+ if len(addressI) > 0 {
+ firstI = addressI[0]
+ }
+ if len(addressJ) > 0 {
+ firstJ = addressJ[0]
+ }
+ if firstI == nil && firstJ == nil {
+ return false
+ } else if firstI == nil && firstJ != nil {
+ return false
+ } else if firstI != nil && firstJ == nil {
+ return true
+ } else /* firstI != nil && firstJ != nil */ {
+ getName := func(addr *models.Address) string {
+ if addr.Name != "" {
+ return addr.Name
+ } else {
+ return fmt.Sprintf("%s@%s", addr.Mailbox, addr.Host)
+ }
+ }
+ return getName(firstI) < getName(firstJ)
+ }
+ })
}
func sortFlags(messageInfos []*models.MessageInfo, criterion *types.SortCriterion,
- testFlag models.Flag) error {
+ testFlag models.Flag) {
var slice []*boolStore
for _, msgInfo := range messageInfos {
flagPresent := false
@@ -116,31 +106,17 @@ func sortFlags(messageInfos []*models.MessageInfo, criterion *types.SortCriterio
MsgInfo: msgInfo,
})
}
- sortSlice(criterion, boolSlice{slice})
- for i := 0; i < len(messageInfos); i++ {
- messageInfos[i] = slice[i].MsgInfo
- }
- return nil
-}
-
-func sortInts(messageInfos []*models.MessageInfo, criterion *types.SortCriterion,
- getValue func(*models.MessageInfo) uint32) error {
- var slice []*intStore
- for _, msgInfo := range messageInfos {
- slice = append(slice, &intStore{
- Value: getValue(msgInfo),
- MsgInfo: msgInfo,
- })
- }
- sortSlice(criterion, intSlice{slice})
+ sortSlice(criterion, slice, func(i, j int) bool {
+ valI, valJ := slice[i].Value, slice[j].Value
+ return valI && !valJ
+ })
for i := 0; i < len(messageInfos); i++ {
messageInfos[i] = slice[i].MsgInfo
}
- return nil
}
func sortStrings(messageInfos []*models.MessageInfo, criterion *types.SortCriterion,
- getValue func(*models.MessageInfo) string) error {
+ getValue func(*models.MessageInfo) string) {
var slice []*lexiStore
for _, msgInfo := range messageInfos {
slice = append(slice, &lexiStore{
@@ -148,11 +124,12 @@ func sortStrings(messageInfos []*models.MessageInfo, criterion *types.SortCriter
MsgInfo: msgInfo,
})
}
- sortSlice(criterion, lexiSlice{slice})
+ sortSlice(criterion, slice, func(i, j int) bool {
+ return slice[i].Value < slice[j].Value
+ })
for i := 0; i < len(messageInfos); i++ {
messageInfos[i] = slice[i].MsgInfo
}
- return nil
}
type lexiStore struct {
@@ -160,94 +137,17 @@ type lexiStore struct {
MsgInfo *models.MessageInfo
}
-type lexiSlice struct{ Slice []*lexiStore }
-
-func (s lexiSlice) Len() int { return len(s.Slice) }
-func (s lexiSlice) Swap(i, j int) { s.Slice[i], s.Slice[j] = s.Slice[j], s.Slice[i] }
-func (s lexiSlice) Less(i, j int) bool {
- return s.Slice[i].Value < s.Slice[j].Value
-}
-
-type dateStore struct {
- Value time.Time
- MsgInfo *models.MessageInfo
-}
-
-type dateSlice struct{ Slice []*dateStore }
-
-func (s dateSlice) Len() int { return len(s.Slice) }
-func (s dateSlice) Swap(i, j int) { s.Slice[i], s.Slice[j] = s.Slice[j], s.Slice[i] }
-func (s dateSlice) Less(i, j int) bool {
- return s.Slice[i].Value.Before(s.Slice[j].Value)
-}
-
-type intStore struct {
- Value uint32
- MsgInfo *models.MessageInfo
-}
-
-type intSlice struct{ Slice []*intStore }
-
-func (s intSlice) Len() int { return len(s.Slice) }
-func (s intSlice) Swap(i, j int) { s.Slice[i], s.Slice[j] = s.Slice[j], s.Slice[i] }
-func (s intSlice) Less(i, j int) bool {
- return s.Slice[i].Value < s.Slice[j].Value
-}
-
-type addressStore struct {
- Value []*models.Address
- MsgInfo *models.MessageInfo
-}
-
-type addressSlice struct{ Slice []*addressStore }
-
-func (s addressSlice) Len() int { return len(s.Slice) }
-func (s addressSlice) Swap(i, j int) { s.Slice[i], s.Slice[j] = s.Slice[j], s.Slice[i] }
-func (s addressSlice) Less(i, j int) bool {
- addressI, addressJ := s.Slice[i].Value, s.Slice[j].Value
- var firstI, firstJ *models.Address
- if len(addressI) > 0 {
- firstI = addressI[0]
- }
- if len(addressJ) > 0 {
- firstJ = addressJ[0]
- }
- if firstI == nil && firstJ == nil {
- return false
- } else if firstI == nil && firstJ != nil {
- return false
- } else if firstI != nil && firstJ == nil {
- return true
- } else /* firstI != nil && firstJ != nil */ {
- getName := func(addr *models.Address) string {
- if addr.Name != "" {
- return addr.Name
- } else {
- return fmt.Sprintf("%s@%s", addr.Mailbox, addr.Host)
- }
- }
- return getName(firstI) < getName(firstJ)
- }
-}
-
type boolStore struct {
Value bool
MsgInfo *models.MessageInfo
}
-type boolSlice struct{ Slice []*boolStore }
-
-func (s boolSlice) Len() int { return len(s.Slice) }
-func (s boolSlice) Swap(i, j int) { s.Slice[i], s.Slice[j] = s.Slice[j], s.Slice[i] }
-func (s boolSlice) Less(i, j int) bool {
- valI, valJ := s.Slice[i].Value, s.Slice[j].Value
- return valI && !valJ
-}
-
-func sortSlice(criterion *types.SortCriterion, interfce sort.Interface) {
+func sortSlice(criterion *types.SortCriterion, slice interface{}, less func(i, j int) bool) {
if criterion.Reverse {
- sort.Stable(sort.Reverse(interfce))
+ sort.SliceStable(slice, func(i, j int) bool {
+ return less(j, i)
+ })
} else {
- sort.Stable(interfce)
+ sort.SliceStable(slice, less)
}
}