From 055cb774e060abfe71ee80f18bf248d5c7fe7b39 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Tue, 4 Feb 2025 22:12:00 +0200 Subject: [PATCH] mu4e: show short counts next to maildir/bookmark entry When you ask for bookmarks or maildirs through mu4e-ask-bookmark, mu4e-ask-maildir, the counts are displayed in the (default) completions next to the maildirs. This is a shorter version of the full display, just showing either the delta or the number of unread messages, if any. If you don't want to see these counts, there is mu4e-hide-short-counts. --- NEWS.org | 5 +++++ mu4e/mu4e-bookmarks.el | 34 +++++++++++++++++++++++----------- mu4e/mu4e-context.el | 8 +++++--- mu4e/mu4e-folders.el | 35 +++++++++++++++++++++++++++-------- mu4e/mu4e-query-items.el | 34 +++++++++++++++++++++++++++++++--- mu4e/mu4e-search.el | 2 +- mu4e/mu4e.texi | 11 ++++++++++- 7 files changed, 102 insertions(+), 27 deletions(-) diff --git a/NEWS.org b/NEWS.org index 15bc7b28..a28751bb 100644 --- a/NEWS.org +++ b/NEWS.org @@ -66,6 +66,11 @@ server interpreted the last query; this can be useful if you don't get the result you expected. + - When you ask for bookmarks or maildirs through ~mu4e-ask-bookmark~ or + ~mu4e-ask-maildir~, unread counts are displayed in the (default) completions UI + next to the maildir or bookmark. If you don't want to see these counts, set + ~mu4e-hide-short-counts~ to non-~nil~. + * 1.12 (released on February 24, 2024) ** Some highlights diff --git a/mu4e/mu4e-bookmarks.el b/mu4e/mu4e-bookmarks.el index ee071df2..f118133f 100644 --- a/mu4e/mu4e-bookmarks.el +++ b/mu4e/mu4e-bookmarks.el @@ -1,6 +1,6 @@ ;;; mu4e-bookmarks.el --- Bookmarks handling -*- lexical-binding: t -*- -;; Copyright (C) 2011-2023 Dirk-Jan C. Binnema +;; Copyright (C) 2011-2025 Dirk-Jan C. Binnema ;; Author: Dirk-Jan C. Binnema ;; Maintainer: Dirk-Jan C. Binnema @@ -28,7 +28,6 @@ (require 'mu4e-folders) (require 'mu4e-query-items) - ;;; Configuration (defgroup mu4e-bookmarks nil @@ -79,19 +78,33 @@ query." :type '(repeat (plist)) :group 'mu4e-bookmarks) +(declare-function mu4e-query-items "mu4e-query-items") +(declare-function mu4e--query-item-display-short-counts "mu4e-query-items") (defun mu4e-ask-bookmark (prompt) "Ask user for bookmark using PROMPT. Return the corresponding query. The bookmark are as defined in -`mu4e-bookmarks'." +`mu4e-bookmarks'. + +The names of the bookmarks are displayed in the minibuffer, +suffixed with the short version of the unread counts, as per +`mu4e--query-item-display-short-counts'." (unless (mu4e-bookmarks) (mu4e-error "No bookmarks defined")) - (let* ((bmarks (seq-map (lambda (bm) - (cons (format "%c%s" - (plist-get bm :key) - (plist-get bm :name)) - (plist-get bm :query))) - (mu4e-filter-single-key (mu4e-bookmarks))))) - (mu4e-read-option prompt bmarks))) + (let* ((bmarks + (seq-map + (lambda (bm) ;; find query-item for bookmark + (let* ((qitem (seq-find + (lambda (qitem) + (equal (plist-get bm :query) (plist-get qitem :query))) + (mu4e-query-items 'bookmarks))) + (unreads (mu4e--query-item-display-short-counts qitem))) + (cons (format "%c%s%s" + (plist-get bm :key) + (plist-get bm :name) + unreads) + (plist-get bm :query)))) + (mu4e-filter-single-key (mu4e-bookmarks))))) + (mu4e-read-option prompt bmarks))) (defun mu4e-get-bookmark-query (kar) "Get the corresponding bookmarked query for shortcut KAR. @@ -190,6 +203,5 @@ one, creates a propertized string for display in the modeline." (mouse-1 . mu4e-jump-to-favorite) (mouse-2 . mu4e-jump-to-favorite) (mouse-3 . mu4e-jump-to-favorite)))))) - (provide 'mu4e-bookmarks) ;;; mu4e-bookmarks.el ends here diff --git a/mu4e/mu4e-context.el b/mu4e/mu4e-context.el index e35ef78b..735eef37 100644 --- a/mu4e/mu4e-context.el +++ b/mu4e/mu4e-context.el @@ -1,6 +1,6 @@ ;;; mu4e-context.el --- Switching between settings -*- lexical-binding: t -*- -;; Copyright (C) 2015-2023 Dirk-Jan C. Binnema +;; Copyright (C) 2015-2025 Dirk-Jan C. Binnema ;; Author: Dirk-Jan C. Binnema ;; Maintainer: Dirk-Jan C. Binnema @@ -87,6 +87,9 @@ none." (cl-defstruct mu4e-context "A mu4e context object with the following members: - `name': the name of the context, eg. \"Work\" or \"Private\". + When using mu4e's default completion, it uses the first letter of + the name for this, so you should ensure those are different for + all contexts. - `enter-func': a parameterless function invoked when entering this context, or nil - `leave-func':a parameterless function invoked when leaving this @@ -104,7 +107,6 @@ none." ;; if it matches, nil otherwise vars) ;; alist of variables. - (defun mu4e--context-ask-user (prompt) "Let user choose some context based on its name with PROMPT." (when mu4e-contexts @@ -168,7 +170,7 @@ match, return the first. For MSG and POLICY, see nil (mu4e-context-name context)))))) (defun mu4e-context-determine (msg &optional policy) - "Return the first context where match-func evaluate to non-nil. + "Return first context for which match-func returns non-nil. MSG points to the plist for the message replied to or forwarded, or nil if there is no such MSG; similar to what diff --git a/mu4e/mu4e-folders.el b/mu4e/mu4e-folders.el index 09fdfa55..fad001e4 100644 --- a/mu4e/mu4e-folders.el +++ b/mu4e/mu4e-folders.el @@ -177,6 +177,16 @@ Converts from the old format if needed." item)) mu4e-maildir-shortcuts)) +(declare-function mu4e-query-items "mu4e-query-items") +(declare-function mu4e--query-item-display-short-counts "mu4e-query-items") + +(defun mu4e--query-item-for-maildir-shortcut (mds) + "Find the corresponding query-item for some maildir shortcut MDS. +This is based on their query. Return nil if not found." + (seq-find (lambda (qitem) + (equal (plist-get qitem :maildir) (plist-get mds :maildir))) + (mu4e-query-items 'maildirs))) + ;; the standard folders can be functions too (defun mu4e--get-folder (foldervar msg) "Within the mu-context of MSG, get message folder FOLDERVAR. @@ -231,7 +241,7 @@ to create it; otherwise return nil." (let ((seems-to-exist (file-directory-p dir))) (when (or seems-to-exist (yes-or-no-p (mu4e-format "%s does not exist yet. Create now?" dir))) - ;; even when the maildir already seems to exist, call mkdir for a deeper + ;; even when the maildir already seems to exist, call mkdir for a deepe ;; check. However only get an update when the maildir is totally new. (mu4e--server-mkdir dir (not seems-to-exist)) t))) @@ -245,14 +255,23 @@ to create it; otherwise return nil." If the special shortcut \"o\" (for _o_ther) is used, or if (mu4e-maildir-shortcuts) evaluates to nil, let user choose -from all maildirs under `mu4e-maildir'." +from all maildirs under `mu4e-maildir'. + +The names of the maildirs are displayed in the minibuffer, +suffixed with the short version of the unread counts, as per +`mu4e--query-item-display-short-counts'." (let* ((options - (seq-map (lambda (md) - (cons - (format "%c%s" (plist-get md :key) - (or (plist-get md :name) - (plist-get md :maildir))) - (plist-get md :maildir))) + (seq-map + (lambda (md) + (let* ((qitem (mu4e--query-item-for-maildir-shortcut md)) + (unreads (mu4e--query-item-display-short-counts qitem))) + (cons + (format "%c%s%s" + (plist-get md :key) + (or (plist-get md :name) + (plist-get md :maildir)) + unreads) + (plist-get md :maildir)))) (mu4e-filter-single-key (mu4e-maildir-shortcuts)))) (response (if (not options) diff --git a/mu4e/mu4e-query-items.el b/mu4e/mu4e-query-items.el index b420155b..90aad7e3 100644 --- a/mu4e/mu4e-query-items.el +++ b/mu4e/mu4e-query-items.el @@ -1,6 +1,6 @@ ;;; mu4e-query-items.el --- Manage query results -*- lexical-binding: t -*- -;; Copyright (C) 2023-2024 Dirk-Jan C. Binnema +;; Copyright (C) 2023-2025 Dirk-Jan C. Binnema ;; Author: Dirk-Jan C. Binnema ;; Maintainer: Dirk-Jan C. Binnema @@ -61,6 +61,12 @@ incorrect results for the various unread counts." :type 'function :group 'mu4e-search) +(defcustom mu4e-hide-short-counts nil + "Hide the short count of unread messages. +As used in `mu4e-ask-bookmark' and `mu4e-ask-folder'." + :type 'boolean + :group 'mu4e) + (defvar mu4e--query-items-baseline nil "Some previous version of the query-items. This is used as the baseline to track updates by comparing it to @@ -98,7 +104,9 @@ If ITEMS does not yet have a favorite item, pick the first." (declare-function mu4e-maildir-shortcuts "mu4e-folders") (defun mu4e--query-item-display-counts (item) - "Get the count display string for some query-data ITEM." + "Get the count display string for some query-data ITEM. +If the items has its `:hide-unread' at a non-nil value, return +an empty string." ;; purely for display, but we need it in the main menu, modeline ;; so let's keep it consistent. (cl-destructuring-bind (&key unread hide-unread delta-unread count @@ -116,6 +124,25 @@ If ITEMS does not yet have a favorite item, pick the first." (propertize (number-to-string count) 'help-echo "Total number"))))) +(defun mu4e--query-item-display-short-counts (item) + "Get the short count display string for some query-data ITEM. +This gets the delta if it is greater than zero. Otherwise, the +total unread count if is greater than zero. Otherwise, an empty +string. + +If the items has its `:hide-unread' at a non-nil value, or if +`mu4e-hide-short-counts' is non-nil, returns an empty string." + (cl-destructuring-bind (&key unread hide-unread delta-unread + &allow-other-keys) item + (if (or hide-unread mu4e-hide-short-counts) + "" + (concat + (if (> (or delta-unread 0) 0) + (concat "(" (propertize (format "+%d" delta-unread) 'face 'mu4e-unread-face) ")") + (if (> (or unread 0) 0) + (concat "(" (propertize (format "%d" unread) 'face 'mu4e-header-key-face) ")") + "")))))) + (defun mu4e--query-items-refresh (&optional reset-baseline) "Get the latest query data from the mu4e server. With RESET-BASELINE, reset the baseline first." @@ -210,7 +237,8 @@ bookmark or maildir." ;; 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)) ;; nil props bring me discomfort (when (plist-get item :favorite) (plist-put value :favorite t)) diff --git a/mu4e/mu4e-search.el b/mu4e/mu4e-search.el index 2fdb8ee4..f72d9da2 100644 --- a/mu4e/mu4e-search.el +++ b/mu4e/mu4e-search.el @@ -1,6 +1,6 @@ ;;; mu4e-search.el --- Search-related functions -*- lexical-binding: t -*- -;; Copyright (C) 2021,2024 Dirk-Jan C. Binnema +;; Copyright (C) 2021-2025 Dirk-Jan C. Binnema ;; Author: Dirk-Jan C. Binnema ;; Maintainer: Dirk-Jan C. Binnema diff --git a/mu4e/mu4e.texi b/mu4e/mu4e.texi index 2579909b..3261e4f8 100644 --- a/mu4e/mu4e.texi +++ b/mu4e/mu4e.texi @@ -847,7 +847,7 @@ attention: ;; bookmark for message that require quick attention '( :name "Urgent" :key ?u - :query "maildir:/inbox AND from:boss@@exmaple.com")) + :query "maildir:/inbox AND from:boss@@example.com")) @end lisp Note that @t{mu4e} resets the baseline when you are interacting with it (for @@ -859,6 +859,13 @@ as being a special kind of bookmark query that matches a Maildir. You can configure this using the variable @code{mu4e-maildir-shortcuts}; see its docstring and @ref{Maildir searches} for more details. +When you ask for bookmarks or maildirs through @code{mu4e-ask-bookmark}, +@code{mu4e-ask-maildir}, the counts are displayed in the (default) completions +next to the maildir or bookmark entry. This is a shorter version of the full +display, just showing either the delta or the number of unread messages, if any. +If you do not want to see these counts, set @t{mu4e-hide-short-counts} to +non-@t{nil}. + @node Miscellaneous @section Miscellaneous @@ -2610,6 +2617,8 @@ Let's see what's contained in a context. Most of it is optional. A @code{mu4e-context} is Lisp object with the following members: @itemize @item @t{name}: the name of the context, e.g. @t{work} or @t{private} +in the default completion UI, @t{mu4e} uses the first letter of the context to +select them, so you should ensure all start with a different letter @item @t{vars}: an association-list (alist) of variable settings for this account. @item @t{enter-func}: