mu4e-view/headers: remove m-v-in-headers-context

Remove mu4e--view-in-headers context and the functions that use it;
instead ensure that the functions (in mu4e-headers) handle any context
switching if needed.

This allows for removing a lot of mu4e-view-... wrappers for
mu4e-headers functions. function aliases are provided for backward
compat.
This commit is contained in:
Dirk-Jan C. Binnema
2026-03-15 12:11:54 +02:00
committed by Seth Ladygo
parent befac48916
commit a0fae8f531
3 changed files with 202 additions and 297 deletions

View File

@ -893,6 +893,38 @@ COUNT is the number of messages found."
;; run-hooks
(run-hooks 'mu4e-headers-found-hook))
(defmacro mu4e--in-headers-context (&rest body)
"Evaluate BODY in the context of the headers buffer/window.
If we're already in the headers buffer/window, do nothing.
If we're in the message view, temporarily switch."
`(progn
(let* ((msg (mu4e-message-at-point))
(buffer (mu4e-get-headers-buffer))
(docid (mu4e-message-field msg :docid)))
(unless (and buffer msg docid)
(mu4e-error "Action is not possible"))
;; make sure to select the window if possible, or jumping won't be
;; reflected.
(with-selected-window (get-buffer-window buffer)
(with-current-buffer buffer
(mu4e-thread-unfold-all)
(if (or (mu4e~headers-goto-docid docid)
;; TODO: Is this the best way to find another
;; relevant docid for a view buffer?
;;
;; If you attach a view buffer to another headers
;; buffer that does not contain the current docid
;; then `mu4e~headers-goto-docid' returns nil and we
;; get an error. This "hack" instead gets its
;; now-changed headers buffer's current message as a
;; docid
(mu4e~headers-goto-docid
(with-current-buffer buffer
(mu4e-message-field (mu4e-message-at-point) :docid))))
(progn ,@body)
(mu4e-error "Cannot find message in headers buffer")))))))
;;; Marking
(defmacro mu4e~headers-defun-mark-for (mark)
@ -1331,38 +1363,40 @@ That is, some markpair (move, delete etc.), a field to match and
a regular expression to match with. Then, mark all matching
messages with that mark."
(interactive)
(let ((markpair (mu4e--mark-get-markpair "Mark matched messages with: " t))
(field (mu4e-read-option "Field to match: "
'( ("subject" . :subject)
("from" . :from)
("to" . :to)
("cc" . :cc)
("bcc" . :bcc)
("list" . :list))))
(pattern (read-string
(mu4e-format "Regexp:")
nil 'mu4e~headers-regexp-hist)))
(mu4e-headers-mark-for-each-if
markpair
(lambda (msg _param)
(let* ((value (mu4e-msg-field msg field)))
(if (member field '(:to :from :cc :bcc :reply-to))
(cl-find-if (lambda (contact)
(let ((name (mu4e-contact-name contact))
(email (mu4e-contact-email contact)))
(or (and name (string-match pattern name))
(and email (string-match pattern email)))))
value)
(string-match pattern (or value ""))))))))
(mu4e--in-headers-context
(let ((markpair (mu4e--mark-get-markpair "Mark matched messages with: " t))
(field (mu4e-read-option "Field to match: "
'( ("subject" . :subject)
("from" . :from)
("to" . :to)
("cc" . :cc)
("bcc" . :bcc)
("list" . :list))))
(pattern (read-string
(mu4e-format "Regexp:")
nil 'mu4e~headers-regexp-hist)))
(mu4e-headers-mark-for-each-if
markpair
(lambda (msg _param)
(let* ((value (mu4e-msg-field msg field)))
(if (member field '(:to :from :cc :bcc :reply-to))
(cl-find-if (lambda (contact)
(let ((name (mu4e-contact-name contact))
(email (mu4e-contact-email contact)))
(or (and name (string-match pattern name))
(and email (string-match pattern email)))))
value)
(string-match pattern (or value "")))))))))
(defun mu4e-headers-mark-custom ()
"Mark messages based on a user-provided predicate function."
(interactive)
(let* ((pred (mu4e-read-option "Match function: "
mu4e-headers-custom-markers))
(param (when (cdr pred) (eval (cdr pred))))
(markpair (mu4e--mark-get-markpair "Mark matched messages with: " t)))
(mu4e-headers-mark-for-each-if markpair (car pred) param)))
(mu4e--in-headers-context
(let* ((pred (mu4e-read-option "Match function: "
mu4e-headers-custom-markers))
(param (when (cdr pred) (eval (cdr pred))))
(markpair (mu4e--mark-get-markpair "Mark matched messages with: " t)))
(mu4e-headers-mark-for-each-if markpair (car pred) param))))
(defun mu4e~headers-get-thread-info (msg what)
"Get WHAT (a symbol, either path or thread-id) for MSG."
@ -1426,14 +1460,16 @@ If SUBTHREAD is non-nil, only apply to subthread."
(mu4e--mark-get-markpair
(if subthread "Mark subthread with: " "Mark whole thread with: ")
t))))
(mu4e-headers-mark-thread-using-markpair markpair subthread))
(mu4e--in-headers-context
(mu4e-headers-mark-thread-using-markpair markpair subthread)))
(defun mu4e-headers-mark-subthread (&optional markpair)
"Like `mu4e-mark-thread' with MARKPAIR, but only for a sub-thread."
(interactive)
(if markpair (mu4e-headers-mark-thread t markpair)
(let ((current-prefix-arg t))
(call-interactively 'mu4e-headers-mark-thread))))
(mu4e--in-headers-context
(if markpair (mu4e-headers-mark-thread t markpair)
(let ((current-prefix-arg t))
(call-interactively 'mu4e-headers-mark-thread)))))
(defun mu4e-headers-view-message ()
"View message at point."
@ -1470,37 +1506,38 @@ return nil.
If pointing at a message after the move and there is a
view-window, open the message unless
`mu4e-headers-open-after-move' is non-nil."
(cl-assert (eq major-mode 'mu4e-headers-mode))
(when (ignore-errors
(let (line-move-visual)
(line-move lines)
t))
(let* ((docid (mu4e~headers-docid-at-point))
(folded (and docid (mu4e-thread-message-folded-p))))
(if folded
(mu4e~headers-move (if (< lines 0) -1 1)) ;; skip folded
(when docid
;; Skip invisible text at BOL possibly hidden by
;; the end of another invisible overlay covering
;; previous EOL.
(move-to-column 2)
;; update all windows showing the headers buffer
(walk-windows
(lambda (win)
(when (eq (window-buffer win)
(mu4e-get-headers-buffer (buffer-name)))
(set-window-point win (point))))
nil t)
;; If the assigned (and buffer-local) `mu4e~headers-view-win'
;; is not live then that is indicates the user does not want
;; to pop up the view when they navigate in the headers
;; buffer.
(when (and mu4e-headers-open-after-move
(window-live-p mu4e~headers-view-win))
(mu4e-headers-view-message))
;; attempt to highlight the new line, display the message
(mu4e~headers-highlight docid)
docid)))))
(mu4e--in-headers-context
(cl-assert (eq major-mode 'mu4e-headers-mode))
(when (ignore-errors
(let (line-move-visual)
(line-move lines)
t))
(let* ((docid (mu4e~headers-docid-at-point))
(folded (and docid (mu4e-thread-message-folded-p))))
(if folded
(mu4e~headers-move (if (< lines 0) -1 1)) ;; skip folded
(when docid
;; Skip invisible text at BOL possibly hidden by
;; the end of another invisible overlay covering
;; previous EOL.
(move-to-column 2)
;; update all windows showing the headers buffer
(walk-windows
(lambda (win)
(when (eq (window-buffer win)
(mu4e-get-headers-buffer (buffer-name)))
(set-window-point win (point))))
nil t)
;; If the assigned (and buffer-local) `mu4e~headers-view-win'
;; is not live then that is indicates the user does not want
;; to pop up the view when they navigate in the headers
;; buffer.
(when (and mu4e-headers-open-after-move
(window-live-p mu4e~headers-view-win))
(mu4e-headers-view-message))
;; attempt to highlight the new line, display the message
(mu4e~headers-highlight docid)
docid))))))
(defun mu4e-headers-next (&optional n)
"Move point to the next message header.
@ -1530,13 +1567,14 @@ view-window, open the message unless
"Move point to next message that is unread/untrashed.
If BACKWARDS is non-nil, move backwards."
(interactive "P")
(or (mu4e-headers-find-if-next
(lambda (msg)
(let ((flags (mu4e-message-field msg :flags)))
(and (member 'unread flags) (not (member 'trashed flags)))))
backwards)
(mu4e-message (format "No %s unread message found"
(if backwards "previous" "next")))))
(mu4e--in-headers-context
(or (mu4e-headers-find-if-next
(lambda (msg)
(let ((flags (mu4e-message-field msg :flags)))
(and (member 'unread flags) (not (member 'trashed flags)))))
backwards)
(mu4e-message (format "No %s unread message found"
(if backwards "previous" "next"))))))
(defun mu4e-headers-prev-unread ()
"Move point to previous unread/untrashed message."
@ -1558,11 +1596,27 @@ If MSG is nil, use message at point."
(root (plist-get meta :root)))
(or root (and orphan first-child)))))
(defun mu4e-headers-thread-goto-root ()
"Move to thread root."
(interactive)
(mu4e--in-headers-context (mu4e-thread-goto-root)))
(defun mu4e-headers-thread-fold-toggle-goto-next ()
"Toggle threading or go to next."
(interactive)
(mu4e--in-headers-context (mu4e-thread-fold-toggle-goto-next)))
(defun mu4e-headers-thread-fold-toggle-all ()
"Toggle all threads."
(interactive)
(mu4e--in-headers-context (mu4e-thread-fold-toggle-all)))
(defun mu4e~headers-prev-or-next-thread (backwards)
"Move point to the top of the next thread.
If BACKWARDS is non-nil, move backwards."
(when (mu4e-headers-find-if-next #'mu4e~headers-thread-root-p backwards)
(point)))
(point)))
(defun mu4e-headers-prev-thread ()
"Move point to the previous thread."
@ -1616,10 +1670,11 @@ argument."
"Set MARK on the message at point or in region.
Then, move to the next message."
(interactive)
(when (mu4e-thread-message-folded-p)
(mu4e-warn "Cannot mark folded messages"))
(mu4e-mark-set mark)
(when mu4e-headers-advance-after-mark (mu4e-headers-next)))
(mu4e--in-headers-context
(when (mu4e-thread-message-folded-p)
(mu4e-warn "Cannot mark folded messages"))
(mu4e-mark-set mark)
(when mu4e-headers-advance-after-mark (mu4e-headers-next))))
(defun mu4e~headers-quit-buffer ()
"Quit the mu4e-headers buffer and go back to the main view."

View File

@ -76,6 +76,44 @@
(make-obsolete-variable 'mu4e-view-prefer-html "No longer in use" "1.7.0")
(make-obsolete-variable 'mu4e-view-html-plaintext-ratio-heuristic
"No longer in use" "1.7.0")
(define-obsolete-function-alias 'mu4e-view-headers-next 'mu4e-headers-next "1.14.0")
(define-obsolete-function-alias 'mu4e-view-headers-prev 'mu4e-headers-prev "1.14.0")
(define-obsolete-function-alias 'mu4e-view-mark-pattern 'mu4e-headers-mark-pattern "1.14.0")
(define-obsolete-function-alias 'mu4e-view-unmark 'mu4e-mark-unmark-all "1.14.0")
(define-obsolete-function-alias 'mu4e-view-unmark-all 'mu4e-mark-unmark-all "1.14.0")
(define-obsolete-function-alias 'mu4e-view-search-narrow 'mu4e-search-narrow "1.14.0")
(define-obsolete-function-alias 'mu4e-view-search-edit 'mu4e-search-edit "1.14.0")
(define-obsolete-function-alias 'mu4e-view-search-edit 'mu4e-search-edit "1.14.0")
(define-obsolete-function-alias 'mu4e-view-mark-for-move 'mu4e-headers-mark-for-move "1.14.0")
(define-obsolete-function-alias 'mu4e-view-mark-for-refile 'mu4e-headers-mark-for-refile "1.14.0")
(define-obsolete-function-alias 'mu4e-view-mark-for-delete 'mu4e-headers-mark-for-delete "1.14.0")
(define-obsolete-function-alias 'mu4e-view-mark-for-flag 'mu4e-headers-mark-for-flag "1.14.0")
(define-obsolete-function-alias 'mu4e-view-mark-for-unflag 'mu4e-headers-mark-for-unflag "1.14.0")
(define-obsolete-function-alias 'mu4e-view-mark-for-unmark 'mu4e-headers-mark-for-unmark "1.14.0")
(define-obsolete-function-alias 'mu4e-view-mark-for-something 'mu4e-headers-mark-for-something "1.14.0")
(define-obsolete-function-alias 'mu4e-view-mark-for-read 'mu4e-headers-mark-for-read "1.14.0")
(define-obsolete-function-alias 'mu4e-view-mark-for-unread 'mu4e-headers-mark-for-unread "1.14.0")
(define-obsolete-function-alias 'mu4e-view-mark-for-trash 'mu4e-headers-mark-for-trash "1.14.0")
(define-obsolete-function-alias 'mu4e-view-mark-for-untrash 'mu4e-headers-mark-for-untrash "1.14.0")
(define-obsolete-function-alias 'mu4e-view-mark-for-label 'mu4e-headers-mark-for-label "1.14.0")
(define-obsolete-function-alias 'mu4e-view-mark-for-unlabel 'mu4e-headers-mark-for-unlabel "1.14.0")
(define-obsolete-function-alias 'mu4e-view-mark-custom 'mu4e-headers-mark-custom "1.14.0")
(define-obsolete-function-alias 'mu4e-view-unmark 'mu4e-headers-mark-for-unmark "1.14.0")
(define-obsolete-function-alias 'mu4e-view-marked-execute 'mu4e-mark-execute-all "1.14.0")
(define-obsolete-function-alias 'mu4e-view-mark-thread 'mu4e-headers-mark-thread "1.14.0")
(define-obsolete-function-alias 'mu4e-view-mark-subthread 'mu4e-headers-mark-subthread "1.14.0")
(define-obsolete-function-alias 'mu4e-view-thread-goto-root 'mu4e-headers-thread-goto-root "1.14.0")
(define-obsolete-function-alias 'mu4e-view-thread-fold-toggle-goto-next
'mu4e-headers-thread-fold-toggle-goto-next "1.14.0")
(define-obsolete-function-alias 'mu4e-view-thread-fold-toggle-goto-prev
'mu4e-headers-thread-fold-toggle-goto-prev "1.14.0")
(make-obsolete-variable 'mu4e-message-body-rewrite-functions
"No longer in use" "1.7.0")
;;; Html2Text

View File

@ -1,6 +1,6 @@
;;; mu4e-view.el --- Mode for viewing e-mail messages -*- lexical-binding: t -*-
;; Copyright (C) 2021-2025 Dirk-Jan C. Binnema
;; Copyright (C) 2021-2026 Dirk-Jan C. Binnema
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
@ -120,71 +120,11 @@ Then, display the results."
(let ((path (mu4e-message-readable-path)))
(mu4e-process-file-through-pipe path cmd)))
(defmacro mu4e--view-in-headers-context (&rest body)
"Evaluate BODY in the context of the headers buffer."
`(progn
(let* ((msg (mu4e-message-at-point))
(buffer (cond
;; are we already inside a headers buffer?
((mu4e-current-buffer-type-p 'headers) (current-buffer))
;; if not, are we inside a view buffer, and does
;; it have linked headers buffer?
((mu4e-current-buffer-type-p 'view)
(when (mu4e--view-detached-p (current-buffer))
(mu4e-error
"Cannot navigate in a detached view buffer"))
(mu4e-get-headers-buffer))
;; fallback; but what would trigger this?
(t (mu4e-get-headers-buffer))))
(docid (mu4e-message-field msg :docid)))
(unless docid
(mu4e-error "Message without docid: action is not possible"))
;; make sure to select the window if possible, or jumping won't be
;; reflected.
(with-selected-window (or (get-buffer-window buffer)
(get-buffer-window))
(with-current-buffer buffer
(mu4e-thread-unfold-all)
(if (or (mu4e~headers-goto-docid docid)
;; TODO: Is this the best way to find another
;; relevant docid for a view buffer?
;;
;; If you attach a view buffer to another headers
;; buffer that does not contain the current docid
;; then `mu4e~headers-goto-docid' returns nil and we
;; get an error. This "hack" instead gets its
;; now-changed headers buffer's current message as a
;; docid
(mu4e~headers-goto-docid
(with-current-buffer buffer
(mu4e-message-field (mu4e-message-at-point) :docid))))
,@body
(mu4e-error "Cannot find message in headers buffer")))))))
(defun mu4e-view-headers-next (&optional n)
"Move point to the next message header.
If this succeeds, return the new docid. Otherwise, return nil.
Optionally, takes an integer N (prefix argument), to the Nth next
header."
(interactive "P")
(mu4e--view-in-headers-context
(mu4e~headers-move (or n 1))))
(defun mu4e-view-headers-prev (&optional n)
"Move point to the previous message header.
If this succeeds, return the new docid. Otherwise, return nil.
Optionally, takes an integer N (prefix argument), to the Nth
previous header."
(interactive "P")
(mu4e--view-in-headers-context
(mu4e~headers-move (- (or n 1)))))
(defun mu4e--view-prev-or-next (func backwards)
"Move point to the next or previous message and invoke FUNC.
Go to the previous message if BACKWARDS is non-nil. If this
succeeds, return the new docid. Otherwise, return nil."
(mu4e--view-in-headers-context (funcall func backwards))
(funcall func backwards)
(mu4e-select-other-view)
(mu4e-headers-view-message))
@ -212,21 +152,6 @@ If this succeeds, return the new docid. Otherwise, return nil."
(interactive)
(mu4e--view-prev-or-next #'mu4e~headers-prev-or-next-thread nil))
(defun mu4e-view-thread-goto-root ()
"Move to thread root."
(interactive)
(mu4e--view-in-headers-context (mu4e-thread-goto-root)))
(defun mu4e-view-thread-fold-toggle-goto-next ()
"Toggle threading or go to next."
(interactive)
(mu4e--view-in-headers-context (mu4e-thread-fold-toggle-goto-next)))
(defun mu4e-view-thread-fold-toggle-all ()
"Toggle all threads."
(interactive)
(mu4e--view-in-headers-context (mu4e-thread-fold-toggle-all)))
;;; Interactive functions
(defun mu4e-view-action (&optional msg)
"Ask user for some action to apply on MSG, then do it.
@ -239,46 +164,6 @@ If MSG is nil apply action to message returned by
(actionfunc (mu4e-read-option "Action: " mu4e-view-actions)))
(funcall actionfunc msg)))
(defun mu4e-view-mark-pattern ()
"Mark messages that match a certain pattern.
Ask user for a kind of mark, (move, delete etc.), a field to
match and a regular expression to match with. Then, mark all
matching messages with that mark."
(interactive)
(mu4e--view-in-headers-context (mu4e-headers-mark-pattern)))
(defun mu4e-view-mark-thread (&optional markpair)
"Mark whole thread with a certain mark.
Ask user for a kind of mark (move, delete etc.), and apply it
to all messages in the thread at point in the headers view. The
optional MARKPAIR can also be used to provide the mark
selection."
(interactive)
(mu4e--view-in-headers-context
(if markpair (mu4e-headers-mark-thread nil markpair)
(call-interactively 'mu4e-headers-mark-thread))))
(defun mu4e-view-mark-subthread (&optional markpair)
"Mark subthread with a certain mark.
Ask user for a kind of mark (move, delete etc.), and apply it
to all messages in the subthread at point in the headers view.
The optional MARKPAIR can also be used to provide the mark
selection."
(interactive)
(mu4e--view-in-headers-context
(if markpair (mu4e-headers-mark-subthread markpair)
(mu4e-headers-mark-subthread))))
(defun mu4e-view-search-narrow ()
"Run `mu4e-headers-search-narrow' in the headers buffer."
(interactive)
(mu4e--view-in-headers-context (mu4e-search-narrow)))
(defun mu4e-view-search-edit ()
"Run `mu4e-search-edit' in the headers buffer."
(interactive)
(mu4e--view-in-headers-context (mu4e-search-edit)))
(defun mu4e-mark-region-code ()
"Highlight region marked with `message-mark-inserted-region'.
Add this function to `mu4e-view-mode-hook' to enable this feature."
@ -308,17 +193,10 @@ Add this function to `mu4e-view-mode-hook' to enable this feature."
(setq beg nil end nil))))))
;;; View Utilities
(defun mu4e-view-mark-custom ()
"Run some custom mark function."
(mu4e--view-in-headers-context
(mu4e-headers-mark-custom)))
(defun mu4e--view-split-view-p ()
"Return t if we're in split-view, nil otherwise."
(member mu4e-split-view '(horizontal vertical)))
(defun mu4e-view-detach ()
"Detach the view buffer from its headers buffer."
(interactive)
@ -369,64 +247,6 @@ any further, go the next message."
(interactive)
(scroll-down 1))
;;; Mark commands
(defun mu4e-view-unmark-all ()
"If we're in split-view, unmark all messages.
Otherwise, warn user that unmarking only works in the header
list."
(interactive)
(if (mu4e--view-split-view-p)
(mu4e--view-in-headers-context (mu4e-mark-unmark-all))
(mu4e-message "Unmarking needs to be done in the header list view")))
(defun mu4e-view-unmark ()
"If we're in split-view, unmark message at point.
Otherwise, warn user that unmarking only works in the header
list."
(interactive)
(if (mu4e--view-split-view-p)
(mu4e-view-mark-for-unmark)
(mu4e-message "Unmarking needs to be done in the header list view")))
(defun mu4e-view-mark-and-next (mark)
"Set MARK on the current message.
Then, move to the next message."
(interactive)
(mu4e--view-in-headers-context
(mu4e-headers-mark-and-next mark)))
(defmacro mu4e--view-defun-mark-for (mark)
"Define a function mu4e-view-mark-for- MARK."
(let ((funcname (intern (format "mu4e-view-mark-for-%s" mark)))
(docstring (format "Mark the current message for %s." mark)))
`(progn
(defun ,funcname () ,docstring
(interactive)
(mu4e--view-in-headers-context
(mu4e-headers-mark-and-next ',mark)))
(put ',funcname 'definition-name ',mark))))
(mu4e--view-defun-mark-for move)
(mu4e--view-defun-mark-for refile)
(mu4e--view-defun-mark-for delete)
(mu4e--view-defun-mark-for flag)
(mu4e--view-defun-mark-for unflag)
(mu4e--view-defun-mark-for unmark)
(mu4e--view-defun-mark-for something)
(mu4e--view-defun-mark-for read)
(mu4e--view-defun-mark-for unread)
(mu4e--view-defun-mark-for trash)
(mu4e--view-defun-mark-for untrash)
(mu4e--view-defun-mark-for label)
(mu4e--view-defun-mark-for unlabel)
(defun mu4e-view-marked-execute ()
"Execute the marked actions."
(interactive)
(mu4e--view-in-headers-context
(mu4e-mark-execute-all)))
;;; URL handling
(defvar mu4e--view-link-map nil
@ -958,9 +778,9 @@ This is useful for advising some Gnus-functionality that does not work in mu4e."
(define-key map "z" #'mu4e-view-detach)
(define-key map "Z" #'mu4e-view-attach)
(define-key map "%" #'mu4e-view-mark-pattern)
(define-key map "t" #'mu4e-view-mark-subthread)
(define-key map "T" #'mu4e-view-mark-thread)
(define-key map "%" #'mu4e-headers-mark-pattern)
(define-key map "t" #'mu4e-headers-mark-subthread)
(define-key map "T" #'mu4e-headers-mark-thread)
(define-key map "g" #'mu4e-view-go-to-url)
(define-key map "k" #'mu4e-view-save-url)
@ -987,51 +807,43 @@ This is useful for advising some Gnus-functionality that does not work in mu4e."
(define-key map (kbd "<backspace>") #'mu4e-scroll-down)
;; navigation between messages
(define-key map "p" #'mu4e-view-headers-prev)
(define-key map "n" #'mu4e-view-headers-next)
(define-key map "p" #'mu4e-headers-prev)
(define-key map "n" #'mu4e-headers-next)
;; the same
(define-key map (kbd "<M-down>") #'mu4e-view-headers-next)
(define-key map (kbd "<M-up>") #'mu4e-view-headers-prev)
(define-key map (kbd "<M-down>") #'mu4e-headers-next)
(define-key map (kbd "<M-up>") #'mu4e-headers-prev)
(define-key map (kbd "[") #'mu4e-view-headers-prev-unread)
(define-key map (kbd "]") #'mu4e-view-headers-next-unread)
(define-key map (kbd "{") #'mu4e-view-headers-prev-thread)
(define-key map (kbd "}") #'mu4e-view-headers-next-thread)
;; ;; threads
;; TODO: find some binding that don't conflict
;; (define-key map (kbd "<S-left>") #'mu4e-view-thread-goto-root)
;; ;; <tab> is taken already
;; (define-key map (kbd "<C-S-tab>") #'mu4e-view-thread-fold-toggle-goto-next)
;; (define-key map (kbd "<backtab>") #'mu4e-view-thread-fold-toggle-all)
;; switching from view <-> headers (when visible)
(define-key map "y" #'mu4e-select-other-view)
;; marking/unmarking
(define-key map "d" #'mu4e-view-mark-for-trash)
(define-key map (kbd "<delete>") #'mu4e-view-mark-for-delete)
(define-key map (kbd "<deletechar>") #'mu4e-view-mark-for-delete)
(define-key map (kbd "D") #'mu4e-view-mark-for-delete)
(define-key map (kbd "m") #'mu4e-view-mark-for-move)
(define-key map (kbd "r") #'mu4e-view-mark-for-refile)
(define-key map "d" #'mu4e-headers-mark-for-trash)
(define-key map (kbd "<delete>") #'mu4e-headers-mark-for-delete)
(define-key map (kbd "<deletechar>") #'mu4e-headers-mark-for-delete)
(define-key map (kbd "D") #'mu4e-headers-mark-for-delete)
(define-key map (kbd "m") #'mu4e-headers-mark-for-move)
(define-key map (kbd "r") #'mu4e-headers-mark-for-refile)
(define-key map (kbd "?") #'mu4e-view-mark-for-unread)
(define-key map (kbd "!") #'mu4e-view-mark-for-read)
(define-key map (kbd "?") #'mu4e-headers-mark-for-unread)
(define-key map (kbd "!") #'mu4e-headers-mark-for-read)
(define-key map (kbd "+") #'mu4e-view-mark-for-flag)
(define-key map (kbd "-") #'mu4e-view-mark-for-unflag)
(define-key map (kbd "=") #'mu4e-view-mark-for-untrash)
(define-key map (kbd "&") #'mu4e-view-mark-custom)
(define-key map (kbd "+") #'mu4e-headers-mark-for-flag)
(define-key map (kbd "-") #'mu4e-headers-mark-for-unflag)
(define-key map (kbd "=") #'mu4e-headers-mark-for-untrash)
(define-key map (kbd "&") #'mu4e-headers-mark-custom)
(define-key map (kbd "l") #'mu4e-view-mark-for-label)
(define-key map (kbd "L") #'mu4e-view-mark-for-unlabel)
(define-key map (kbd "l") #'mu4e-headers-mark-for-label)
(define-key map (kbd "L") #'mu4e-headers-mark-for-unlabel)
(define-key map (kbd "*") #'mu4e-view-mark-for-something)
(define-key map (kbd "<kp-multiply>") #'mu4e-view-mark-for-something)
(define-key map (kbd "<insert>") #'mu4e-view-mark-for-something)
(define-key map (kbd "<insertchar>") #'mu4e-view-mark-for-something)
(define-key map (kbd "*") #'mu4e-headers-mark-for-something)
(define-key map (kbd "<kp-multiply>") #'mu4e-headers-mark-for-something)
(define-key map (kbd "<insert>") #'mu4e-headers-mark-for-something)
(define-key map (kbd "<insertchar>") #'mu4e-headers-mark-for-something)
(define-key map ";" #'mu4e-context-switch)
@ -1046,9 +858,9 @@ This is useful for advising some Gnus-functionality that does not work in mu4e."
(define-key map "c" #'mu4e-copy-thing-at-point)
;; next 3 only warn user when attempt in the message view
(define-key map "u" #'mu4e-view-unmark)
(define-key map "U" #'mu4e-view-unmark-all)
(define-key map "x" #'mu4e-view-marked-execute)
(define-key map "u" #'mu4e-headers-mark-for-unmark)
(define-key map "U" #'mu4e-mark-unmark-all)
(define-key map "x" #'mu4e-mark-execute-all)
(define-key map "$" #'mu4e-show-log)
(define-key map "H" #'mu4e-display-manual)
@ -1074,10 +886,10 @@ This is useful for advising some Gnus-functionality that does not work in mu4e."
["View raw" mu4e-view-raw-message]
["Pipe through shell" mu4e-view-pipe]
"--"
["Mark for deletion" mu4e-view-mark-for-delete]
["Mark for untrash" mu4e-view-mark-for-untrash]
["Mark for trash" mu4e-view-mark-for-trash]
["Mark for move" mu4e-view-mark-for-move]
["Mark for deletion" mu4e-headers-mark-for-delete]
["Mark for untrash" mu4e-headers-mark-for-untrash]
["Mark for trash" mu4e-headers-mark-for-trash]
["Mark for move" mu4e-headers-mark-for-move]
)
mu4e--compose-menu-items
mu4e--search-menu-items