notmuch: allow sort by file order

When using the notmuch backend, it often makes more sense to sort
folders (actual virtual folders, or queries) by the order specified in
the query-map file, rather than alphabetically. This patch introduces a
configuration option (disabled by default) that allows this.

Additionally, due to the notmuch backend previously using maps (which
are order-undefined) to store the list of queries, default query
selection on aerc startup fluctuated. This patch fixes that by using
slices to store query order.
This commit is contained in:
Kalyan Sriram 2021-11-13 08:10:09 +00:00 committed by Robin Jarry
parent 88d28908d2
commit 402612fd97
4 changed files with 43 additions and 24 deletions

View file

@ -10,6 +10,7 @@ import (
"path" "path"
"regexp" "regexp"
"sort" "sort"
"strconv"
"strings" "strings"
"time" "time"
"unicode" "unicode"
@ -90,6 +91,7 @@ type AccountConfig struct {
OutgoingCredCmd string OutgoingCredCmd string
SignatureFile string SignatureFile string
SignatureCmd string SignatureCmd string
EnableFoldersSort bool `ini:"enable-folders-sort"`
FoldersSort []string `ini:"folders-sort" delim:","` FoldersSort []string `ini:"folders-sort" delim:","`
} }
@ -186,6 +188,7 @@ func loadAccountConfig(path string) ([]AccountConfig, error) {
Postpone: "Drafts", Postpone: "Drafts",
Name: _sec, Name: _sec,
Params: make(map[string]string), Params: make(map[string]string),
EnableFoldersSort: true,
} }
if err = sec.MapTo(&account); err != nil { if err = sec.MapTo(&account); err != nil {
return nil, err return nil, err
@ -213,6 +216,8 @@ func loadAccountConfig(path string) ([]AccountConfig, error) {
account.CopyTo = val account.CopyTo = val
} else if key == "archive" { } else if key == "archive" {
account.Archive = val account.Archive = val
} else if key == "enable-folders-sort" {
account.EnableFoldersSort, _ = strconv.ParseBool(val)
} else if key != "name" { } else if key != "name" {
account.Params[key] = val account.Params[key] = val
} }

View file

@ -427,6 +427,12 @@ Note that many of these configuration options are written for you, such as
Default: no folders Default: no folders
*enable-folders-sort*
If true, folders are sorted, first by specified folders (see *folders-sort*),
then alphabetically.
Default: true
*folders-sort* *folders-sort*
Specifies a comma separated list of folders to be shown at the top of the Specifies a comma separated list of folders to be shown at the top of the
list in the provided order. Remaining folders will be sorted alphabetically. list in the provided order. Remaining folders will be sorted alphabetically.

View file

@ -105,7 +105,9 @@ func (dirlist *DirectoryList) Select(name string) {
if !hasSelected && dirlist.selected != "" { if !hasSelected && dirlist.selected != "" {
dirlist.dirs = append(dirlist.dirs, dirlist.selected) dirlist.dirs = append(dirlist.dirs, dirlist.selected)
} }
if dirlist.acctConf.EnableFoldersSort {
sort.Strings(dirlist.dirs) sort.Strings(dirlist.dirs)
}
dirlist.sortDirsByFoldersSortConfig() dirlist.sortDirsByFoldersSortConfig()
} }
dirlist.Invalidate() dirlist.Invalidate()
@ -376,6 +378,10 @@ func folderMatches(folder string, pattern string) bool {
// AccountConfig.FoldersSort option. Folders not included in the option // AccountConfig.FoldersSort option. Folders not included in the option
// will be appended at the end in alphabetical order // will be appended at the end in alphabetical order
func (dirlist *DirectoryList) sortDirsByFoldersSortConfig() { func (dirlist *DirectoryList) sortDirsByFoldersSortConfig() {
if !dirlist.acctConf.EnableFoldersSort {
return
}
sort.Slice(dirlist.dirs, func(i, j int) bool { sort.Slice(dirlist.dirs, func(i, j int) bool {
foldersSort := dirlist.acctConf.FoldersSort foldersSort := dirlist.acctConf.FoldersSort
iInFoldersSort := findString(foldersSort, dirlist.dirs[i]) iInFoldersSort := findString(foldersSort, dirlist.dirs[i])

View file

@ -35,6 +35,7 @@ type worker struct {
query string query string
currentQueryName string currentQueryName string
uidStore *uidstore.Store uidStore *uidstore.Store
queryMapOrder []string
nameQueryMap map[string]string nameQueryMap map[string]string
db *notmuch.DB db *notmuch.DB
setupErr error setupErr error
@ -185,7 +186,7 @@ func (w *worker) handleConnect(msg *types.Connect) error {
} }
func (w *worker) handleListDirectories(msg *types.ListDirectories) error { func (w *worker) handleListDirectories(msg *types.ListDirectories) error {
for name := range w.nameQueryMap { for _, name := range w.queryMapOrder {
w.w.PostMessage(&types.Directory{ w.w.PostMessage(&types.Directory{
Message: types.RespondTo(msg), Message: types.RespondTo(msg),
Dir: &models.Directory{ Dir: &models.Directory{
@ -508,6 +509,7 @@ func (w *worker) loadQueryMap(acctConfig *config.AccountConfig) error {
return fmt.Errorf("%v: invalid line %q, want name=query", file, line) return fmt.Errorf("%v: invalid line %q, want name=query", file, line)
} }
w.nameQueryMap[split[0]] = split[1] w.nameQueryMap[split[0]] = split[1]
w.queryMapOrder = append(w.queryMapOrder, split[0])
} }
return nil return nil
} }