From f3a61a341c81d70b51d91a71e1b0909acdcdb8f4 Mon Sep 17 00:00:00 2001 From: Jason Cox Date: Sat, 17 Feb 2024 12:34:23 -0500 Subject: commands: add :query to create named notmuch dirs The current :cf command can be used to create folders for arbitrary notmuch queries. These folders use the query as their namee. In some cases, though, it's useful to give a more human-readable name. Create a new :query command to allow doing so. The :query command accepts an optional -n flag to specify a name. The remaining arguments are interpreted verbatim as a notmuch query. If no name is specified, the query itself is used as the name. For example, to create a new folder with the full thread of the current message, named by its subject, run the following command: :query -n "{{.SubjectBase}}" thread:"{mid:{{.MessageId}}}" :query could have been implemented as an additional flag to :cf. Giving a name to the created folder would make the smantics of :cf strange, though. For example, to create a named query folder, one would use :cf -n . This syntax feels odd; the name of the folder seems like it ought to be the positional argument of the change folder command. Alternatively, the usage could be :cf -q , but this feels wrong as well: the query, which is provided as a positional parameter when no name is specified, becomes a flag parameter when a name is specified. What's more, both of these potential usages add a notmuch-specific flag to an otherwise general command. Creating a new command feels cleaner. Perhaps the current query functionality of the :cf command could eventually be deprecated to remove the duplicate functionality and keep :cf limited to changing to existing folders. Changelog-added: Create notmuch named queries with the `:query` command. Signed-off-by: Jason Cox Tested-by: Inwit Acked-by: Robin Jarry --- worker/notmuch/eventhandlers.go | 7 +++++ worker/notmuch/worker.go | 60 ++++++++++++++++++++++++++++++----------- worker/types/messages.go | 1 + 3 files changed, 52 insertions(+), 16 deletions(-) (limited to 'worker') diff --git a/worker/notmuch/eventhandlers.go b/worker/notmuch/eventhandlers.go index be01a71b..76517953 100644 --- a/worker/notmuch/eventhandlers.go +++ b/worker/notmuch/eventhandlers.go @@ -55,6 +55,13 @@ func (w *worker) updateDirCounts() error { }, nil) } + for name, query := range w.dynamicNameQueryMap { + w.w.PostMessage(&types.DirectoryInfo{ + Info: w.getDirectoryInfo(name, query), + Refetch: w.query == query, + }, nil) + } + return nil } diff --git a/worker/notmuch/worker.go b/worker/notmuch/worker.go index c5792709..aa2da391 100644 --- a/worker/notmuch/worker.go +++ b/worker/notmuch/worker.go @@ -27,6 +27,7 @@ import ( "git.sr.ht/~rjarry/aerc/worker/lib" notmuch "git.sr.ht/~rjarry/aerc/worker/notmuch/lib" "git.sr.ht/~rjarry/aerc/worker/types" + "github.com/emersion/go-maildir" ) func init() { @@ -42,6 +43,7 @@ type worker struct { currentQueryName string queryMapOrder []string nameQueryMap map[string]string + dynamicNameQueryMap map[string]string store *lib.MaildirStore maildirAccountPath string db *notmuch.DB @@ -70,6 +72,7 @@ func NewWorker(w *types.Worker) (types.Backend, error) { Sort: true, Thread: true, }, + dynamicNameQueryMap: make(map[string]string), }, nil } @@ -284,6 +287,17 @@ func (w *worker) handleListDirectories(msg *types.ListDirectories) error { }, }, nil) } + + for name := range w.dynamicNameQueryMap { + w.w.PostMessage(&types.Directory{ + Message: types.RespondTo(msg), + Dir: &models.Directory{ + Name: name, + Role: models.QueryRole, + }, + }, nil) + } + // Update dir counts when listing directories err := w.updateDirCounts() if err != nil { @@ -318,14 +332,15 @@ func (w *worker) handleOpenDirectory(msg *types.OpenDirectory) error { if msg.Context.Err() != nil { return context.Canceled } - w.w.Tracef("opening %s", msg.Directory) + w.w.Tracef("opening %s with query %s", msg.Directory, msg.Query) - var isDynamicFolder bool + var exists bool q := "" if w.store != nil { folders, _ := w.store.FolderMap() - dir, ok := folders[msg.Directory] - if ok { + var dir maildir.Dir + dir, exists = folders[msg.Directory] + if exists { folder := filepath.Join(w.maildirAccountPath, msg.Directory) q = fmt.Sprintf("folder:%s", strconv.Quote(folder)) if err := w.processNewMaildirFiles(string(dir)); err != nil { @@ -334,19 +349,26 @@ func (w *worker) handleOpenDirectory(msg *types.OpenDirectory) error { } } if q == "" { - var ok bool - q, ok = w.nameQueryMap[msg.Directory] - if !ok { + q, exists = w.nameQueryMap[msg.Directory] + if !exists { + q, exists = w.dynamicNameQueryMap[msg.Directory] + } + } + if !exists { + q = msg.Query + if q == "" { q = msg.Directory - isDynamicFolder = true - w.w.PostMessage(&types.Directory{ - Message: types.RespondTo(msg), - Dir: &models.Directory{ - Name: q, - Role: models.QueryRole, - }, - }, nil) } + w.dynamicNameQueryMap[msg.Directory] = q + w.w.PostMessage(&types.Directory{ + Message: types.RespondTo(msg), + Dir: &models.Directory{ + Name: msg.Directory, + Role: models.QueryRole, + }, + }, nil) + } else if msg.Query != "" && msg.Query != q { + return errors.New("cannot use existing folder name for new query") } w.query = q w.currentQueryName = msg.Directory @@ -355,7 +377,7 @@ func (w *worker) handleOpenDirectory(msg *types.OpenDirectory) error { Info: w.getDirectoryInfo(msg.Directory, w.query), Message: types.RespondTo(msg), }, nil) - if isDynamicFolder { + if !exists { w.w.PostMessage(&types.DirectoryInfo{ Info: w.getDirectoryInfo(msg.Directory, w.query), Message: types.RespondTo(msg), @@ -921,6 +943,12 @@ func (w *worker) handleRemoveDirectory(msg *types.RemoveDirectory) error { return errUnsupported } + if _, ok := w.dynamicNameQueryMap[msg.Directory]; ok { + delete(w.dynamicNameQueryMap, msg.Directory) + w.done(msg) + return nil + } + if w.store == nil { w.done(msg) return nil diff --git a/worker/types/messages.go b/worker/types/messages.go index 7ebb3aae..90d3d7bb 100644 --- a/worker/types/messages.go +++ b/worker/types/messages.go @@ -101,6 +101,7 @@ type OpenDirectory struct { Message Context context.Context Directory string + Query string } type FetchDirectoryContents struct { -- cgit