Merge branch 'wip/djcb/toggle-property'

This commit is contained in:
Dirk-Jan C. Binnema
2022-12-11 15:36:57 +02:00
7 changed files with 603 additions and 565 deletions

19
.dir-locals.el Normal file
View File

@ -0,0 +1,19 @@
;;; Directory Local Variables -*- no-byte-compile: t; -*-
;;; For more information see (info "(emacs) Directory Variables")
((nil . ((tab-width . 8)
(fill-column . 80)
;; (commment-fill-column . 80)
(emacs-lisp-docstring-fill-column . 65)
(bug-reference-url-format . "https://github.com/djcb/mu/issues/%s")))
(c-mode . ((c-file-style . "linux")
(indent-tabs-mode . t)
(mode . bug-reference-prog)))
(c++-mode . ((c-file-style . "linux")
(fill-column . 100)
;; (comment-fill-column . 80)
(mode . bug-reference-prog)))
(emacs-lisp-mode . ((indent-tabs-mode . nil)
(mode . bug-reference-prog)))
(lisp-data-mode . ((indent-tabs-mode . nil)))
(texinfo-mode . ((mode . bug-reference-prog)))
(org-mode . ((mode . bug-reference))))

View File

@ -15,13 +15,31 @@
there's now 'z' binding (~mu4e-view-detach~), to 'detach' view and alllow there's now 'z' binding (~mu4e-view-detach~), to 'detach' view and alllow
for keeping multiple views around; see the Mu4e manual for details. for keeping multiple views around; see the Mu4e manual for details.
- One very visible (experimental) change is that the main-window is no
longer full-screen
- when moving messages (which includes changing flags), file-flags changes - when moving messages (which includes changing flags), file-flags changes
are propagated to duplicates of the messages; that is, e.g. the /Seen/ or are propagated to duplicates of the messages; that is, e.g. the /Seen/ or
/Replied/ status is propagated to all duplicates (earlier, this was only /Replied/ status is propagated to all duplicates (earlier, this was only
done when marking a message as read). Note, /Draft/, /Flagged/ and /Trashed/ done when marking a message as read). Note, /Draft/, /Flagged/ and /Trashed/
flags are deliberately *not* propagated. flags are deliberately *not* propagated.
- teach ~mu4e-copy-thing-at-point~ about shr links - teach ~mu4e-copy-thing-at-point~ about ~shr~ links
- The ~mu4e-headers-toggle-setting~ has been renamed
~mu4e-headers-toggle-property~ and has the new default binding ~P~, which
works in both the headers-view and message-view. The older functions
~mu4e-headers-toggle-threading~, ~mu4e-headers-toggle-threading~,
~mu4e-headers-toggle-full-search~ ~mu4e-headers-toggle-include-related~,
~full-search~skip-duplicates~ have been removed (with their keybindings) in
favor of ~mu4e-headers-toggle-property~.
- There's also a new property ~mu4e-headers-hide-enabled~, which controls
wheter ~mu4e-headers-hide-predicate~ is applied (when non-~nil~). This can be
used to temporarily turn the predicate off/on.
- When searching, the number of hidden messages is now shown in the
message footer along with the number of Found messages
- all the obsolete function and variable aliases have been moved to - all the obsolete function and variable aliases have been moved to
~mu4e-obsolete.el~ so we can unclutter the non-obsolete code a bit. ~mu4e-obsolete.el~ so we can unclutter the non-obsolete code a bit.

View File

@ -32,7 +32,8 @@
(require 'fringe) (require 'fringe)
(require 'hl-line) (require 'hl-line)
(require 'mailcap) (require 'mailcap)
(require 'mule-util) ;; seems _some_ people need this for truncate-string-ellipsis (require 'mule-util) ;; seems _some_ people need this for
;; truncate-string-ellipsis
(require 'mu4e-update) (require 'mu4e-update)
@ -129,11 +130,10 @@ next mail after marking a message in header view."
(defvar mu4e-headers-hide-predicate nil (defvar mu4e-headers-hide-predicate nil
"Predicate function to hide matching heasders. "Predicate function to hide matching headers.
If the function evaluates to non-nil when applied a a message Either nil or a function taking one message plist parameter and
plist, do not show the corresponding header. The function takes which which return non-nil for messages that should be hidden from
one parameter MSG, which is the message plist for the message to the search results. Also see `mu4e-headers-hide-enabled'.
be hidden or not.
Example that hides all trashed messages: Example that hides all trashed messages:
@ -141,8 +141,14 @@ Example that hides all trashed messages:
(lambda (msg) (lambda (msg)
(member \='trashed (mu4e-message-field msg :flags)))).") (member \='trashed (mu4e-message-field msg :flags)))).")
(defvar mu4e-headers-hide-enabled t
"Whether `mu4e-headers-hide-predicate' should be active.
This can be used to toggle use of the predicate through
`mu4e-headers-toggle-property'.")
(defcustom mu4e-headers-visible-flags (defcustom mu4e-headers-visible-flags
'(draft flagged new passed replied trashed attach encrypted signed list personal) '(draft flagged new passed replied trashed attach encrypted signed
list personal)
"An ordered list of flags to show in the headers buffer. "An ordered list of flags to show in the headers buffer.
Each element is a symbol in the list. Each element is a symbol in the list.
@ -269,6 +275,9 @@ Must have the same length as `mu4e-headers-thread-connection-prefix'.")
"Non-fancy and fancy labels to indicate related search in the mode-line.") "Non-fancy and fancy labels to indicate related search in the mode-line.")
(defvar mu4e-headers-skip-duplicates-label '("U" . "") ;; 'U' for 'unique' (defvar mu4e-headers-skip-duplicates-label '("U" . "") ;; 'U' for 'unique'
"Non-fancy and fancy labels for include-related search in the mode-line.") "Non-fancy and fancy labels for include-related search in the mode-line.")
(defvar mu4e-headers-hide-label '("H" . "")
"Non-fancy and fancy labels to indicate header-hiding is active in
the mode-line.")
;;;; Various ;;;; Various
@ -333,6 +342,9 @@ In the format needed for `mu4e-read-option'.")
"If non-nil, report on the time it took to render the messages. "If non-nil, report on the time it took to render the messages.
This is mostly useful for profiling.") This is mostly useful for profiling.")
(defvar mu4e~headers-hidden 0
"Number of headers hidden due to `mu4e-headers-hide-predicate'.")
;;; Clear ;;; Clear
@ -341,7 +353,8 @@ This is mostly useful for profiling.")
"Clear the headers buffer and related data structures. "Clear the headers buffer and related data structures.
Optionally, show TEXT." Optionally, show TEXT."
(when (buffer-live-p (mu4e-get-headers-buffer)) (when (buffer-live-p (mu4e-get-headers-buffer))
(setq mu4e~headers-render-start (float-time)) (setq mu4e~headers-render-start (float-time)
mu4e~headers-hidden 0)
(let ((inhibit-read-only t)) (let ((inhibit-read-only t))
(with-current-buffer (mu4e-get-headers-buffer) (with-current-buffer (mu4e-get-headers-buffer)
(mu4e--mark-clear) (mu4e--mark-clear)
@ -374,7 +387,8 @@ into a string."
(connection (funcall get-prefix mu4e-headers-thread-connection-prefix)) (connection (funcall get-prefix mu4e-headers-thread-connection-prefix))
(blank (funcall get-prefix mu4e-headers-thread-blank-prefix)) (blank (funcall get-prefix mu4e-headers-thread-blank-prefix))
(orphan (funcall get-prefix mu4e-headers-thread-orphan-prefix)) (orphan (funcall get-prefix mu4e-headers-thread-orphan-prefix))
(single-orphan (funcall get-prefix mu4e-headers-thread-single-orphan-prefix)) (single-orphan (funcall get-prefix
mu4e-headers-thread-single-orphan-prefix))
(duplicate (funcall get-prefix mu4e-headers-thread-duplicate-prefix)) (duplicate (funcall get-prefix mu4e-headers-thread-duplicate-prefix))
(t "?")))) (t "?"))))
@ -481,7 +495,8 @@ with DOCID which must be present in the headers buffer."
(if single-orphan 'single-orphan (if single-orphan 'single-orphan
(if (and orphan (if (and orphan
(or first-child (or first-child
(not (eq mu4e-headers-thread-mark-as-orphan 'first)))) (not (eq mu4e-headers-thread-mark-as-orphan
'first))))
'orphan 'orphan
(if last-child 'last-child (if last-child 'last-child
(if first-child 'first-child (if first-child 'first-child
@ -650,7 +665,10 @@ space propertized with a `display' text property which expands to
(let* ((field (car f-w)) (let* ((field (car f-w))
(width (cdr f-w)) (width (cdr f-w))
(val (mu4e~headers-field-value msg field)) (val (mu4e~headers-field-value msg field))
(val (and val (if width (mu4e~headers-truncate-field field val width) val)))) (val (and val
(if width
(mu4e~headers-truncate-field field val width)
val))))
val)) val))
(defsubst mu4e~headers-apply-flags (msg fieldval) (defsubst mu4e~headers-apply-flags (msg fieldval)
@ -671,15 +689,18 @@ space propertized with a `display' text property which expands to
fieldval)) fieldval))
(defsubst mu4e~message-header-line (msg) (defsubst mu4e~message-header-line (msg)
"Return a propertized description of MSG suitable for "Return a propertized description of message MSG suitable for
displaying in the header view." displaying in the header view."
(unless (and mu4e-headers-hide-predicate (if (and mu4e-headers-hide-enabled mu4e-headers-hide-predicate
(funcall mu4e-headers-hide-predicate msg)) (funcall mu4e-headers-hide-predicate msg))
(progn
(cl-incf mu4e~headers-hidden)
nil)
(progn
(mu4e~headers-apply-flags (mu4e~headers-apply-flags
msg msg
(mapconcat (lambda (f-w) (mu4e~headers-field-handler f-w msg)) (mapconcat (lambda (f-w) (mu4e~headers-field-handler f-w msg))
mu4e-headers-fields " ")))) mu4e-headers-fields " ")))))
(defsubst mu4e~headers-insert-header (msg pos) (defsubst mu4e~headers-insert-header (msg pos)
"Insert a header for MSG at point POS." "Insert a header for MSG at point POS."
@ -716,7 +737,8 @@ docid is not found."
(defun mu4e~headers-view-this-message-p (docid) (defun mu4e~headers-view-this-message-p (docid)
"Is DOCID currently being viewed?" "Is DOCID currently being viewed?"
(mu4e-get-view-buffers (lambda (_) (eq docid (plist-get mu4e~view-message :docid))))) (mu4e-get-view-buffers
(lambda (_) (eq docid (plist-get mu4e~view-message :docid)))))
;; note: this function is very performance-sensitive ;; note: this function is very performance-sensitive
(defun mu4e~headers-append-handler (msglst) (defun mu4e~headers-append-handler (msglst)
@ -869,8 +891,9 @@ after the end of the search results."
(goto-char (point-max)) (goto-char (point-max))
(let ((inhibit-read-only t) (let ((inhibit-read-only t)
(str (if (zerop count) mu4e~no-matches mu4e~end-of-results)) (str (if (zerop count) mu4e~no-matches mu4e~end-of-results))
(msg (format "Found %d matching message%s%s" (msg (format "Found %d matching message%s; %d hidden%s"
count (if (= 1 count) "" "s") count (if (= 1 count) "" "s")
mu4e~headers-hidden
(mu4e~headers-benchmark-message count)))) (mu4e~headers-benchmark-message count))))
(insert (propertize str 'face 'mu4e-system-face 'intangible t)) (insert (propertize str 'face 'mu4e-system-face 'intangible t))
@ -882,7 +905,8 @@ after the end of the search results."
(when mu4e--search-msgid-target (when mu4e--search-msgid-target
(if (eq (current-buffer) (window-buffer)) (if (eq (current-buffer) (window-buffer))
(mu4e-headers-goto-message-id mu4e--search-msgid-target) (mu4e-headers-goto-message-id mu4e--search-msgid-target)
(let* ((pos (mu4e-headers-goto-message-id mu4e--search-msgid-target))) (let* ((pos (mu4e-headers-goto-message-id
mu4e--search-msgid-target)))
(when pos (when pos
(set-window-point (get-buffer-window nil t) pos))))) (set-window-point (get-buffer-window nil t) pos)))))
(when (and mu4e--search-view-target (mu4e-message-at-point 'noerror)) (when (and mu4e--search-view-target (mu4e-message-at-point 'noerror))
@ -931,14 +955,7 @@ after the end of the search results."
(define-key map "j" 'mu4e~headers-jump-to-maildir) (define-key map "j" 'mu4e~headers-jump-to-maildir)
(define-key map "O" 'mu4e-headers-change-sorting) (define-key map "O" 'mu4e-headers-change-sorting)
(define-key map "M" 'mu4e-headers-toggle-setting) (define-key map "P" 'mu4e-headers-toggle-property)
;; these are impossible to remember; use mu4e-headers-toggle-setting
;; instead :)
(define-key map "P" 'mu4e-headers-toggle-threading)
(define-key map "Q" 'mu4e-headers-toggle-full-search)
(define-key map "W" 'mu4e-headers-toggle-include-related)
(define-key map "V" 'mu4e-headers-toggle-skip-duplicates)
(define-key map "q" 'mu4e~headers-quit-buffer) (define-key map "q" 'mu4e~headers-quit-buffer)
(define-key map "g" 'mu4e-search-rerun) ;; for compatibility (define-key map "g" 'mu4e-search-rerun) ;; for compatibility
@ -962,7 +979,8 @@ after the end of the search results."
(define-key map (kbd "C-+") 'mu4e-headers-split-view-grow) (define-key map (kbd "C-+") 'mu4e-headers-split-view-grow)
(define-key map (kbd "C--") 'mu4e-headers-split-view-shrink) (define-key map (kbd "C--") 'mu4e-headers-split-view-shrink)
(define-key map (kbd "<C-kp-add>") 'mu4e-headers-split-view-grow) (define-key map (kbd "<C-kp-add>") 'mu4e-headers-split-view-grow)
(define-key map (kbd "<C-kp-subtract>") 'mu4e-headers-split-view-shrink) (define-key map (kbd "<C-kp-subtract>")
'mu4e-headers-split-view-shrink)
;; switching to view mode (if it's visible) ;; switching to view mode (if it's visible)
(define-key map "y" 'mu4e-select-other-view) (define-key map "y" 'mu4e-select-other-view)
@ -986,10 +1004,14 @@ after the end of the search results."
(define-key map (kbd "=") 'mu4e-headers-mark-for-untrash) (define-key map (kbd "=") 'mu4e-headers-mark-for-untrash)
(define-key map (kbd "&") 'mu4e-headers-mark-custom) (define-key map (kbd "&") 'mu4e-headers-mark-custom)
(define-key map (kbd "*") 'mu4e-headers-mark-for-something) (define-key map (kbd "*")
(define-key map (kbd "<kp-multiply>") 'mu4e-headers-mark-for-something) 'mu4e-headers-mark-for-something)
(define-key map (kbd "<insertchar>") 'mu4e-headers-mark-for-something) (define-key map (kbd "<kp-multiply>")
(define-key map (kbd "<insert>") 'mu4e-headers-mark-for-something) 'mu4e-headers-mark-for-something)
(define-key map (kbd "<insertchar>")
'mu4e-headers-mark-for-something)
(define-key map (kbd "<insert>")
'mu4e-headers-mark-for-something)
(define-key map (kbd "#") 'mu4e-mark-resolve-deferred-marks) (define-key map (kbd "#") 'mu4e-mark-resolve-deferred-marks)
@ -1023,18 +1045,6 @@ after the end of the search results."
(define-key menumap [sepa0] '("--")) (define-key menumap [sepa0] '("--"))
(define-key menumap [toggle-include-related]
'(menu-item "Toggle related messages"
mu4e-headers-toggle-include-related
:button (:toggle .
(and (boundp 'mu4e-headers-include-related)
mu4e-headers-include-related))))
(define-key menumap [toggle-threading]
'(menu-item "Toggle threading" mu4e-headers-toggle-threading
:button (:toggle .
(and (boundp 'mu4e-search-threads)
mu4e-search-threads))))
(define-key menumap "|" '("Pipe through shell" . mu4e-view-pipe)) (define-key menumap "|" '("Pipe through shell" . mu4e-view-pipe))
(define-key menumap [sepa1] '("--")) (define-key menumap [sepa1] '("--"))
@ -1296,12 +1306,15 @@ message plist, or nil if not found."
`((,mu4e-search-full . ,mu4e-headers-full-label) `((,mu4e-search-full . ,mu4e-headers-full-label)
(,mu4e-headers-include-related . ,mu4e-headers-related-label) (,mu4e-headers-include-related . ,mu4e-headers-related-label)
(,mu4e-search-threads . ,mu4e-headers-threaded-label) (,mu4e-search-threads . ,mu4e-headers-threaded-label)
(,mu4e-headers-skip-duplicates . ,mu4e-headers-skip-duplicates-label)) (,mu4e-headers-skip-duplicates
. ,mu4e-headers-skip-duplicates-label)
(,mu4e-headers-hide-enabled . ,mu4e-headers-hide-label))
"")) ""))
(name "mu4e-headers")) (name "mu4e-headers"))
(setq mode-name name) (setq mode-name name)
(setq mu4e~headers-mode-line-label (concat flagstr " " mu4e--search-last-query)) (setq mu4e~headers-mode-line-label
(concat flagstr " " mu4e--search-last-query))
(make-local-variable 'global-mode-string) (make-local-variable 'global-mode-string)
@ -1407,7 +1420,8 @@ matching messages with that mark."
(let ((name (mu4e-contact-name contact)) (let ((name (mu4e-contact-name contact))
(email (mu4e-contact-email contact))) (email (mu4e-contact-email contact)))
(or (and name (string-match pattern name)) (or (and name (string-match pattern name))
(and email (string-match pattern email))))) value) (and email (string-match pattern email)))))
value)
(string-match pattern (or value "")))))))) (string-match pattern (or value ""))))))))
(defun mu4e-headers-mark-custom () (defun mu4e-headers-mark-custom ()
@ -1501,7 +1515,8 @@ user)."
(or field (or field
(mu4e-read-option "Sortfield: " mu4e~headers-sort-field-choices))) (mu4e-read-option "Sortfield: " mu4e~headers-sort-field-choices)))
;; note: 'sortable' is either a boolean (meaning: if non-nil, this is ;; note: 'sortable' is either a boolean (meaning: if non-nil, this is
;; sortable field), _or_ another field (meaning: sort by this other field). ;; sortable field), _or_ another field (meaning: sort by this other
;; field).
(sortable (plist-get (cdr (assoc field mu4e-header-info)) :sortable)) (sortable (plist-get (cdr (assoc field mu4e-header-info)) :sortable))
;; error check ;; error check
(sortable (sortable
@ -1526,69 +1541,31 @@ user)."
(symbol-name mu4e-headers-sort-direction)) (symbol-name mu4e-headers-sort-direction))
(mu4e-search-rerun))) (mu4e-search-rerun)))
(defun mu4e-headers-toggle-property (&optional dont-refresh key)
(defun mu4e-headers-toggle-setting (&optional dont-refresh)
"Toggle some aspect of headers display. "Toggle some aspect of headers display.
When prefix-argument DONT-REFRESH is non-nill, do not refresh the When prefix-argument DONT-REFRESH is non-nil, do not refresh the
last search with the new setting." last search with the new setting.
If KEY is provided, use it instead of asking user."
(interactive "P") (interactive "P")
(let* ((toggles '(("fFull-search" . mu4e-search-full) (let* ((toggles '(("fFull-search" . mu4e-search-full)
("rInclude-related" . mu4e-headers-include-related) ("rInclude-related" . mu4e-headers-include-related)
("tShow threads" . mu4e-search-threads) ("tShow threads" . mu4e-search-threads)
("uSkip duplicates" . mu4e-headers-skip-duplicates))) ("uSkip duplicates" . mu4e-headers-skip-duplicates)
("pHide-predicate" . mu4e-headers-hide-enabled)))
(toggles (seq-map (toggles (seq-map
(lambda (cell) (lambda (cell)
(cons (cons
(concat (car cell) (format" (%s)" (concat (car cell)
(format" (%s)"
(if (symbol-value (cdr cell)) "on" "off"))) (if (symbol-value (cdr cell)) "on" "off")))
(cdr cell))) toggles)) (cdr cell))) toggles))
(choice (mu4e-read-option "Toggle setting " toggles))) (choice (mu4e-read-option "Toggle property " toggles key)))
(when choice (when choice
(set choice (not (symbol-value choice))) (set choice (not (symbol-value choice)))
(mu4e-message "Set `%s' to %s" (symbol-name choice) (symbol-value choice)) (mu4e-message "Set `%s' to %s" (symbol-name choice) (symbol-value choice))
(unless dont-refresh (unless dont-refresh
(mu4e-search-rerun))))) (mu4e-search-rerun)))))
(defun mu4e~headers-toggle (name togglevar dont-refresh)
"Toggle variable TOGGLEVAR for feature NAME. Unless DONT-REFRESH is non-nil,
re-run the last search."
(set togglevar (not (symbol-value togglevar)))
(mu4e-message "%s turned %s%s"
name
(if (symbol-value togglevar) "on" "off")
(if dont-refresh
" (press 'g' to refresh)" ""))
(unless dont-refresh
(mu4e-search-rerun)))
(defun mu4e-headers-toggle-threading (&optional dont-refresh)
"Toggle `mu4e-search-threads'. With prefix-argument, do
_not_ refresh the last search with the new setting for threading."
(interactive "P")
(mu4e~headers-toggle "Threading" 'mu4e-search-threads dont-refresh))
(defun mu4e-headers-toggle-full-search (&optional dont-refresh)
"Toggle `mu4e-search-full'. With prefix-argument, do
_not_ refresh the last search with the new setting for threading."
(interactive "P")
(mu4e~headers-toggle "Full-search"
'mu4e-search-full dont-refresh))
(defun mu4e-headers-toggle-include-related (&optional dont-refresh)
"Toggle `mu4e-headers-include-related'. With prefix-argument, do
_not_ refresh the last search with the new setting for threading."
(interactive "P")
(mu4e~headers-toggle "Include-related"
'mu4e-headers-include-related dont-refresh))
(defun mu4e-headers-toggle-skip-duplicates (&optional dont-refresh)
"Toggle `mu4e-headers-skip-duplicates'. With prefix-argument, do
_not_ refresh the last search with the new setting for threading."
(interactive "P")
(mu4e~headers-toggle "Skip-duplicates"
'mu4e-headers-skip-duplicates dont-refresh))
(defun mu4e-headers-view-message () (defun mu4e-headers-view-message ()
"View message at point." "View message at point."
(interactive) (interactive)
@ -1637,7 +1614,8 @@ return nil."
;; update all windows showing the headers buffer ;; update all windows showing the headers buffer
(walk-windows (walk-windows
(lambda (win) (lambda (win)
(when (eq (window-buffer win) (mu4e-get-headers-buffer (buffer-name))) (when (eq (window-buffer win)
(mu4e-get-headers-buffer (buffer-name)))
(set-window-point win (point)))) (set-window-point win (point))))
nil t) nil t)
;; If the assigned (and buffer-local) `mu4e~headers-view-win' ;; If the assigned (and buffer-local) `mu4e~headers-view-win'
@ -1701,7 +1679,8 @@ given, offer to edit the search query before executing it."
(list maildir current-prefix-arg))) (list maildir current-prefix-arg)))
(when maildir (when maildir
(let* ((query (format "maildir:\"%s\"" maildir)) (let* ((query (format "maildir:\"%s\"" maildir))
(query (if edit (mu4e-search-read-query "Refine query: " query) query))) (query (if edit
(mu4e-search-read-query "Refine query: " query) query)))
(mu4e-mark-handle-when-leaving) (mu4e-mark-handle-when-leaving)
(mu4e-search query)))) (mu4e-search query))))
@ -1741,7 +1720,8 @@ pass ACTIONFUNC, which is a function that takes a msg-plist
argument." argument."
(interactive) (interactive)
(let ((msg (mu4e-message-at-point)) (let ((msg (mu4e-message-at-point))
(afunc (or actionfunc (mu4e-read-option "Action: " mu4e-headers-actions)))) (afunc (or actionfunc
(mu4e-read-option "Action: " mu4e-headers-actions))))
(funcall afunc msg))) (funcall afunc msg)))
(defun mu4e-headers-mark-and-next (mark) (defun mu4e-headers-mark-and-next (mark)
@ -1779,14 +1759,18 @@ other windows."
(when mu4e-dim-when-loading (when mu4e-dim-when-loading
(setq mu4e--loading-overlay-bg (setq mu4e--loading-overlay-bg
(let ((overlay (make-overlay (point-min) (point-max)))) (let ((overlay (make-overlay (point-min) (point-max))))
(overlay-put overlay 'face `(:foreground "gray22" :background (overlay-put overlay 'face
,(face-attribute 'default :background))) `(:foreground "gray22" :background
,(face-attribute 'default
:background)))
(overlay-put overlay 'priority 9998) (overlay-put overlay 'priority 9998)
overlay))) overlay)))
(setq mu4e--loading-overlay-text (setq mu4e--loading-overlay-text
(let ((overlay (make-overlay (point-min) (point-min)))) (let ((overlay (make-overlay (point-min) (point-min))))
(overlay-put overlay 'priority 9999) (overlay-put overlay 'priority 9999)
(overlay-put overlay 'before-string (propertize "Loading…\n" 'face 'mu4e-header-title-face)) (overlay-put overlay 'before-string
(propertize "Loading…\n"
'face 'mu4e-header-title-face))
overlay))) overlay)))
(when mu4e--loading-overlay-bg (when mu4e--loading-overlay-bg
(delete-overlay mu4e--loading-overlay-bg)) (delete-overlay mu4e--loading-overlay-bg))

View File

@ -164,22 +164,24 @@ Does a local-exit and does not return."
nil nil
(mu4e-error "Missing property %s in %s" prop lst)))) (mu4e-error "Missing property %s in %s" prop lst))))
(defun mu4e--read-char-choice (prompt choices) (defun mu4e--read-char-choice (prompt choices &optional key)
"Read and return one of CHOICES, prompting for PROMPT. "Read and return one of CHOICES, prompting for PROMPT.
Any input that is not one of CHOICES is ignored. This is mu4e's Any input that is not one of CHOICES is ignored. This is mu4e's
version of `read-char-choice' which becomes case-insentive after version of `read-char-choice' which becomes case-insentive after
trying an exact match." trying an exact match.
If optional KEY is provided, use that instead of asking user."
(let ((choice) (chosen) (inhibit-quit nil)) (let ((choice) (chosen) (inhibit-quit nil))
(while (not chosen) (while (not chosen)
(message nil);; this seems needed... (message nil);; this seems needed...
(setq choice (read-char-exclusive prompt)) (setq choice (or key (read-char-exclusive prompt)))
(if (eq choice 27) (keyboard-quit)) ;; quit if ESC is pressed (if (eq choice 27) (keyboard-quit)) ;; quit if ESC is pressed
(setq chosen (or (member choice choices) (setq chosen (or (member choice choices)
(member (downcase choice) choices) (member (downcase choice) choices)
(member (upcase choice) choices)))) (member (upcase choice) choices))))
(car chosen))) (car chosen)))
(defun mu4e-read-option (prompt options) (defun mu4e-read-option (prompt options &optional key)
"Ask user for an option from a list on the input area. "Ask user for an option from a list on the input area.
PROMPT describes a multiple-choice question to the user. OPTIONS PROMPT describes a multiple-choice question to the user. OPTIONS
describe the options, and is a list of cells describing describe the options, and is a list of cells describing
@ -200,6 +202,9 @@ user can then choose by typing CHAR. Example:
User now will be presented with a list: \"Choose an animal: User now will be presented with a list: \"Choose an animal:
[M]onkey, [G]nu, [x]Moose\". [M]onkey, [G]nu, [x]Moose\".
If optional character KEY is provied, use that instead of asking
the user.
Function returns the cdr of the list element." Function returns the cdr of the list element."
(let* ((prompt (mu4e-format "%s" prompt)) (let* ((prompt (mu4e-format "%s" prompt))
(optionsstr (optionsstr
@ -221,7 +226,8 @@ Function returns the cdr of the list element."
" [" (propertize "C-g" 'face 'mu4e-highlight-face) " [" (propertize "C-g" 'face 'mu4e-highlight-face)
" to cancel]") " to cancel]")
;; the allowable chars ;; the allowable chars
(seq-map (lambda(elm) (string-to-char (car elm))) options))) (seq-map (lambda(elm) (string-to-char (car elm))) options)
key))
(chosen (chosen
(seq-find (seq-find
(lambda (option) (eq response (string-to-char (car option)))) (lambda (option) (eq response (string-to-char (car option))))

View File

@ -150,6 +150,16 @@
(make-obsolete-variable 'mu4e-headers-field-properties-function (make-obsolete-variable 'mu4e-headers-field-properties-function
"not used" "1.6.1") "not used" "1.6.1")
(define-obsolete-function-alias 'mu4e-headers-toggle-setting
'mu4e-headers-toggle-property "1.9.5")
(define-obsolete-function-alias 'mu4e-headers-toggle-threading
'mu4e-headers-toggle-property "1.9.5")
(define-obsolete-function-alias 'mu4e-headers-toggle-full-search
'mu4e-headers-toggle-settin "1.9.5")
(define-obsolete-function-alias 'mu4e-headers-toggle-include-related
'mu4e-headers-toggle-property "1.9.5")
(define-obsolete-function-alias 'mu4e-headers-toggle-skip-duplicates
'mu4e-headers-toggle-property "1.9.5")
;; mu4e-main ;; mu4e-main

View File

@ -163,7 +163,8 @@ Then, display the results."
;; it have linked headers buffer? ;; it have linked headers buffer?
((mu4e-current-buffer-type-p 'view) ((mu4e-current-buffer-type-p 'view)
(when (mu4e--view-detached-p (current-buffer)) (when (mu4e--view-detached-p (current-buffer))
(mu4e-error "You cannot navigate in a detached view buffer.")) (mu4e-error
"Cannot navigate in a detached view buffer."))
(mu4e-get-headers-buffer)) (mu4e-get-headers-buffer))
;; fallback; but what would trigger this? ;; fallback; but what would trigger this?
(t (mu4e-get-headers-buffer)))) (t (mu4e-get-headers-buffer))))
@ -645,7 +646,8 @@ As a side-effect, a message that is being viewed loses its
;; ;;
;; Otherwise, `mu4e-display-buffer' may adjust the view buffer's ;; Otherwise, `mu4e-display-buffer' may adjust the view buffer's
;; window height based on a buffer that has no text in it yet! ;; window height based on a buffer that has no text in it yet!
(setq-local mu4e~headers-view-win (mu4e-display-buffer gnus-article-buffer nil)) (setq-local mu4e~headers-view-win
(mu4e-display-buffer gnus-article-buffer nil))
(unless (window-live-p mu4e~headers-view-win) (unless (window-live-p mu4e~headers-view-win)
(mu4e-error "Cannot get a message view")) (mu4e-error "Cannot get a message view"))
(select-window mu4e~headers-view-win))) (select-window mu4e~headers-view-win)))
@ -887,9 +889,7 @@ This is useful for advising some Gnus-functionality that does not work in mu4e."
;; toggle header settings ;; toggle header settings
(define-key map "O" #'mu4e-headers-change-sorting) (define-key map "O" #'mu4e-headers-change-sorting)
(define-key map "P" #'mu4e-headers-toggle-threading) (define-key map "P" #'mu4e-headers-toggle-property)
(define-key map "Q" #'mu4e-headers-toggle-full-search)
(define-key map "W" #'mu4e-headers-toggle-include-related)
;; change the number of headers ;; change the number of headers
(define-key map (kbd "C-+") #'mu4e-headers-split-view-grow) (define-key map (kbd "C-+") #'mu4e-headers-split-view-grow)

View File

@ -950,10 +950,7 @@ M-left,\ previous query
M-right next query M-right next query
O change sort order O change sort order
P toggle threading P toggle search property
Q toggle full-search
V toggle skip-duplicates
W toggle include-related
marking marking
------- -------
@ -1037,14 +1034,14 @@ The header field used for sorting is indicated by ``@t{V}'' or
variable @code{mu4e-use-fancy-chars}}, indicating the sort order variable @code{mu4e-use-fancy-chars}}, indicating the sort order
(descending or ascending, respectively). (descending or ascending, respectively).
You can change the sort order by clicking the corresponding column with You can change the sort order by clicking the corresponding column with the
the mouse, or with @kbd{M-x mu4e-headers-change-sorting} (@key{O}); note mouse, or with @kbd{M-x mu4e-headers-change-sorting} (@key{O}); note that not
that not all fields can be used for sorting. You can toggle threading all fields can be used for sorting. You can toggle threading on/off through
on/off using @kbd{M-x mu4e-headers-toggle-threading} or @key{P}. For @kbd{M-x mu4e-headers-toggle-property} or @key{Pt}. For both of these functions,
both of these functions, unless you provide a prefix argument unless you provide a prefix argument (@key{C-u}), the current search is updated
(@key{C-u}), the current search is updated immediately using the new immediately using the new parameters. You can toggle full-search
parameters. You can toggle full-search (@ref{Searching}) using @kbd{M-x (@ref{Searching}) through @kbd{M-x mu4e-headers-toggle-property} as well; or
mu4e-headers-toggle-full-search} or @key{Q}. @key{Pf}.
Note that with threading enabled, the sorting is exclusively by date, Note that with threading enabled, the sorting is exclusively by date,
regardless of the column clicked. regardless of the column clicked.
@ -1274,6 +1271,9 @@ b search bookmark
B edit bookmark before search B edit bookmark before search
j jump to maildir j jump to maildir
O change sort order
P toggle search property
M-left previous query M-left previous query
M-right next query M-right next query
@ -1728,12 +1728,11 @@ order for this to work properly you need to pass your address to
executing a query for messages that happen to have the property of being in a executing a query for messages that happen to have the property of being in a
certain folder (maildir). certain folder (maildir).
Normally, queries return up to @code{mu4e-headers-results-limit} (default: Normally, queries return up to @code{mu4e-headers-results-limit} (default: 500)
500) results. That is usually more than enough, and makes things significantly results. That is usually more than enough, and makes things significantly
faster. Sometimes, however, you may want to show @emph{all} results; you can faster. Sometimes, however, you may want to show @emph{all} results; you can
enable this with @kbd{M-x mu4e-headers-toggle-full-search}, or by customizing enable this with @kbd{M-x mu4e-headers-toggle-property}, or by customizing the
the variable @code{mu4e-headers-full-search}. This applies to all search variable @code{mu4e-headers-full-search}. This applies to all search commands.
commands.
You can also influence the sort order and whether threads are shown or not; You can also influence the sort order and whether threads are shown or not;
see @ref{Sorting and threading}. see @ref{Sorting and threading}.
@ -3798,10 +3797,12 @@ completion.
Set @code{mu4e-cache-maildir-list} to @code{t} (make sure to read Set @code{mu4e-cache-maildir-list} to @code{t} (make sure to read
its docstring). its docstring).
@subsection How can I hide messages from the search results? @subsection How can I hide certain messages from the search results?
See the variable @code{mu4e-headers-hide-predicate}. See the variables @code{mu4e-headers-hide-predicate} and
@code{mu4e-headers-hide-enabled}. The latter can be toggled through
@code{mu4e-headers-toggle-property}.
For example, to filter out GMail's spam, set it to: For example, to filter out GMail's spam folder, set it to:
@lisp @lisp
(setq mu4e-headers-hide-predicate (setq mu4e-headers-hide-predicate
(lambda (msg) (lambda (msg)