From a15e640eb79012fc241b491c411b11abe37d33b4 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Sat, 8 Mar 2025 11:36:40 +0200 Subject: [PATCH] mu4e: implement :hide-if-no-unread Make mu4e-maildir-shortcut and mu4e-bookmarks understand a property :hide-if-no-unread~, which hides the maildir/bookmark from the main-view if there are no unread messages which the corresponding query. --- NEWS.org | 4 +++ mu4e/mu4e-bookmarks.el | 4 +++ mu4e/mu4e-folders.el | 6 +++- mu4e/mu4e-helpers.el | 27 +++++++++++++++++ mu4e/mu4e-main.el | 14 +++++---- mu4e/mu4e-query-items.el | 20 +++++-------- mu4e/mu4e.texi | 63 ++++++++++++++++++++++++++++------------ 7 files changed, 100 insertions(+), 38 deletions(-) diff --git a/NEWS.org b/NEWS.org index c099a0b1..41ca105e 100644 --- a/NEWS.org +++ b/NEWS.org @@ -91,6 +91,10 @@ automatically translate; this depends on the ~pcre2el~ package which the user should install when using regular expression-addresses. + - ~mu4e-maildir-shortcuts~ and ~mu4e-bookmarks~ now understand a property + ~:hide-if-no-unread~, which hides the maildir/bookmark from the main-view if + there are no unread messages which the corresponding query. + * 1.12 (released on February 24, 2024) ** Some highlights diff --git a/mu4e/mu4e-bookmarks.el b/mu4e/mu4e-bookmarks.el index f118133f..37127e2f 100644 --- a/mu4e/mu4e-bookmarks.el +++ b/mu4e/mu4e-bookmarks.el @@ -65,6 +65,10 @@ item must be unique among `mu4e-bookmarks' and `mu4e-maildir-shortcuts'. - `:hide' - if t, the bookmark is hidden from the main-view and speedbar. +- `:hide-if-no-unread' - if t, the shortcut is hidden from + the main-view if it contains are no unread messages. + +You can also use: - `:hide-unread' - do not show the counts of unread/total number of matches for the query in the main-view. This can be useful if a bookmark uses a very slow query. diff --git a/mu4e/mu4e-folders.el b/mu4e/mu4e-folders.el index fad001e4..22d1ee28 100644 --- a/mu4e/mu4e-folders.el +++ b/mu4e/mu4e-folders.el @@ -105,9 +105,13 @@ Each of the list elements is a plist with at least: Optionally, you can add the following: `:name' - name of the maildir to be displayed in main-view. `:hide' - if t, the shortcut is hidden from the main-view. +`:hide-if-no-unread' - if it t, the shortcut is hidden from + the main-view if it contains no unread messages. + + You can also use: `:hide-unread' - do not show the counts of unread/total number of matches for the maildir in the main-view, and is implied -from `:hide'. + from `:hide'. For backward compatibility, an older form is recognized as well: diff --git a/mu4e/mu4e-helpers.el b/mu4e/mu4e-helpers.el index d756b81e..c5c7634f 100644 --- a/mu4e/mu4e-helpers.el +++ b/mu4e/mu4e-helpers.el @@ -593,6 +593,33 @@ This is mu4e's version of Emacs 29's `plistp'." (let ((len (proper-list-p object))) (and len (zerop (% len 2))))) +(defun mu4e-plist-do (func plist) + "Apply FUNC to each element in PLIST. +FUNC receives to arguments: the key and its value." + (when plist + (funcall func (car plist) (cadr plist)) + (mu4e-plist-do func (cddr plist)))) + +(defun mu4e-plist-remove (plist prop) + "Remove PROP from PLIST. +Returns the updated PLIST." + ;; inspired by org-plist-delete + (let (p) + (while plist + (if (not (eq prop (car plist))) + (setq p (plist-put p (car plist) (nth 1 plist)))) + (setq plist (cddr plist))) + p)) + +(defun mu4e-plist-remove-nils (plist) + "Remove all properties with value nil from PLIST." + (let (p) + (while plist + (when (cadr plist) + (setq p (plist-put p (car plist) (cadr plist)))) + (setq plist (cddr plist))) + p)) + (defun mu4e--message-hide-headers () "Hide headers based on the `message-hidden-headers' variable. This is mu4e's version of the post-emacs-28 `message-hide-headers', diff --git a/mu4e/mu4e-main.el b/mu4e/mu4e-main.el index 56dc82f2..803c269a 100644 --- a/mu4e/mu4e-main.el +++ b/mu4e/mu4e-main.el @@ -223,10 +223,11 @@ for aligning them." (mapconcat (lambda (item) (cl-destructuring-bind - (&key hide name key favorite query &allow-other-keys) item + (&key name key favorite query + hide hide-if-no-unread unread &allow-other-keys) item ;; hide items explicitly hidden, without key or wrong category. - (if hide - "" + (if (or hide (and hide-if-no-unread (zerop unread))) + "" ;; hide (let ((item-info ;; note, we have a function for the binding, ;; and perhaps a different one for the lambda. @@ -235,7 +236,7 @@ for aligning them." (list #'mu4e-search-maildir #'mu4e-search query)) ((eq item-type 'bookmarks) - (list #'mu4e-search-bookmark #'mu4e-search-bookmark + (list #'mu4e-search-bookmark #'mu4e-search-bookmark (mu4e-get-bookmark-query key))) (t (mu4e-error "Invalid item-type %s" item-type))))) @@ -410,8 +411,9 @@ instead." (unless (file-directory-p smtpmail-queue-dir) (mu4e-error "`smtpmail-queue-dir' does not exist")) (setq smtpmail-queue-mail (not smtpmail-queue-mail)) - (message (concat "Outgoing mail will now be " - (if smtpmail-queue-mail "queued" "sent directly"))) + (mu4e-message + (concat "Outgoing mail will now be " + (if smtpmail-queue-mail "queued" "sent directly"))) (unless (or (eq mu4e-split-view 'single-window) (not (buffer-live-p (get-buffer mu4e-main-buffer-name)))) (mu4e--main-redraw))) diff --git a/mu4e/mu4e-query-items.el b/mu4e/mu4e-query-items.el index 90aad7e3..1c5018c7 100644 --- a/mu4e/mu4e-query-items.el +++ b/mu4e/mu4e-query-items.el @@ -228,25 +228,21 @@ bookmark or maildir." (list :name name :query query - :key (plist-get item :key) :count count :unread unread :delta-count (- count baseline-count) :delta-unread delta-unread))) ;; remember the *effective* query too; we don't really need it, but ;; useful for debugging. - (unless (string= query effective-query) - (plist-put value :effective-query effective-query)) - ;;for matching maildir shortcuts - (when maildir (plist-put value :maildir maildir)) + (setq value (plist-put value :effective-query effective-query)) + (setq value (plist-put value :maildir maildir)) + ;; copy some other items from item. + (mu4e-plist-do (lambda (k v) + (when (memq k '(:key :maildir :hide :hide-if-no-unread + :hide-unread)) + (setq value (plist-put value k v)))) item) ;; nil props bring me discomfort - (when (plist-get item :favorite) - (plist-put value :favorite t)) - (when (plist-get item :hide) - (plist-put value :hide t)) - (when (plist-get item :hide-unread) - (plist-put value :hide-unread t)) - value)) + (mu4e-plist-remove-nils value))) data)) (defun mu4e-query-items (&optional type) diff --git a/mu4e/mu4e.texi b/mu4e/mu4e.texi index 3794ae17..088ed216 100644 --- a/mu4e/mu4e.texi +++ b/mu4e/mu4e.texi @@ -840,12 +840,15 @@ instance: :query "list:mu-discuss.googlegroups.com AND date:7d..now")) @end lisp -There are optional keys @t{:hide} to hide the bookmark from the main menu, but -still have it available (using @key{b})) and @t{:hide-unread} to avoid -generating the unread-number; that can be useful if you have bookmarks for slow -queries. Note that @t{:hide-unread} is implied when the query is not a string; -this for the common case where the query function involves some user input, -which would be disruptive in this case. +There are optional keys @code{:hide} to hide the bookmark or maildirs from the +main menu, but still have it available (using @key{b})), and +@code{:hide-if-no-unread} to hide it if there are no unread messages. + +To customize the display, there is also @code{:hide-unread} to avoid generating +the unread-number; that can be useful if you have bookmarks for slow queries. +Note that @code{:hide-unread} is implied when the query is not a string; this +for the common case where the query function involves some user input, which +would be disruptive in this case. There is also the optional @code{:favorite} property, which at most one bookmark should have; this bookmark is highlighted in the main view, and its @@ -2180,18 +2183,36 @@ be instructive: "List of pre-defined queries that are shown on the main screen. Each of the list elements is a plist with at least: -:name - the name of the query -:query - the query expression -:key - the shortcut key. +`:name' - the name of the query +`:query' - the query expression string or function +`:key' - the shortcut key (single character) -Optionally, you add the following: -:hide - if t, bookmark is hidden from the main-view and speedbar. -:hide-unread - do not show the counts of unread/total number - of matches for the query. This can be useful if a bookmark uses - a very slow query. :hide-unread is implied from :hide. -" +Optionally, you can add the following: + +- `:favorite' - if t, monitor the results of this query, and make +it eligible for showing its status in the modeline. At most +one bookmark should have this set to t (otherwise the _first_ +bookmark is the implicit favorite). The query for the `:favorite' +item must be unique among `mu4e-bookmarks' and +`mu4e-maildir-shortcuts'. +- `:hide' - if t, the bookmark is hidden from the main-view and +speedbar. +- `:hide-if-no-unread' - if t, the shortcut is hidden from + the main-view if it contains are no unread messages. + +You can also use: +- `:hide-unread' - do not show the counts of +unread/total number of matches for the query in the main-view. +This can be useful if a bookmark uses a very slow query. + +`:hide-unread' is implied from `:hide'. + +Note: for efficiency, queries used to determine the unread/all +counts do not discard duplicate or unreadable messages. Thus, the +numbers shown may differ from the number you get from a normal +query." :type '(repeat (plist)) - :group 'mu4e) + :group 'mu4e-bookmarks) @end lisp You can replace these or add your own items, by putting in your @@ -2303,14 +2324,18 @@ maildirs (folders) very quickly --- for example, getting to the @t{/lists} folder only requires you to type @kbd{jl}, then change to @t{/work} with @kbd{jw}. -While in queries you need to quote folder names (maildirs) with spaces in -them, you should @emph{not} quote them when used in -@code{mu4e-maildir-shortcuts}, since @t{mu4e} does that automatically for you. +While in queries you need to quote folder names (maildirs) with spaces in them, +you should @emph{not} quote them when used in @code{mu4e-maildir-shortcuts}, +since @t{mu4e} does that automatically for you. The very same shortcuts are used by @kbd{M-x mu4e-mark-for-move} (default shortcut @key{m}); so, for example, if you want to move a message to the @t{/archive} folder, you can do so by typing @kbd{ma}. +For further customization, you can use @code{:hide}, @code{:hide-if-no-unread}, +@code{:hide-unread} and @code{:favorite} properties, just like for +@ref{Bookmarks and Maildirs}. + @node Other search functionality @section Other search functionality