Merge branch 'wip/djcb/toggle-property'
This commit is contained in:
19
.dir-locals.el
Normal file
19
.dir-locals.el
Normal 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))))
|
||||||
20
NEWS.org
20
NEWS.org
@ -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.
|
||||||
|
|||||||
@ -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.
|
||||||
|
|
||||||
@ -159,9 +165,9 @@ mostly covered by `new', and the display gets cluttered otherwise."
|
|||||||
(const :tag "Attach" attach)
|
(const :tag "Attach" attach)
|
||||||
(const :tag "Encrypted" encrypted)
|
(const :tag "Encrypted" encrypted)
|
||||||
(const :tag "Signed" signed)
|
(const :tag "Signed" signed)
|
||||||
(const :tag "List" list)
|
(const :tag "List" list)
|
||||||
(const :tag "Personal" personal)
|
(const :tag "Personal" personal)
|
||||||
(const :tag "Calendar" calendar))
|
(const :tag "Calendar" calendar))
|
||||||
:group 'mu4e-headers)
|
:group 'mu4e-headers)
|
||||||
|
|
||||||
(defcustom mu4e-headers-found-hook nil
|
(defcustom mu4e-headers-found-hook nil
|
||||||
@ -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,12 +353,13 @@ 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)
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(when text
|
(when text
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
(insert (propertize text 'face 'mu4e-system-face 'intangible t)))))))
|
(insert (propertize text 'face 'mu4e-system-face 'intangible t)))))))
|
||||||
|
|
||||||
@ -359,7 +372,7 @@ into a string."
|
|||||||
(mapconcat
|
(mapconcat
|
||||||
(lambda (contact)
|
(lambda (contact)
|
||||||
(let ((name (mu4e-contact-name contact))
|
(let ((name (mu4e-contact-name contact))
|
||||||
(email (mu4e-contact-email contact)))
|
(email (mu4e-contact-email contact)))
|
||||||
(or name email "?"))) contacts ", "))
|
(or name email "?"))) contacts ", "))
|
||||||
|
|
||||||
(defun mu4e~headers-thread-prefix-map (type)
|
(defun mu4e~headers-thread-prefix-map (type)
|
||||||
@ -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
|
||||||
@ -507,14 +522,14 @@ function is for display. (This difference is significant, since
|
|||||||
internally, the Maildir spec determines what the flags look like,
|
internally, the Maildir spec determines what the flags look like,
|
||||||
while our display may be different)."
|
while our display may be different)."
|
||||||
(or (mapconcat
|
(or (mapconcat
|
||||||
(lambda (flag)
|
(lambda (flag)
|
||||||
(when (member flag mu4e-headers-visible-flags)
|
(when (member flag mu4e-headers-visible-flags)
|
||||||
(if-let* ((mark (intern-soft
|
(if-let* ((mark (intern-soft
|
||||||
(format "mu4e-headers-%s-mark" (symbol-name flag))))
|
(format "mu4e-headers-%s-mark" (symbol-name flag))))
|
||||||
(cell (symbol-value mark)))
|
(cell (symbol-value mark)))
|
||||||
(if mu4e-use-fancy-chars (cdr cell) (car cell))
|
(if mu4e-use-fancy-chars (cdr cell) (car cell))
|
||||||
"")))
|
"")))
|
||||||
flags "")
|
flags "")
|
||||||
""))
|
""))
|
||||||
|
|
||||||
;;; Special headers
|
;;; Special headers
|
||||||
@ -526,8 +541,8 @@ addresses, (as per `mu4e-personal-address-p'), show the To
|
|||||||
address. Otherwise, show the From address, prefixed with the
|
address. Otherwise, show the From address, prefixed with the
|
||||||
appropriate `mu4e-headers-from-or-to-prefix'."
|
appropriate `mu4e-headers-from-or-to-prefix'."
|
||||||
(let* ((from1 (car-safe (mu4e-message-field msg :from)))
|
(let* ((from1 (car-safe (mu4e-message-field msg :from)))
|
||||||
(from1-addr (and from1 (mu4e-contact-email from1)))
|
(from1-addr (and from1 (mu4e-contact-email from1)))
|
||||||
(is-user (and from1-addr (mu4e-personal-address-p from1-addr))))
|
(is-user (and from1-addr (mu4e-personal-address-p from1-addr))))
|
||||||
(if is-user
|
(if is-user
|
||||||
(concat (cdr mu4e-headers-from-or-to-prefix)
|
(concat (cdr mu4e-headers-from-or-to-prefix)
|
||||||
(mu4e~headers-contact-str (mu4e-message-field msg :to)))
|
(mu4e~headers-contact-str (mu4e-message-field msg :to)))
|
||||||
@ -591,8 +606,8 @@ found."
|
|||||||
(truncate-string-to-width val 600)))
|
(truncate-string-to-width val 600)))
|
||||||
(:thread-subject ;; if not searching threads, fall back to :subject
|
(:thread-subject ;; if not searching threads, fall back to :subject
|
||||||
(if mu4e-search-threads
|
(if mu4e-search-threads
|
||||||
(mu4e~headers-thread-subject msg)
|
(mu4e~headers-thread-subject msg)
|
||||||
(mu4e~headers-field-value msg :subject)))
|
(mu4e~headers-field-value msg :subject)))
|
||||||
((:maildir :path :message-id) val)
|
((:maildir :path :message-id) val)
|
||||||
((:to :from :cc :bcc) (mu4e~headers-contact-str val))
|
((:to :from :cc :bcc) (mu4e~headers-contact-str val))
|
||||||
;; if we (ie. `user-mail-address' is the 'From', show
|
;; if we (ie. `user-mail-address' is the 'From', show
|
||||||
@ -650,41 +665,47 @@ 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)
|
||||||
"Adjust FIELDVAL's face property based on flags in MSG."
|
"Adjust FIELDVAL's face property based on flags in MSG."
|
||||||
(let* ((flags (plist-get msg :flags))
|
(let* ((flags (plist-get msg :flags))
|
||||||
(meta (plist-get msg :meta))
|
(meta (plist-get msg :meta))
|
||||||
(face (cond
|
(face (cond
|
||||||
((memq 'trashed flags) 'mu4e-trashed-face)
|
((memq 'trashed flags) 'mu4e-trashed-face)
|
||||||
((memq 'draft flags) 'mu4e-draft-face)
|
((memq 'draft flags) 'mu4e-draft-face)
|
||||||
((or (memq 'unread flags) (memq 'new flags))
|
((or (memq 'unread flags) (memq 'new flags))
|
||||||
'mu4e-unread-face)
|
'mu4e-unread-face)
|
||||||
((memq 'flagged flags) 'mu4e-flagged-face)
|
((memq 'flagged flags) 'mu4e-flagged-face)
|
||||||
((plist-get meta :related) 'mu4e-related-face)
|
((plist-get meta :related) 'mu4e-related-face)
|
||||||
((memq 'replied flags) 'mu4e-replied-face)
|
((memq 'replied flags) 'mu4e-replied-face)
|
||||||
((memq 'passed flags) 'mu4e-forwarded-face)
|
((memq 'passed flags) 'mu4e-forwarded-face)
|
||||||
(t 'mu4e-header-face))))
|
(t 'mu4e-header-face))))
|
||||||
(add-face-text-property 0 (length fieldval) face t fieldval)
|
(add-face-text-property 0 (length fieldval) face t fieldval)
|
||||||
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))
|
||||||
(mu4e~headers-apply-flags
|
(progn
|
||||||
msg
|
(cl-incf mu4e~headers-hidden)
|
||||||
(mapconcat (lambda (f-w) (mu4e~headers-field-handler f-w msg))
|
nil)
|
||||||
mu4e-headers-fields " "))))
|
(progn
|
||||||
|
(mu4e~headers-apply-flags
|
||||||
|
msg
|
||||||
|
(mapconcat (lambda (f-w) (mu4e~headers-field-handler f-w msg))
|
||||||
|
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."
|
||||||
(when-let ((line (mu4e~message-header-line msg))
|
(when-let ((line (mu4e~message-header-line msg))
|
||||||
(docid (plist-get msg :docid)))
|
(docid (plist-get msg :docid)))
|
||||||
(goto-char pos)
|
(goto-char pos)
|
||||||
(insert
|
(insert
|
||||||
(propertize
|
(propertize
|
||||||
@ -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)
|
||||||
@ -725,11 +747,11 @@ Do this at the end of the headers-buffer."
|
|||||||
(when (buffer-live-p (mu4e-get-headers-buffer))
|
(when (buffer-live-p (mu4e-get-headers-buffer))
|
||||||
(with-current-buffer (mu4e-get-headers-buffer)
|
(with-current-buffer (mu4e-get-headers-buffer)
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(let ((inhibit-read-only t))
|
(let ((inhibit-read-only t))
|
||||||
(seq-do
|
(seq-do
|
||||||
(lambda (msg)
|
(lambda (msg)
|
||||||
(mu4e~headers-insert-header msg (point-max)))
|
(mu4e~headers-insert-header msg (point-max)))
|
||||||
msglst))))))
|
msglst))))))
|
||||||
|
|
||||||
|
|
||||||
(defun mu4e~headers-update-handler (msg is-move maybe-view)
|
(defun mu4e~headers-update-handler (msg is-move maybe-view)
|
||||||
@ -741,7 +763,7 @@ headers."
|
|||||||
(let* ((docid (mu4e-message-field msg :docid))
|
(let* ((docid (mu4e-message-field msg :docid))
|
||||||
(initial-message-at-point (mu4e~headers-docid-at-point))
|
(initial-message-at-point (mu4e~headers-docid-at-point))
|
||||||
(initial-column (current-column))
|
(initial-column (current-column))
|
||||||
(inhibit-read-only t)
|
(inhibit-read-only t)
|
||||||
(point (mu4e~headers-docid-pos docid))
|
(point (mu4e~headers-docid-pos docid))
|
||||||
(markinfo (gethash docid mu4e--mark-map)))
|
(markinfo (gethash docid mu4e--mark-map)))
|
||||||
(when point ;; is the message present in this list?
|
(when point ;; is the message present in this list?
|
||||||
@ -772,8 +794,8 @@ headers."
|
|||||||
;; longer matches the query, but this seem a good heuristic. if it
|
;; longer matches the query, but this seem a good heuristic. if it
|
||||||
;; was only a flag-change, show the message with its updated flags.
|
;; was only a flag-change, show the message with its updated flags.
|
||||||
(unless is-move
|
(unless is-move
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(mu4e~headers-insert-header msg point)))
|
(mu4e~headers-insert-header msg point)))
|
||||||
|
|
||||||
;; restore the mark, if any. See #2076.
|
;; restore the mark, if any. See #2076.
|
||||||
(when (and markinfo (mu4e~headers-goto-docid docid))
|
(when (and markinfo (mu4e~headers-goto-docid docid))
|
||||||
@ -848,16 +870,16 @@ true, do *not* update the query history stack."
|
|||||||
(defun mu4e~headers-benchmark-message (count)
|
(defun mu4e~headers-benchmark-message (count)
|
||||||
"Get some report message for messaging search and rendering speed."
|
"Get some report message for messaging search and rendering speed."
|
||||||
(if (and mu4e-headers-report-render-time
|
(if (and mu4e-headers-report-render-time
|
||||||
mu4e~headers-search-start
|
mu4e~headers-search-start
|
||||||
mu4e~headers-render-start
|
mu4e~headers-render-start
|
||||||
(> count 0))
|
(> count 0))
|
||||||
(let ((render-time-ms (* 1000(- (float-time) mu4e~headers-render-start)))
|
(let ((render-time-ms (* 1000(- (float-time) mu4e~headers-render-start)))
|
||||||
(search-time-ms (* 1000(- (float-time) mu4e~headers-search-start))))
|
(search-time-ms (* 1000(- (float-time) mu4e~headers-search-start))))
|
||||||
(format (concat
|
(format (concat
|
||||||
"; search: %0.1f ms (%0.2f ms/msg)"
|
"; search: %0.1f ms (%0.2f ms/msg)"
|
||||||
"; render: %0.1f ms (%0.2f ms/msg)")
|
"; render: %0.1f ms (%0.2f ms/msg)")
|
||||||
search-time-ms (/ search-time-ms count)
|
search-time-ms (/ search-time-ms count)
|
||||||
render-time-ms (/ render-time-ms count)))
|
render-time-ms (/ render-time-ms count)))
|
||||||
""))
|
""))
|
||||||
|
|
||||||
(defun mu4e~headers-found-handler (count)
|
(defun mu4e~headers-found-handler (count)
|
||||||
@ -869,9 +891,10 @@ 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-benchmark-message count))))
|
mu4e~headers-hidden
|
||||||
|
(mu4e~headers-benchmark-message count))))
|
||||||
|
|
||||||
(insert (propertize str 'face 'mu4e-system-face 'intangible t))
|
(insert (propertize str 'face 'mu4e-system-face 'intangible t))
|
||||||
(unless (zerop count)
|
(unless (zerop count)
|
||||||
@ -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
|
||||||
@ -947,7 +964,7 @@ after the end of the search results."
|
|||||||
(define-key map "t" 'mu4e-headers-mark-subthread)
|
(define-key map "t" 'mu4e-headers-mark-subthread)
|
||||||
(define-key map "T" 'mu4e-headers-mark-thread)
|
(define-key map "T" 'mu4e-headers-mark-thread)
|
||||||
|
|
||||||
(define-key map "," #'mu4e-sexp-at-point)
|
(define-key map "," #'mu4e-sexp-at-point)
|
||||||
|
|
||||||
;; navigation between messages
|
;; navigation between messages
|
||||||
(define-key map "p" 'mu4e-headers-prev)
|
(define-key map "p" 'mu4e-headers-prev)
|
||||||
@ -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] '("--"))
|
||||||
|
|
||||||
@ -1104,7 +1114,7 @@ after the end of the search results."
|
|||||||
(field (car item)) (width (cdr item))
|
(field (car item)) (width (cdr item))
|
||||||
(info (cdr (assoc field
|
(info (cdr (assoc field
|
||||||
(append mu4e-header-info mu4e-header-info-custom))))
|
(append mu4e-header-info mu4e-header-info-custom))))
|
||||||
(sortable (plist-get info :sortable))
|
(sortable (plist-get info :sortable))
|
||||||
;; if sortable, it is either t (when field is sortable itself)
|
;; if sortable, it is either t (when field is sortable itself)
|
||||||
;; or a symbol (if another field is used for sorting)
|
;; or a symbol (if another field is used for sorting)
|
||||||
(this-field (when sortable (if (booleanp sortable) field sortable)))
|
(this-field (when sortable (if (booleanp sortable) field sortable)))
|
||||||
@ -1143,8 +1153,8 @@ after the end of the search results."
|
|||||||
some changes, `mu4e-headers-auto-update' is non-nil and there is
|
some changes, `mu4e-headers-auto-update' is non-nil and there is
|
||||||
no user-interaction ongoing."
|
no user-interaction ongoing."
|
||||||
(when (and mu4e-headers-auto-update ;; must be set
|
(when (and mu4e-headers-auto-update ;; must be set
|
||||||
mu4e-index-update-status
|
mu4e-index-update-status
|
||||||
(not (zerop (plist-get mu4e-index-update-status :updated)))
|
(not (zerop (plist-get mu4e-index-update-status :updated)))
|
||||||
;; NOTE: `mu4e-mark-marks-num' can return nil. Is that intended?
|
;; NOTE: `mu4e-mark-marks-num' can return nil. Is that intended?
|
||||||
(zerop (or (mu4e-mark-marks-num) 0)) ;; non active marks
|
(zerop (or (mu4e-mark-marks-num) 0)) ;; non active marks
|
||||||
(not (active-minibuffer-window))) ;; no user input only
|
(not (active-minibuffer-window))) ;; no user input only
|
||||||
@ -1287,21 +1297,24 @@ message plist, or nil if not found."
|
|||||||
(defvar mu4e~headers-mode-line-label "")
|
(defvar mu4e~headers-mode-line-label "")
|
||||||
(defun mu4e~headers-update-mode-line ()
|
(defun mu4e~headers-update-mode-line ()
|
||||||
"Update mode-line settings."
|
"Update mode-line settings."
|
||||||
(let* ((flagstr
|
(let* ((flagstr
|
||||||
(mapconcat
|
(mapconcat
|
||||||
(lambda (flag-cell)
|
(lambda (flag-cell)
|
||||||
(if (car flag-cell)
|
(if (car flag-cell)
|
||||||
(if mu4e-use-fancy-chars
|
(if mu4e-use-fancy-chars
|
||||||
(cddr flag-cell) (cadr flag-cell) ) ""))
|
(cddr flag-cell) (cadr flag-cell) ) ""))
|
||||||
`((,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)
|
||||||
(name "mu4e-headers"))
|
(,mu4e-headers-hide-enabled . ,mu4e-headers-hide-label))
|
||||||
|
""))
|
||||||
|
(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)
|
||||||
|
|
||||||
@ -1405,9 +1418,10 @@ matching messages with that mark."
|
|||||||
(if (member field '(:to :from :cc :bcc :reply-to))
|
(if (member field '(:to :from :cc :bcc :reply-to))
|
||||||
(cl-find-if (lambda (contact)
|
(cl-find-if (lambda (contact)
|
||||||
(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,68 +1541,30 @@ 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)
|
||||||
(toggles (seq-map
|
("pHide-predicate" . mu4e-headers-hide-enabled)))
|
||||||
(lambda (cell)
|
(toggles (seq-map
|
||||||
(cons
|
(lambda (cell)
|
||||||
(concat (car cell) (format" (%s)"
|
(cons
|
||||||
(if (symbol-value (cdr cell)) "on" "off")))
|
(concat (car cell)
|
||||||
(cdr cell))) toggles))
|
(format" (%s)"
|
||||||
(choice (mu4e-read-option "Toggle setting " toggles)))
|
(if (symbol-value (cdr cell)) "on" "off")))
|
||||||
|
(cdr cell))) 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."
|
||||||
@ -1595,9 +1572,9 @@ _not_ refresh the last search with the new setting for threading."
|
|||||||
(unless (eq major-mode 'mu4e-headers-mode)
|
(unless (eq major-mode 'mu4e-headers-mode)
|
||||||
(mu4e-error "Must be in mu4e-headers-mode (%S)" major-mode))
|
(mu4e-error "Must be in mu4e-headers-mode (%S)" major-mode))
|
||||||
(let* ((msg (mu4e-message-at-point))
|
(let* ((msg (mu4e-message-at-point))
|
||||||
(path (mu4e-message-field msg :path))
|
(path (mu4e-message-field msg :path))
|
||||||
(_exists (or (file-readable-p path)
|
(_exists (or (file-readable-p path)
|
||||||
(mu4e-warn "No message at %s" path)))
|
(mu4e-warn "No message at %s" path)))
|
||||||
(docid (or (mu4e-message-field msg :docid)
|
(docid (or (mu4e-message-field msg :docid)
|
||||||
(mu4e-warn "No message at point")))
|
(mu4e-warn "No message at point")))
|
||||||
(mark-as-read
|
(mark-as-read
|
||||||
@ -1622,12 +1599,12 @@ return nil."
|
|||||||
(condition-case _err
|
(condition-case _err
|
||||||
(prog1
|
(prog1
|
||||||
(let (line-move-visual)
|
(let (line-move-visual)
|
||||||
(and (line-move arg) 0))
|
(and (line-move arg) 0))
|
||||||
;; Skip invisible text at BOL possibly hidden by
|
;; Skip invisible text at BOL possibly hidden by
|
||||||
;; the end of another invisible overlay covering
|
;; the end of another invisible overlay covering
|
||||||
;; previous EOL.
|
;; previous EOL.
|
||||||
(move-to-column 2))
|
(move-to-column 2))
|
||||||
((beginning-of-buffer end-of-buffer)
|
((beginning-of-buffer end-of-buffer)
|
||||||
1))))
|
1))))
|
||||||
(let* ((succeeded (zerop (goto-next-line lines)))
|
(let* ((succeeded (zerop (goto-next-line lines)))
|
||||||
(docid (mu4e~headers-docid-at-point)))
|
(docid (mu4e~headers-docid-at-point)))
|
||||||
@ -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'
|
||||||
@ -1649,8 +1627,8 @@ return nil."
|
|||||||
;; attempt to highlight the new line, display the message
|
;; attempt to highlight the new line, display the message
|
||||||
(mu4e~headers-highlight docid)
|
(mu4e~headers-highlight docid)
|
||||||
(if succeeded
|
(if succeeded
|
||||||
docid
|
docid
|
||||||
nil)))))
|
nil)))))
|
||||||
|
|
||||||
(defun mu4e-headers-next (&optional n)
|
(defun mu4e-headers-next (&optional n)
|
||||||
"Move point to the next message header.
|
"Move point to the next message header.
|
||||||
@ -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))
|
||||||
|
|||||||
@ -161,25 +161,27 @@ Does a local-exit and does not return."
|
|||||||
"Get PROP from plist LST and raise an error if not present."
|
"Get PROP from plist LST and raise an error if not present."
|
||||||
(or (plist-get lst prop)
|
(or (plist-get lst prop)
|
||||||
(if (plist-member lst prop)
|
(if (plist-member lst prop)
|
||||||
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))))
|
||||||
@ -369,18 +375,18 @@ http://cr.yp.to/proto/maildir.html."
|
|||||||
(seq-mapcat
|
(seq-mapcat
|
||||||
(lambda (flag)
|
(lambda (flag)
|
||||||
(pcase flag
|
(pcase flag
|
||||||
(`draft "D")
|
(`draft "D")
|
||||||
(`flagged "F")
|
(`flagged "F")
|
||||||
(`new "N")
|
(`new "N")
|
||||||
(`passed "P")
|
(`passed "P")
|
||||||
(`replied "R")
|
(`replied "R")
|
||||||
(`seen "S")
|
(`seen "S")
|
||||||
(`trashed "T")
|
(`trashed "T")
|
||||||
(`attach "a")
|
(`attach "a")
|
||||||
(`encrypted "x")
|
(`encrypted "x")
|
||||||
(`signed "s")
|
(`signed "s")
|
||||||
(`unread "u")
|
(`unread "u")
|
||||||
(_ "")))
|
(_ "")))
|
||||||
(seq-uniq flags) 'string)))
|
(seq-uniq flags) 'string)))
|
||||||
|
|
||||||
(defun mu4e-string-to-flags (str)
|
(defun mu4e-string-to-flags (str)
|
||||||
@ -394,14 +400,14 @@ http://cr.yp.to/proto/maildir.html."
|
|||||||
(seq-mapcat
|
(seq-mapcat
|
||||||
(lambda (kar)
|
(lambda (kar)
|
||||||
(list
|
(list
|
||||||
(pcase kar
|
(pcase kar
|
||||||
('?D 'draft)
|
('?D 'draft)
|
||||||
('?F 'flagged)
|
('?F 'flagged)
|
||||||
('?P 'passed)
|
('?P 'passed)
|
||||||
('?R 'replied)
|
('?R 'replied)
|
||||||
('?S 'seen)
|
('?S 'seen)
|
||||||
('?T 'trashed)
|
('?T 'trashed)
|
||||||
(_ nil))))
|
(_ nil))))
|
||||||
str))))
|
str))))
|
||||||
|
|
||||||
|
|
||||||
@ -470,7 +476,7 @@ The file will self-destruct in a short while, enough to open it
|
|||||||
in an external program."
|
in an external program."
|
||||||
(let ((tmpfile (make-temp-file "mu4e-" nil (concat "." ext))))
|
(let ((tmpfile (make-temp-file "mu4e-" nil (concat "." ext))))
|
||||||
(run-at-time "30 sec" nil
|
(run-at-time "30 sec" nil
|
||||||
(lambda () (ignore-errors (delete-file tmpfile))))
|
(lambda () (ignore-errors (delete-file tmpfile))))
|
||||||
tmpfile))
|
tmpfile))
|
||||||
|
|
||||||
(defsubst mu4e-is-mode-or-derived-p (mode)
|
(defsubst mu4e-is-mode-or-derived-p (mode)
|
||||||
@ -492,12 +498,12 @@ Or go to the top level if there is none."
|
|||||||
(defun mu4e--make-bookmark-record ()
|
(defun mu4e--make-bookmark-record ()
|
||||||
"Create a bookmark for the message at point."
|
"Create a bookmark for the message at point."
|
||||||
(let* ((msg (mu4e-message-at-point))
|
(let* ((msg (mu4e-message-at-point))
|
||||||
(subject (or (plist-get msg :subject) "No subject"))
|
(subject (or (plist-get msg :subject) "No subject"))
|
||||||
(date (plist-get msg :date))
|
(date (plist-get msg :date))
|
||||||
(date (if date (format-time-string "%F: " date) ""))
|
(date (if date (format-time-string "%F: " date) ""))
|
||||||
(title (format "%s%s" date subject))
|
(title (format "%s%s" date subject))
|
||||||
(msgid (or (plist-get msg :message-id)
|
(msgid (or (plist-get msg :message-id)
|
||||||
(mu4e-error "Cannot bookmark message without message-id"))))
|
(mu4e-error "Cannot bookmark message without message-id"))))
|
||||||
`(,title
|
`(,title
|
||||||
,@(bookmark-make-record-default 'no-file 'no-context)
|
,@(bookmark-make-record-default 'no-file 'no-context)
|
||||||
(message-id . ,msgid)
|
(message-id . ,msgid)
|
||||||
|
|||||||
@ -60,9 +60,9 @@
|
|||||||
(make-obsolete-variable 'mu4e-html2text-command "No longer in use" "1.7.0")
|
(make-obsolete-variable 'mu4e-html2text-command "No longer in use" "1.7.0")
|
||||||
(make-obsolete-variable 'mu4e-view-prefer-html "No longer in use" "1.7.0")
|
(make-obsolete-variable 'mu4e-view-prefer-html "No longer in use" "1.7.0")
|
||||||
(make-obsolete-variable 'mu4e-view-html-plaintext-ratio-heuristic
|
(make-obsolete-variable 'mu4e-view-html-plaintext-ratio-heuristic
|
||||||
"No longer in use" "1.7.0")
|
"No longer in use" "1.7.0")
|
||||||
(make-obsolete-variable 'mu4e-message-body-rewrite-functions
|
(make-obsolete-variable 'mu4e-message-body-rewrite-functions
|
||||||
"No longer in use" "1.7.0")
|
"No longer in use" "1.7.0")
|
||||||
;;; Html2Text
|
;;; Html2Text
|
||||||
(make-obsolete 'mu4e-shr2text "No longer in use" "1.7.0")
|
(make-obsolete 'mu4e-shr2text "No longer in use" "1.7.0")
|
||||||
|
|
||||||
@ -70,32 +70,32 @@
|
|||||||
|
|
||||||
;; old message view
|
;; old message view
|
||||||
(make-obsolete-variable 'mu4e-view-show-addresses
|
(make-obsolete-variable 'mu4e-view-show-addresses
|
||||||
"Unused with the new message view" "1.7.0")
|
"Unused with the new message view" "1.7.0")
|
||||||
(make-obsolete-variable 'mu4e-view-wrap-lines nil "0.9.9-dev7")
|
(make-obsolete-variable 'mu4e-view-wrap-lines nil "0.9.9-dev7")
|
||||||
(make-obsolete-variable 'mu4e-view-hide-cited nil "0.9.9-dev7")
|
(make-obsolete-variable 'mu4e-view-hide-cited nil "0.9.9-dev7")
|
||||||
(make-obsolete-variable 'mu4e-view-date-format
|
(make-obsolete-variable 'mu4e-view-date-format
|
||||||
"Unused with the new message view" "1.7.0")
|
"Unused with the new message view" "1.7.0")
|
||||||
(make-obsolete-variable 'mu4e-view-image-max-width
|
(make-obsolete-variable 'mu4e-view-image-max-width
|
||||||
"Unused with the new message view" "1.7.0")
|
"Unused with the new message view" "1.7.0")
|
||||||
(make-obsolete-variable 'mu4e-view-image-max-height
|
(make-obsolete-variable 'mu4e-view-image-max-height
|
||||||
"Unused with the new message view" "1.7.0")
|
"Unused with the new message view" "1.7.0")
|
||||||
(make-obsolete-variable 'mu4e-save-multiple-attachments-without-asking
|
(make-obsolete-variable 'mu4e-save-multiple-attachments-without-asking
|
||||||
"Unused with the new message view" "1.7.0")
|
"Unused with the new message view" "1.7.0")
|
||||||
(make-obsolete-variable 'mu4e-view-attachment-assoc
|
(make-obsolete-variable 'mu4e-view-attachment-assoc
|
||||||
"Unused with the new message view" "1.7.0")
|
"Unused with the new message view" "1.7.0")
|
||||||
(make-obsolete-variable 'mu4e-view-attachment-actions
|
(make-obsolete-variable 'mu4e-view-attachment-actions
|
||||||
"See mu4e-view-mime-part-actions" "1.7.0")
|
"See mu4e-view-mime-part-actions" "1.7.0")
|
||||||
(make-obsolete-variable 'mu4e-view-header-field-keymap
|
(make-obsolete-variable 'mu4e-view-header-field-keymap
|
||||||
"Unused with the new message view" "1.7.0")
|
"Unused with the new message view" "1.7.0")
|
||||||
(make-obsolete-variable 'mu4e-view-header-field-keymap
|
(make-obsolete-variable 'mu4e-view-header-field-keymap
|
||||||
"Unused with the new message view" "1.7.0")
|
"Unused with the new message view" "1.7.0")
|
||||||
(make-obsolete-variable 'mu4e-view-contacts-header-keymap
|
(make-obsolete-variable 'mu4e-view-contacts-header-keymap
|
||||||
"Unused with the new message view" "1.7.0")
|
"Unused with the new message view" "1.7.0")
|
||||||
(make-obsolete-variable 'mu4e-view-attachments-header-keymap
|
(make-obsolete-variable 'mu4e-view-attachments-header-keymap
|
||||||
"Unused with the new message view" "1.7.0")
|
"Unused with the new message view" "1.7.0")
|
||||||
(make-obsolete-variable 'mu4e-imagemagick-identify nil "1.7.0")
|
(make-obsolete-variable 'mu4e-imagemagick-identify nil "1.7.0")
|
||||||
(make-obsolete-variable 'mu4e-view-show-images
|
(make-obsolete-variable 'mu4e-view-show-images
|
||||||
"No longer used" "1.7.0")
|
"No longer used" "1.7.0")
|
||||||
(make-obsolete-variable 'mu4e-view-gnus "Old view is gone" "1.7.0")
|
(make-obsolete-variable 'mu4e-view-gnus "Old view is gone" "1.7.0")
|
||||||
(make-obsolete-variable 'mu4e-view-use-gnus "Gnus view is the default" "1.5.10")
|
(make-obsolete-variable 'mu4e-view-use-gnus "Gnus view is the default" "1.5.10")
|
||||||
|
|
||||||
@ -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
|
||||||
|
|||||||
@ -60,7 +60,7 @@ Otherwise, don't move to the next message."
|
|||||||
|
|
||||||
(defcustom mu4e-view-fields
|
(defcustom mu4e-view-fields
|
||||||
'(:from :to :cc :subject :flags :date :maildir :mailing-list :tags
|
'(:from :to :cc :subject :flags :date :maildir :mailing-list :tags
|
||||||
:attachments :signature :decryption)
|
:attachments :signature :decryption)
|
||||||
"Header fields to display in the message view buffer.
|
"Header fields to display in the message view buffer.
|
||||||
For the complete list of available headers, see
|
For the complete list of available headers, see
|
||||||
`mu4e-header-info'.
|
`mu4e-header-info'.
|
||||||
@ -75,11 +75,11 @@ details."
|
|||||||
|
|
||||||
(defcustom mu4e-view-actions
|
(defcustom mu4e-view-actions
|
||||||
(seq-filter 'identity
|
(seq-filter 'identity
|
||||||
`( ("capture message" . mu4e-action-capture-message)
|
`( ("capture message" . mu4e-action-capture-message)
|
||||||
("view in browser" . mu4e-action-view-in-browser)
|
("view in browser" . mu4e-action-view-in-browser)
|
||||||
,(when (fboundp 'xwidget-webkit-browse-url)
|
,(when (fboundp 'xwidget-webkit-browse-url)
|
||||||
'("xview in xwidget" . mu4e-action-view-in-xwidget))
|
'("xview in xwidget" . mu4e-action-view-in-xwidget))
|
||||||
("show this thread" . mu4e-action-show-thread)))
|
("show this thread" . mu4e-action-show-thread)))
|
||||||
"List of actions to perform on messages in view mode.
|
"List of actions to perform on messages in view mode.
|
||||||
The actions are cons-cells of the form:
|
The actions are cons-cells of the form:
|
||||||
(NAME . FUNC)
|
(NAME . FUNC)
|
||||||
@ -136,13 +136,13 @@ other windows."
|
|||||||
"Display the raw contents of message at point in a new buffer."
|
"Display the raw contents of message at point in a new buffer."
|
||||||
(interactive)
|
(interactive)
|
||||||
(let ((path (mu4e-message-readable-path))
|
(let ((path (mu4e-message-readable-path))
|
||||||
(buf (get-buffer-create mu4e~view-raw-buffer-name)))
|
(buf (get-buffer-create mu4e~view-raw-buffer-name)))
|
||||||
(with-current-buffer buf
|
(with-current-buffer buf
|
||||||
(let ((inhibit-read-only t))
|
(let ((inhibit-read-only t))
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(mu4e-raw-view-mode)
|
(mu4e-raw-view-mode)
|
||||||
(insert-file-contents path)
|
(insert-file-contents path)
|
||||||
(goto-char (point-min))))
|
(goto-char (point-min))))
|
||||||
(mu4e-display-buffer buf t)))
|
(mu4e-display-buffer buf t)))
|
||||||
|
|
||||||
(defun mu4e-view-pipe (cmd)
|
(defun mu4e-view-pipe (cmd)
|
||||||
@ -163,16 +163,17 @@ 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))))
|
||||||
(docid (mu4e-message-field msg :docid)))
|
(docid (mu4e-message-field msg :docid)))
|
||||||
(unless docid
|
(unless docid
|
||||||
(mu4e-error "Message without docid: action is not possible"))
|
(mu4e-error "Message without docid: action is not possible"))
|
||||||
(with-current-buffer buffer
|
(with-current-buffer buffer
|
||||||
(mu4e-display-buffer buffer)
|
(mu4e-display-buffer buffer)
|
||||||
(if (or (mu4e~headers-goto-docid docid)
|
(if (or (mu4e~headers-goto-docid docid)
|
||||||
;; TODO: Is this the best way to find another
|
;; TODO: Is this the best way to find another
|
||||||
;; relevant docid for a view buffer?
|
;; relevant docid for a view buffer?
|
||||||
;;
|
;;
|
||||||
@ -185,8 +186,8 @@ Then, display the results."
|
|||||||
(mu4e~headers-goto-docid
|
(mu4e~headers-goto-docid
|
||||||
(with-current-buffer buffer
|
(with-current-buffer buffer
|
||||||
(mu4e-message-field (mu4e-message-at-point) :docid))))
|
(mu4e-message-field (mu4e-message-at-point) :docid))))
|
||||||
,@body
|
,@body
|
||||||
(mu4e-error "Cannot find message in headers buffer"))))))
|
(mu4e-error "Cannot find message in headers buffer"))))))
|
||||||
|
|
||||||
(defun mu4e-view-headers-next (&optional n)
|
(defun mu4e-view-headers-next (&optional n)
|
||||||
"Move point to the next message header.
|
"Move point to the next message header.
|
||||||
@ -238,7 +239,7 @@ bymessage-at-point. The actions are specified in
|
|||||||
`mu4e-view-actions'."
|
`mu4e-view-actions'."
|
||||||
(interactive)
|
(interactive)
|
||||||
(let* ((msg (or msg (mu4e-message-at-point)))
|
(let* ((msg (or msg (mu4e-message-at-point)))
|
||||||
(actionfunc (mu4e-read-option "Action: " mu4e-view-actions)))
|
(actionfunc (mu4e-read-option "Action: " mu4e-view-actions)))
|
||||||
(funcall actionfunc msg)))
|
(funcall actionfunc msg)))
|
||||||
|
|
||||||
(defun mu4e-view-mark-pattern ()
|
(defun mu4e-view-mark-pattern ()
|
||||||
@ -289,25 +290,25 @@ Add this function to `mu4e-view-mode-hook' to enable this feature."
|
|||||||
(save-excursion
|
(save-excursion
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
(while (re-search-forward
|
(while (re-search-forward
|
||||||
(concat "^" message-mark-insert-begin) nil t)
|
(concat "^" message-mark-insert-begin) nil t)
|
||||||
(setq ov-beg (match-beginning 0)
|
(setq ov-beg (match-beginning 0)
|
||||||
ov-end (match-end 0)
|
ov-end (match-end 0)
|
||||||
ov-inv (make-overlay ov-beg ov-end)
|
ov-inv (make-overlay ov-beg ov-end)
|
||||||
beg ov-end)
|
beg ov-end)
|
||||||
(overlay-put ov-inv 'invisible t)
|
(overlay-put ov-inv 'invisible t)
|
||||||
(overlay-put ov-inv 'mu4e-overlay t)
|
(overlay-put ov-inv 'mu4e-overlay t)
|
||||||
(when (re-search-forward
|
(when (re-search-forward
|
||||||
(concat "^" message-mark-insert-end) nil t)
|
(concat "^" message-mark-insert-end) nil t)
|
||||||
(setq ov-beg (match-beginning 0)
|
(setq ov-beg (match-beginning 0)
|
||||||
ov-end (match-end 0)
|
ov-end (match-end 0)
|
||||||
ov-inv (make-overlay ov-beg ov-end)
|
ov-inv (make-overlay ov-beg ov-end)
|
||||||
end ov-beg)
|
end ov-beg)
|
||||||
(overlay-put ov-inv 'invisible t))
|
(overlay-put ov-inv 'invisible t))
|
||||||
(when (and beg end)
|
(when (and beg end)
|
||||||
(let ((ov (make-overlay beg end)))
|
(let ((ov (make-overlay beg end)))
|
||||||
(overlay-put ov 'mu4e-overlay t)
|
(overlay-put ov 'mu4e-overlay t)
|
||||||
(overlay-put ov 'face 'mu4e-region-code))
|
(overlay-put ov 'face 'mu4e-region-code))
|
||||||
(setq beg nil end nil))))))
|
(setq beg nil end nil))))))
|
||||||
|
|
||||||
;;; View Utilities
|
;;; View Utilities
|
||||||
|
|
||||||
@ -391,12 +392,12 @@ list."
|
|||||||
(defmacro mu4e~view-defun-mark-for (mark)
|
(defmacro mu4e~view-defun-mark-for (mark)
|
||||||
"Define a function mu4e-view-mark-for- MARK."
|
"Define a function mu4e-view-mark-for- MARK."
|
||||||
(let ((funcname (intern (format "mu4e-view-mark-for-%s" mark)))
|
(let ((funcname (intern (format "mu4e-view-mark-for-%s" mark)))
|
||||||
(docstring (format "Mark the current message for %s." mark)))
|
(docstring (format "Mark the current message for %s." mark)))
|
||||||
`(progn
|
`(progn
|
||||||
(defun ,funcname () ,docstring
|
(defun ,funcname () ,docstring
|
||||||
(interactive)
|
(interactive)
|
||||||
(mu4e~view-in-headers-context
|
(mu4e~view-in-headers-context
|
||||||
(mu4e-headers-mark-and-next ',mark)))
|
(mu4e-headers-mark-and-next ',mark)))
|
||||||
(put ',funcname 'definition-name ',mark))))
|
(put ',funcname 'definition-name ',mark))))
|
||||||
|
|
||||||
(mu4e~view-defun-mark-for move)
|
(mu4e~view-defun-mark-for move)
|
||||||
@ -446,8 +447,8 @@ If the url is mailto link, start writing an email to that address."
|
|||||||
(let* (( url (or url (mu4e~view-get-property-from-event 'mu4e-url))))
|
(let* (( url (or url (mu4e~view-get-property-from-event 'mu4e-url))))
|
||||||
(when url
|
(when url
|
||||||
(if (string-match-p "^mailto:" url)
|
(if (string-match-p "^mailto:" url)
|
||||||
(browse-url-mail url)
|
(browse-url-mail url)
|
||||||
(browse-url url)))))
|
(browse-url url)))))
|
||||||
|
|
||||||
|
|
||||||
(defun mu4e~view-get-property-from-event (prop)
|
(defun mu4e~view-get-property-from-event (prop)
|
||||||
@ -455,13 +456,13 @@ If the url is mailto link, start writing an email to that address."
|
|||||||
The action is chosen based on the `last-command-event'.
|
The action is chosen based on the `last-command-event'.
|
||||||
Meant to be evoked from interactive commands."
|
Meant to be evoked from interactive commands."
|
||||||
(if (and (eventp last-command-event)
|
(if (and (eventp last-command-event)
|
||||||
(mouse-event-p last-command-event))
|
(mouse-event-p last-command-event))
|
||||||
(let ((posn (event-end last-command-event)))
|
(let ((posn (event-end last-command-event)))
|
||||||
(when (numberp (posn-point posn))
|
(when (numberp (posn-point posn))
|
||||||
(get-text-property
|
(get-text-property
|
||||||
(posn-point posn)
|
(posn-point posn)
|
||||||
prop
|
prop
|
||||||
(window-buffer (posn-window posn)))))
|
(window-buffer (posn-window posn)))))
|
||||||
(get-text-property (point) prop)))
|
(get-text-property (point) prop)))
|
||||||
|
|
||||||
;; this is fairly simplistic...
|
;; this is fairly simplistic...
|
||||||
@ -471,27 +472,27 @@ Also number them so they can be opened using `mu4e-view-go-to-url'."
|
|||||||
(let ((num 0))
|
(let ((num 0))
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(setq mu4e~view-link-map ;; buffer local
|
(setq mu4e~view-link-map ;; buffer local
|
||||||
(make-hash-table :size 32 :weakness nil))
|
(make-hash-table :size 32 :weakness nil))
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
(while (re-search-forward mu4e~view-beginning-of-url-regexp nil t)
|
(while (re-search-forward mu4e~view-beginning-of-url-regexp nil t)
|
||||||
(let ((bounds (thing-at-point-bounds-of-url-at-point)))
|
(let ((bounds (thing-at-point-bounds-of-url-at-point)))
|
||||||
(when bounds
|
(when bounds
|
||||||
(let* ((url (thing-at-point-url-at-point))
|
(let* ((url (thing-at-point-url-at-point))
|
||||||
(ov (make-overlay (car bounds) (cdr bounds))))
|
(ov (make-overlay (car bounds) (cdr bounds))))
|
||||||
(puthash (cl-incf num) url mu4e~view-link-map)
|
(puthash (cl-incf num) url mu4e~view-link-map)
|
||||||
(add-text-properties
|
(add-text-properties
|
||||||
(car bounds)
|
(car bounds)
|
||||||
(cdr bounds)
|
(cdr bounds)
|
||||||
`(face mu4e-link-face
|
`(face mu4e-link-face
|
||||||
mouse-face highlight
|
mouse-face highlight
|
||||||
mu4e-url ,url
|
mu4e-url ,url
|
||||||
keymap ,mu4e-view-active-urls-keymap
|
keymap ,mu4e-view-active-urls-keymap
|
||||||
help-echo
|
help-echo
|
||||||
"[mouse-1] or [M-RET] to open the link"))
|
"[mouse-1] or [M-RET] to open the link"))
|
||||||
(overlay-put ov 'mu4e-overlay t)
|
(overlay-put ov 'mu4e-overlay t)
|
||||||
(overlay-put ov 'after-string
|
(overlay-put ov 'after-string
|
||||||
(propertize (format "\u200B[%d]" num)
|
(propertize (format "\u200B[%d]" num)
|
||||||
'face 'mu4e-url-number-face)))))))))
|
'face 'mu4e-url-number-face)))))))))
|
||||||
|
|
||||||
|
|
||||||
(defun mu4e~view-get-urls-num (prompt &optional multi)
|
(defun mu4e~view-get-urls-num (prompt &optional multi)
|
||||||
@ -504,21 +505,21 @@ string."
|
|||||||
(let* ((count (hash-table-count mu4e~view-link-map)) (def))
|
(let* ((count (hash-table-count mu4e~view-link-map)) (def))
|
||||||
(when (zerop count) (mu4e-error "No links for this message"))
|
(when (zerop count) (mu4e-error "No links for this message"))
|
||||||
(if (not multi)
|
(if (not multi)
|
||||||
(if (= count 1)
|
(if (= count 1)
|
||||||
(read-number (mu4e-format "%s: " prompt) 1)
|
(read-number (mu4e-format "%s: " prompt) 1)
|
||||||
(read-number (mu4e-format "%s (1-%d): " prompt count)))
|
(read-number (mu4e-format "%s (1-%d): " prompt count)))
|
||||||
(progn
|
(progn
|
||||||
(setq def (if (= count 1) "1" (format "1-%d" count)))
|
(setq def (if (= count 1) "1" (format "1-%d" count)))
|
||||||
(read-string (mu4e-format "%s (default %s): " prompt def)
|
(read-string (mu4e-format "%s (default %s): " prompt def)
|
||||||
nil nil def)))))
|
nil nil def)))))
|
||||||
|
|
||||||
(defun mu4e-view-go-to-url (&optional multi)
|
(defun mu4e-view-go-to-url (&optional multi)
|
||||||
"Offer to go visit one or more URLs.
|
"Offer to go visit one or more URLs.
|
||||||
If MULTI (prefix-argument) is non-nil, offer to go to a range of URLs."
|
If MULTI (prefix-argument) is non-nil, offer to go to a range of URLs."
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
(mu4e~view-handle-urls "URL to visit"
|
(mu4e~view-handle-urls "URL to visit"
|
||||||
multi
|
multi
|
||||||
(lambda (url) (mu4e~view-browse-url-from-binding url))))
|
(lambda (url) (mu4e~view-browse-url-from-binding url))))
|
||||||
|
|
||||||
(defun mu4e-view-save-url (&optional multi)
|
(defun mu4e-view-save-url (&optional multi)
|
||||||
"Offer to save URLs to the kill ring.
|
"Offer to save URLs to the kill ring.
|
||||||
@ -526,9 +527,9 @@ If MULTI (prefix-argument) is nil, save a single one, otherwise, offer
|
|||||||
to save a range of URLs."
|
to save a range of URLs."
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
(mu4e~view-handle-urls "URL to save" multi
|
(mu4e~view-handle-urls "URL to save" multi
|
||||||
(lambda (url)
|
(lambda (url)
|
||||||
(kill-new url)
|
(kill-new url)
|
||||||
(mu4e-message "Saved %s to the kill-ring" url))))
|
(mu4e-message "Saved %s to the kill-ring" url))))
|
||||||
|
|
||||||
(defun mu4e-view-fetch-url (&optional multi)
|
(defun mu4e-view-fetch-url (&optional multi)
|
||||||
"Offer to fetch (download) URLs.
|
"Offer to fetch (download) URLs.
|
||||||
@ -540,7 +541,7 @@ URLs. The urls are fetched to `mu4e-attachment-dir'."
|
|||||||
"URL to fetch" multi
|
"URL to fetch" multi
|
||||||
(lambda (url)
|
(lambda (url)
|
||||||
(let ((target (concat (mu4e~get-attachment-dir url) "/"
|
(let ((target (concat (mu4e~get-attachment-dir url) "/"
|
||||||
(file-name-nondirectory url))))
|
(file-name-nondirectory url))))
|
||||||
(url-copy-file url target)
|
(url-copy-file url target)
|
||||||
(mu4e-message "Fetched %s -> %s" url target)))))
|
(mu4e-message "Fetched %s -> %s" url target)))))
|
||||||
|
|
||||||
@ -556,7 +557,7 @@ it to a range of uris. PROMPT is the query to present to the user."
|
|||||||
"Apply URLFUNC to some URL with NUM in the current message.
|
"Apply URLFUNC to some URL with NUM in the current message.
|
||||||
Prompting the user with PROMPT for the number."
|
Prompting the user with PROMPT for the number."
|
||||||
(let* ((num (or num (mu4e~view-get-urls-num prompt)))
|
(let* ((num (or num (mu4e~view-get-urls-num prompt)))
|
||||||
(url (gethash num mu4e~view-link-map)))
|
(url (gethash num mu4e~view-link-map)))
|
||||||
(unless url (mu4e-warn "Invalid number for URL"))
|
(unless url (mu4e-warn "Invalid number for URL"))
|
||||||
(funcall urlfunc url)))
|
(funcall urlfunc url)))
|
||||||
|
|
||||||
@ -572,9 +573,9 @@ of urls. You can type multiple values separated by space, e.g. 1
|
|||||||
Furthermore, there is a shortcut \"a\" which means all urls, but as
|
Furthermore, there is a shortcut \"a\" which means all urls, but as
|
||||||
this is the default, you may not need it."
|
this is the default, you may not need it."
|
||||||
(let* ((linkstr (mu4e~view-get-urls-num
|
(let* ((linkstr (mu4e~view-get-urls-num
|
||||||
"URL number range (or 'a' for 'all')" t))
|
"URL number range (or 'a' for 'all')" t))
|
||||||
(count (hash-table-count mu4e~view-link-map))
|
(count (hash-table-count mu4e~view-link-map))
|
||||||
(linknums (mu4e-split-ranges-to-numbers linkstr count)))
|
(linknums (mu4e-split-ranges-to-numbers linkstr count)))
|
||||||
(dolist (num linknums)
|
(dolist (num linknums)
|
||||||
(mu4e~view-handle-single-url prompt urlfunc num))))
|
(mu4e~view-handle-single-url prompt urlfunc num))))
|
||||||
|
|
||||||
@ -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)))
|
||||||
@ -673,17 +675,17 @@ determine which browser function to use."
|
|||||||
(mu4e-message-readable-path msg) nil nil nil t)
|
(mu4e-message-readable-path msg) nil nil nil t)
|
||||||
(run-hooks 'gnus-article-decode-hook)
|
(run-hooks 'gnus-article-decode-hook)
|
||||||
(let ((header (unless skip-headers
|
(let ((header (unless skip-headers
|
||||||
(cl-loop for field in '("from" "to" "cc" "date" "subject")
|
(cl-loop for field in '("from" "to" "cc" "date" "subject")
|
||||||
when (message-fetch-field field)
|
when (message-fetch-field field)
|
||||||
concat (format "%s: %s\n" (capitalize field) it))))
|
concat (format "%s: %s\n" (capitalize field) it))))
|
||||||
(parts (mm-dissect-buffer t t)))
|
(parts (mm-dissect-buffer t t)))
|
||||||
;; If singlepart, enforce a list.
|
;; If singlepart, enforce a list.
|
||||||
(when (and (bufferp (car parts))
|
(when (and (bufferp (car parts))
|
||||||
(stringp (car (mm-handle-type parts))))
|
(stringp (car (mm-handle-type parts))))
|
||||||
(setq parts (list parts)))
|
(setq parts (list parts)))
|
||||||
;; Process the list
|
;; Process the list
|
||||||
(unless (gnus-article-browse-html-parts parts header)
|
(unless (gnus-article-browse-html-parts parts header)
|
||||||
(mu4e-warn "Message does not contain a \"text/html\" part"))
|
(mu4e-warn "Message does not contain a \"text/html\" part"))
|
||||||
(mm-destroy-parts parts))))
|
(mm-destroy-parts parts))))
|
||||||
|
|
||||||
(defun mu4e-action-view-in-xwidget (msg)
|
(defun mu4e-action-view-in-xwidget (msg)
|
||||||
@ -700,38 +702,38 @@ determine which browser function to use."
|
|||||||
"Render current buffer with MSG using Gnus' article mode."
|
"Render current buffer with MSG using Gnus' article mode."
|
||||||
(setq gnus-summary-buffer (get-buffer-create " *appease-gnus*"))
|
(setq gnus-summary-buffer (get-buffer-create " *appease-gnus*"))
|
||||||
(let* ((inhibit-read-only t)
|
(let* ((inhibit-read-only t)
|
||||||
(max-specpdl-size mu4e-view-max-specpdl-size)
|
(max-specpdl-size mu4e-view-max-specpdl-size)
|
||||||
(mm-decrypt-option 'known)
|
(mm-decrypt-option 'known)
|
||||||
(ct (mail-fetch-field "Content-Type"))
|
(ct (mail-fetch-field "Content-Type"))
|
||||||
(ct (and ct (mail-header-parse-content-type ct)))
|
(ct (and ct (mail-header-parse-content-type ct)))
|
||||||
(charset (mail-content-type-get ct 'charset))
|
(charset (mail-content-type-get ct 'charset))
|
||||||
(charset (and charset (intern charset)))
|
(charset (and charset (intern charset)))
|
||||||
(mu4e~view-rendering t); Needed if e.g. an ics file is buttonized
|
(mu4e~view-rendering t); Needed if e.g. an ics file is buttonized
|
||||||
(gnus-article-emulate-mime t)
|
(gnus-article-emulate-mime t)
|
||||||
(gnus-unbuttonized-mime-types '(".*/.*"))
|
(gnus-unbuttonized-mime-types '(".*/.*"))
|
||||||
(gnus-buttonized-mime-types
|
(gnus-buttonized-mime-types
|
||||||
(append (list "multipart/signed" "multipart/encrypted")
|
(append (list "multipart/signed" "multipart/encrypted")
|
||||||
gnus-buttonized-mime-types))
|
gnus-buttonized-mime-types))
|
||||||
(gnus-newsgroup-charset
|
(gnus-newsgroup-charset
|
||||||
(if (and charset (coding-system-p charset)) charset
|
(if (and charset (coding-system-p charset)) charset
|
||||||
(detect-coding-region (point-min) (point-max) t)))
|
(detect-coding-region (point-min) (point-max) t)))
|
||||||
;; Possibly add headers (before "Attachments")
|
;; Possibly add headers (before "Attachments")
|
||||||
(gnus-display-mime-function (mu4e~view-gnus-display-mime msg))
|
(gnus-display-mime-function (mu4e~view-gnus-display-mime msg))
|
||||||
(gnus-icalendar-additional-identities
|
(gnus-icalendar-additional-identities
|
||||||
(mu4e-personal-addresses 'no-regexp)))
|
(mu4e-personal-addresses 'no-regexp)))
|
||||||
(condition-case err
|
(condition-case err
|
||||||
(progn
|
(progn
|
||||||
(mm-enable-multibyte)
|
(mm-enable-multibyte)
|
||||||
(run-hooks 'gnus-article-decode-hook)
|
(run-hooks 'gnus-article-decode-hook)
|
||||||
(gnus-article-prepare-display)
|
(gnus-article-prepare-display)
|
||||||
(mu4e~view-activate-urls)
|
(mu4e~view-activate-urls)
|
||||||
(setq mu4e~gnus-article-mime-handles gnus-article-mime-handles
|
(setq mu4e~gnus-article-mime-handles gnus-article-mime-handles
|
||||||
gnus-article-decoded-p gnus-article-decode-hook)
|
gnus-article-decoded-p gnus-article-decode-hook)
|
||||||
(set-buffer-modified-p nil)
|
(set-buffer-modified-p nil)
|
||||||
(add-hook 'kill-buffer-hook #'mu4e~view-kill-mime-handles))
|
(add-hook 'kill-buffer-hook #'mu4e~view-kill-mime-handles))
|
||||||
(epg-error
|
(epg-error
|
||||||
(mu4e-warn "EPG error: %s; fall back to raw view"
|
(mu4e-warn "EPG error: %s; fall back to raw view"
|
||||||
(error-message-string err))))))
|
(error-message-string err))))))
|
||||||
|
|
||||||
(defun mu4e~view-kill-mime-handles ()
|
(defun mu4e~view-kill-mime-handles ()
|
||||||
"Kill cached MIME-handles, if any."
|
"Kill cached MIME-handles, if any."
|
||||||
@ -750,7 +752,7 @@ determine which browser function to use."
|
|||||||
"Toggle whether to show all MIME-parts."
|
"Toggle whether to show all MIME-parts."
|
||||||
(interactive)
|
(interactive)
|
||||||
(setq gnus-inhibit-mime-unbuttonizing
|
(setq gnus-inhibit-mime-unbuttonizing
|
||||||
(not gnus-inhibit-mime-unbuttonizing))
|
(not gnus-inhibit-mime-unbuttonizing))
|
||||||
(mu4e-view-refresh))
|
(mu4e-view-refresh))
|
||||||
|
|
||||||
(defun mu4e-view-toggle-fill-flowed()
|
(defun mu4e-view-toggle-fill-flowed()
|
||||||
@ -765,54 +767,54 @@ determine which browser function to use."
|
|||||||
(gnus-display-mime ihandles)
|
(gnus-display-mime ihandles)
|
||||||
(unless ihandles
|
(unless ihandles
|
||||||
(save-restriction
|
(save-restriction
|
||||||
(article-goto-body)
|
(article-goto-body)
|
||||||
(forward-line -1)
|
(forward-line -1)
|
||||||
(narrow-to-region (point) (point))
|
(narrow-to-region (point) (point))
|
||||||
(dolist (field mu4e-view-fields)
|
(dolist (field mu4e-view-fields)
|
||||||
(let ((fieldval (mu4e-message-field msg field)))
|
(let ((fieldval (mu4e-message-field msg field)))
|
||||||
(pcase field
|
(pcase field
|
||||||
((or ':path ':maildir :list ':user-agent ':message-id)
|
((or ':path ':maildir :list ':user-agent ':message-id)
|
||||||
(mu4e~view-gnus-insert-header field fieldval))
|
(mu4e~view-gnus-insert-header field fieldval))
|
||||||
(':mailing-list
|
(':mailing-list
|
||||||
(let ((list (plist-get msg :list)))
|
(let ((list (plist-get msg :list)))
|
||||||
(if list (mu4e-get-mailing-list-shortname list) "")))
|
(if list (mu4e-get-mailing-list-shortname list) "")))
|
||||||
((or ':flags ':tags)
|
((or ':flags ':tags)
|
||||||
(let ((flags (mapconcat (lambda (flag)
|
(let ((flags (mapconcat (lambda (flag)
|
||||||
(if (symbolp flag)
|
(if (symbolp flag)
|
||||||
(symbol-name flag)
|
(symbol-name flag)
|
||||||
flag)) fieldval ", ")))
|
flag)) fieldval ", ")))
|
||||||
(mu4e~view-gnus-insert-header field flags)))
|
(mu4e~view-gnus-insert-header field flags)))
|
||||||
(':size (mu4e~view-gnus-insert-header
|
(':size (mu4e~view-gnus-insert-header
|
||||||
field (mu4e-display-size fieldval)))
|
field (mu4e-display-size fieldval)))
|
||||||
((or ':subject ':to ':from ':cc ':bcc ':from-or-to
|
((or ':subject ':to ':from ':cc ':bcc ':from-or-to
|
||||||
':date :attachments ':signature
|
':date :attachments ':signature
|
||||||
':decryption)) ; handled by Gnus
|
':decryption)) ; handled by Gnus
|
||||||
(_
|
(_
|
||||||
(mu4e~view-gnus-insert-header-custom msg field)))))
|
(mu4e~view-gnus-insert-header-custom msg field)))))
|
||||||
(let ((gnus-treatment-function-alist
|
(let ((gnus-treatment-function-alist
|
||||||
'((gnus-treat-highlight-headers
|
'((gnus-treat-highlight-headers
|
||||||
gnus-article-highlight-headers))))
|
gnus-article-highlight-headers))))
|
||||||
(gnus-treat-article 'head))))))
|
(gnus-treat-article 'head))))))
|
||||||
|
|
||||||
(defun mu4e~view-gnus-insert-header (field val)
|
(defun mu4e~view-gnus-insert-header (field val)
|
||||||
"Insert a header FIELD with value VAL."
|
"Insert a header FIELD with value VAL."
|
||||||
(let* ((info (cdr (assoc field mu4e-header-info)))
|
(let* ((info (cdr (assoc field mu4e-header-info)))
|
||||||
(key (plist-get info :name))
|
(key (plist-get info :name))
|
||||||
(help (plist-get info :help)))
|
(help (plist-get info :help)))
|
||||||
(if (and val (> (length val) 0))
|
(if (and val (> (length val) 0))
|
||||||
(insert (propertize (concat key ":") 'help-echo help)
|
(insert (propertize (concat key ":") 'help-echo help)
|
||||||
" " val "\n"))))
|
" " val "\n"))))
|
||||||
|
|
||||||
(defun mu4e~view-gnus-insert-header-custom (msg field)
|
(defun mu4e~view-gnus-insert-header-custom (msg field)
|
||||||
"Insert MSG's custom FIELD."
|
"Insert MSG's custom FIELD."
|
||||||
(let* ((info (cdr-safe (or (assoc field mu4e-header-info-custom)
|
(let* ((info (cdr-safe (or (assoc field mu4e-header-info-custom)
|
||||||
(mu4e-error "Custom field %S not found" field))))
|
(mu4e-error "Custom field %S not found" field))))
|
||||||
(key (plist-get info :name))
|
(key (plist-get info :name))
|
||||||
(func (or (plist-get info :function)
|
(func (or (plist-get info :function)
|
||||||
(mu4e-error "No :function defined for custom field %S %S"
|
(mu4e-error "No :function defined for custom field %S %S"
|
||||||
field info)))
|
field info)))
|
||||||
(val (funcall func msg))
|
(val (funcall func msg))
|
||||||
(help (plist-get info :help)))
|
(help (plist-get info :help)))
|
||||||
(when (and val (> (length val) 0))
|
(when (and val (> (length val) 0))
|
||||||
(insert (propertize (concat key ":") 'help-echo help) " " val "\n"))))
|
(insert (propertize (concat key ":") 'help-echo help) " " val "\n"))))
|
||||||
|
|
||||||
@ -821,14 +823,14 @@ determine which browser function to use."
|
|||||||
"Avoid error when displaying an ical attachment without a charset."
|
"Avoid error when displaying an ical attachment without a charset."
|
||||||
(if (and (boundp 'mu4e~view-rendering) mu4e~view-rendering)
|
(if (and (boundp 'mu4e~view-rendering) mu4e~view-rendering)
|
||||||
(let* ((handle (car handle-attendee))
|
(let* ((handle (car handle-attendee))
|
||||||
(attendee (cadr handle-attendee))
|
(attendee (cadr handle-attendee))
|
||||||
(buf (mm-handle-buffer handle))
|
(buf (mm-handle-buffer handle))
|
||||||
(ty (mm-handle-type handle))
|
(ty (mm-handle-type handle))
|
||||||
(rest (cddr handle)))
|
(rest (cddr handle)))
|
||||||
;; Put the fallback at the end:
|
;; Put the fallback at the end:
|
||||||
(setq ty (append ty '((charset . "utf-8"))))
|
(setq ty (append ty '((charset . "utf-8"))))
|
||||||
(setq handle (cons buf (cons ty rest)))
|
(setq handle (cons buf (cons ty rest)))
|
||||||
(list handle attendee))
|
(list handle attendee))
|
||||||
handle-attendee))
|
handle-attendee))
|
||||||
|
|
||||||
(defun mu4e~view-mode-p ()
|
(defun mu4e~view-mode-p ()
|
||||||
@ -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)
|
||||||
@ -961,26 +961,26 @@ This is useful for advising some Gnus-functionality that does not work in mu4e."
|
|||||||
(define-key map [menu-bar headers] (cons "Mu4e" menumap))
|
(define-key map [menu-bar headers] (cons "Mu4e" menumap))
|
||||||
|
|
||||||
(define-key menumap [quit-buffer]
|
(define-key menumap [quit-buffer]
|
||||||
'("Quit view" . mu4e~view-quit-buffer))
|
'("Quit view" . mu4e~view-quit-buffer))
|
||||||
(define-key menumap [display-help] '("Help" . mu4e-display-manual))
|
(define-key menumap [display-help] '("Help" . mu4e-display-manual))
|
||||||
|
|
||||||
(define-key menumap [sepa0] '("--"))
|
(define-key menumap [sepa0] '("--"))
|
||||||
(define-key menumap [wrap-lines]
|
(define-key menumap [wrap-lines]
|
||||||
'("Toggle wrap lines" . visual-line-mode))
|
'("Toggle wrap lines" . visual-line-mode))
|
||||||
(define-key menumap [raw-view]
|
(define-key menumap [raw-view]
|
||||||
'("View raw message" . mu4e-view-raw-message))
|
'("View raw message" . mu4e-view-raw-message))
|
||||||
(define-key menumap [pipe]
|
(define-key menumap [pipe]
|
||||||
'("Pipe through shell" . mu4e-view-pipe))
|
'("Pipe through shell" . mu4e-view-pipe))
|
||||||
|
|
||||||
(define-key menumap [sepa1] '("--"))
|
(define-key menumap [sepa1] '("--"))
|
||||||
(define-key menumap [mark-delete]
|
(define-key menumap [mark-delete]
|
||||||
'("Mark for deletion" . mu4e-view-mark-for-delete))
|
'("Mark for deletion" . mu4e-view-mark-for-delete))
|
||||||
(define-key menumap [mark-untrash]
|
(define-key menumap [mark-untrash]
|
||||||
'("Mark for untrash" . mu4e-view-mark-for-untrash))
|
'("Mark for untrash" . mu4e-view-mark-for-untrash))
|
||||||
(define-key menumap [mark-trash]
|
(define-key menumap [mark-trash]
|
||||||
'("Mark for trash" . mu4e-view-mark-for-trash))
|
'("Mark for trash" . mu4e-view-mark-for-trash))
|
||||||
(define-key menumap [mark-move]
|
(define-key menumap [mark-move]
|
||||||
'("Mark for move" . mu4e-view-mark-for-move))
|
'("Mark for move" . mu4e-view-mark-for-move))
|
||||||
|
|
||||||
(define-key menumap [sepa2] '("--"))
|
(define-key menumap [sepa2] '("--"))
|
||||||
(define-key menumap [resend] '("Resend" . mu4e-compose-resend))
|
(define-key menumap [resend] '("Resend" . mu4e-compose-resend))
|
||||||
@ -990,17 +990,17 @@ This is useful for advising some Gnus-functionality that does not work in mu4e."
|
|||||||
(define-key menumap [sepa3] '("--"))
|
(define-key menumap [sepa3] '("--"))
|
||||||
|
|
||||||
(define-key menumap [query-next]
|
(define-key menumap [query-next]
|
||||||
'("Next query" . mu4e-headers-query-next))
|
'("Next query" . mu4e-headers-query-next))
|
||||||
(define-key menumap [query-prev]
|
(define-key menumap [query-prev]
|
||||||
'("Previous query" . mu4e-headers-query-prev))
|
'("Previous query" . mu4e-headers-query-prev))
|
||||||
(define-key menumap [narrow-search]
|
(define-key menumap [narrow-search]
|
||||||
'("Narrow search" . mu4e-headers-search-narrow))
|
'("Narrow search" . mu4e-headers-search-narrow))
|
||||||
(define-key menumap [bookmark]
|
(define-key menumap [bookmark]
|
||||||
'("Search bookmark" . mu4e-headers-search-bookmark))
|
'("Search bookmark" . mu4e-headers-search-bookmark))
|
||||||
(define-key menumap [jump]
|
(define-key menumap [jump]
|
||||||
'("Jump to maildir" . mu4e~headers-jump-to-maildir))
|
'("Jump to maildir" . mu4e~headers-jump-to-maildir))
|
||||||
(define-key menumap [search]
|
(define-key menumap [search]
|
||||||
'("Search" . mu4e-headers-search))
|
'("Search" . mu4e-headers-search))
|
||||||
|
|
||||||
(define-key menumap [sepa4] '("--"))
|
(define-key menumap [sepa4] '("--"))
|
||||||
(define-key menumap [next] '("Next" . mu4e-view-headers-next))
|
(define-key menumap [next] '("Next" . mu4e-view-headers-next))
|
||||||
@ -1048,9 +1048,9 @@ Based on Gnus' article-mode."
|
|||||||
;; advice gnus-block-private-groups to always return "."
|
;; advice gnus-block-private-groups to always return "."
|
||||||
;; so that by default we block images.
|
;; so that by default we block images.
|
||||||
(advice-add 'gnus-block-private-groups :around
|
(advice-add 'gnus-block-private-groups :around
|
||||||
(lambda(func &rest args)
|
(lambda(func &rest args)
|
||||||
(if (mu4e~view-mode-p)
|
(if (mu4e~view-mode-p)
|
||||||
"." (apply func args))))
|
"." (apply func args))))
|
||||||
(use-local-map mu4e-view-mode-map)
|
(use-local-map mu4e-view-mode-map)
|
||||||
(mu4e-context-minor-mode)
|
(mu4e-context-minor-mode)
|
||||||
(mu4e-search-minor-mode)
|
(mu4e-search-minor-mode)
|
||||||
@ -1094,12 +1094,12 @@ The alist uniquely maps the number to the gnus-part."
|
|||||||
(save-excursion
|
(save-excursion
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
(while (not (eobp))
|
(while (not (eobp))
|
||||||
(let ((part (get-text-property (point) 'gnus-data))
|
(let ((part (get-text-property (point) 'gnus-data))
|
||||||
(index (get-text-property (point) 'gnus-part)))
|
(index (get-text-property (point) 'gnus-part)))
|
||||||
(when (and part (numberp index) (not (assoc index parts))
|
(when (and part (numberp index) (not (assoc index parts))
|
||||||
(push `(,index . ,part) parts)))
|
(push `(,index . ,part) parts)))
|
||||||
(goto-char (or (next-single-property-change (point) 'gnus-part)
|
(goto-char (or (next-single-property-change (point) 'gnus-part)
|
||||||
(point-max))))))
|
(point-max))))))
|
||||||
parts))
|
parts))
|
||||||
|
|
||||||
|
|
||||||
@ -1118,47 +1118,47 @@ Note, currently this does not work well with file names
|
|||||||
containing commas."
|
containing commas."
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
(cl-assert (and (eq major-mode 'mu4e-view-mode)
|
(cl-assert (and (eq major-mode 'mu4e-view-mode)
|
||||||
(derived-mode-p 'gnus-article-mode)))
|
(derived-mode-p 'gnus-article-mode)))
|
||||||
(let* ((parts (mu4e~view-gather-mime-parts))
|
(let* ((parts (mu4e~view-gather-mime-parts))
|
||||||
(handles '())
|
(handles '())
|
||||||
(files '())
|
(files '())
|
||||||
(compfn (if (and (boundp 'helm-mode) helm-mode)
|
(compfn (if (and (boundp 'helm-mode) helm-mode)
|
||||||
#'completing-read
|
#'completing-read
|
||||||
;; Fallback to `completing-read-multiple' with poor
|
;; Fallback to `completing-read-multiple' with poor
|
||||||
;; completion
|
;; completion
|
||||||
#'completing-read-multiple))
|
#'completing-read-multiple))
|
||||||
dir)
|
dir)
|
||||||
(dolist (part parts)
|
(dolist (part parts)
|
||||||
(let ((fname (or (cdr (assoc 'filename (assoc "attachment" (cdr part))))
|
(let ((fname (or (cdr (assoc 'filename (assoc "attachment" (cdr part))))
|
||||||
(cl-loop for item in part
|
(cl-loop for item in part
|
||||||
for name = (and (listp item)
|
for name = (and (listp item)
|
||||||
(assoc-default 'name item))
|
(assoc-default 'name item))
|
||||||
thereis (and (stringp name) name)))))
|
thereis (and (stringp name) name)))))
|
||||||
(when fname
|
(when fname
|
||||||
(push `(,fname . ,(cdr part)) handles)
|
(push `(,fname . ,(cdr part)) handles)
|
||||||
(push fname files))))
|
(push fname files))))
|
||||||
(if files
|
(if files
|
||||||
(progn
|
(progn
|
||||||
(setq files (let ((helm-comp-read-use-marked t))
|
(setq files (let ((helm-comp-read-use-marked t))
|
||||||
(funcall compfn "Save part(s): " files))
|
(funcall compfn "Save part(s): " files))
|
||||||
dir (if arg (read-directory-name "Save to directory: ")
|
dir (if arg (read-directory-name "Save to directory: ")
|
||||||
mu4e-attachment-dir))
|
mu4e-attachment-dir))
|
||||||
(cl-loop for (f . h) in handles
|
(cl-loop for (f . h) in handles
|
||||||
when (member f files)
|
when (member f files)
|
||||||
do (mm-save-part-to-file
|
do (mm-save-part-to-file
|
||||||
h (let ((file (expand-file-name f dir)))
|
h (let ((file (expand-file-name f dir)))
|
||||||
(if (file-exists-p file)
|
(if (file-exists-p file)
|
||||||
(let (newname (count 1))
|
(let (newname (count 1))
|
||||||
(while (and
|
(while (and
|
||||||
(setq newname
|
(setq newname
|
||||||
(concat
|
(concat
|
||||||
(file-name-sans-extension file)
|
(file-name-sans-extension file)
|
||||||
(format "(%s)" count)
|
(format "(%s)" count)
|
||||||
(file-name-extension file t)))
|
(file-name-extension file t)))
|
||||||
(file-exists-p newname))
|
(file-exists-p newname))
|
||||||
(cl-incf count))
|
(cl-incf count))
|
||||||
newname)
|
newname)
|
||||||
file)))))
|
file)))))
|
||||||
(mu4e-message "No attached files found"))))
|
(mu4e-message "No attached files found"))))
|
||||||
|
|
||||||
|
|
||||||
@ -1176,7 +1176,7 @@ containing commas."
|
|||||||
(:name "open" :handler mu4e~view-open-file :receives temp)
|
(:name "open" :handler mu4e~view-open-file :receives temp)
|
||||||
;; open with some custom file.
|
;; open with some custom file.
|
||||||
(:name "wopen-with" :handler (lambda (file)(mu4e~view-open-file file t))
|
(:name "wopen-with" :handler (lambda (file)(mu4e~view-open-file file t))
|
||||||
:receives temp)
|
:receives temp)
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;; some more examples
|
;; some more examples
|
||||||
@ -1191,13 +1191,13 @@ containing commas."
|
|||||||
(:name "emacs" :handler find-file-read-only :receives temp)
|
(:name "emacs" :handler find-file-read-only :receives temp)
|
||||||
;; open in this emacs instance, "raw"
|
;; open in this emacs instance, "raw"
|
||||||
(:name "raw" :handler (lambda (str)
|
(:name "raw" :handler (lambda (str)
|
||||||
(let ((tmpbuf
|
(let ((tmpbuf
|
||||||
(get-buffer-create " *mu4e-raw-mime*")))
|
(get-buffer-create " *mu4e-raw-mime*")))
|
||||||
(with-current-buffer tmpbuf
|
(with-current-buffer tmpbuf
|
||||||
(insert str)
|
(insert str)
|
||||||
(view-mode)
|
(view-mode)
|
||||||
(goto-char (point-min)))
|
(goto-char (point-min)))
|
||||||
(display-buffer tmpbuf))) :receives pipe))
|
(display-buffer tmpbuf))) :receives pipe))
|
||||||
|
|
||||||
"Specifies actions for MIME-parts.
|
"Specifies actions for MIME-parts.
|
||||||
|
|
||||||
@ -1205,16 +1205,16 @@ Each of the actions is a plist with keys
|
|||||||
`(:name <name> ;; name of the action; shortcut is first letter of name
|
`(:name <name> ;; name of the action; shortcut is first letter of name
|
||||||
|
|
||||||
:handler ;; one of:
|
:handler ;; one of:
|
||||||
;; - a function receiving the index/temp/pipe
|
;; - a function receiving the index/temp/pipe
|
||||||
;; - a string, which is taken as a shell command
|
;; - a string, which is taken as a shell command
|
||||||
|
|
||||||
:receives ;; a symbol specifying what the handler receives
|
:receives ;; a symbol specifying what the handler receives
|
||||||
;; - index: the index number of the mime part (default)
|
;; - index: the index number of the mime part (default)
|
||||||
;; - temp: the full path to the mime part in a
|
;; - temp: the full path to the mime part in a
|
||||||
;; temporary file, which is deleted immediately
|
;; temporary file, which is deleted immediately
|
||||||
;; after invoking handler
|
;; after invoking handler
|
||||||
;; - pipe: the attachment is piped to some shell command
|
;; - pipe: the attachment is piped to some shell command
|
||||||
;; or as a string parameter to a function
|
;; or as a string parameter to a function
|
||||||
).")
|
).")
|
||||||
|
|
||||||
|
|
||||||
@ -1225,17 +1225,17 @@ otherwise random; the result is placed in a temporary directory
|
|||||||
with a unique name. Returns the full path for the file created.
|
with a unique name. Returns the full path for the file created.
|
||||||
The directory and file are self-destructed."
|
The directory and file are self-destructed."
|
||||||
(let* ((tmpdir (make-temp-file "mu4e-temp-" t))
|
(let* ((tmpdir (make-temp-file "mu4e-temp-" t))
|
||||||
(fname (mm-handle-filename handle))
|
(fname (mm-handle-filename handle))
|
||||||
(fname (and fname
|
(fname (and fname
|
||||||
(gnus-map-function mm-file-name-rewrite-functions
|
(gnus-map-function mm-file-name-rewrite-functions
|
||||||
(file-name-nondirectory fname))))
|
(file-name-nondirectory fname))))
|
||||||
(fname (if fname
|
(fname (if fname
|
||||||
(concat tmpdir "/" (replace-regexp-in-string "/" "-" fname))
|
(concat tmpdir "/" (replace-regexp-in-string "/" "-" fname))
|
||||||
(let ((temporary-file-directory tmpdir))
|
(let ((temporary-file-directory tmpdir))
|
||||||
(make-temp-file "mimepart")))))
|
(make-temp-file "mimepart")))))
|
||||||
(mm-save-part-to-file handle fname)
|
(mm-save-part-to-file handle fname)
|
||||||
(run-at-time "30 sec" nil
|
(run-at-time "30 sec" nil
|
||||||
(lambda () (ignore-errors (delete-directory tmpdir t))))
|
(lambda () (ignore-errors (delete-directory tmpdir t))))
|
||||||
fname))
|
fname))
|
||||||
|
|
||||||
|
|
||||||
@ -1247,9 +1247,9 @@ open with."
|
|||||||
(functionp mu4e-view-open-program))
|
(functionp mu4e-view-open-program))
|
||||||
(funcall mu4e-view-open-program file)
|
(funcall mu4e-view-open-program file)
|
||||||
(let ((opener
|
(let ((opener
|
||||||
(or (and (not force-ask) mu4e-view-open-program
|
(or (and (not force-ask) mu4e-view-open-program
|
||||||
(executable-find mu4e-view-open-program))
|
(executable-find mu4e-view-open-program))
|
||||||
(read-shell-command "Open MIME-part with: "))))
|
(read-shell-command "Open MIME-part with: "))))
|
||||||
(call-process opener nil 0 nil file))))
|
(call-process opener nil 0 nil file))))
|
||||||
|
|
||||||
(defun mu4e-view-mime-part-action (&optional n)
|
(defun mu4e-view-mime-part-action (&optional n)
|
||||||
@ -1258,43 +1258,43 @@ If N is not specified, ask for it. For instance, '3 A o' opens
|
|||||||
the third MIME-part."
|
the third MIME-part."
|
||||||
(interactive "NNumber of MIME-part: ")
|
(interactive "NNumber of MIME-part: ")
|
||||||
(let* ((parts (mu4e~view-gather-mime-parts))
|
(let* ((parts (mu4e~view-gather-mime-parts))
|
||||||
(options
|
(options
|
||||||
(mapcar (lambda (action) `(,(plist-get action :name) . ,action))
|
(mapcar (lambda (action) `(,(plist-get action :name) . ,action))
|
||||||
mu4e-view-mime-part-actions))
|
mu4e-view-mime-part-actions))
|
||||||
(handle
|
(handle
|
||||||
(or (cdr-safe (seq-find (lambda (part) (eq (car part) n)) parts))
|
(or (cdr-safe (seq-find (lambda (part) (eq (car part) n)) parts))
|
||||||
(mu4e-error "MIME-part %s not found" n)))
|
(mu4e-error "MIME-part %s not found" n)))
|
||||||
(action
|
(action
|
||||||
(or (and options (mu4e-read-option "Action on MIME-part: " options))
|
(or (and options (mu4e-read-option "Action on MIME-part: " options))
|
||||||
(mu4e-error "No such action")))
|
(mu4e-error "No such action")))
|
||||||
(handler
|
(handler
|
||||||
(or (plist-get action :handler)
|
(or (plist-get action :handler)
|
||||||
(mu4e-error "No :handler item found for action %S" action)))
|
(mu4e-error "No :handler item found for action %S" action)))
|
||||||
(receives
|
(receives
|
||||||
(or (plist-get action :receives)
|
(or (plist-get action :receives)
|
||||||
(mu4e-error "No :receives item found for action %S" action))))
|
(mu4e-error "No :receives item found for action %S" action))))
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(cond
|
(cond
|
||||||
((functionp handler)
|
((functionp handler)
|
||||||
(cond
|
(cond
|
||||||
((eq receives 'index) (funcall handler n))
|
((eq receives 'index) (funcall handler n))
|
||||||
((eq receives 'pipe) (funcall handler (mm-with-unibyte-buffer
|
((eq receives 'pipe) (funcall handler (mm-with-unibyte-buffer
|
||||||
(mm-insert-part handle)
|
(mm-insert-part handle)
|
||||||
(buffer-string))))
|
(buffer-string))))
|
||||||
((eq receives 'temp)
|
((eq receives 'temp)
|
||||||
(funcall handler (mu4e~view-mime-part-to-temp-file handle)))
|
(funcall handler (mu4e~view-mime-part-to-temp-file handle)))
|
||||||
(t (mu4e-error "Invalid :receive for %S" action))))
|
(t (mu4e-error "Invalid :receive for %S" action))))
|
||||||
((stringp handler)
|
((stringp handler)
|
||||||
(cond
|
(cond
|
||||||
((eq receives 'index)
|
((eq receives 'index)
|
||||||
(shell-command (concat handler " " (shell-quote-argument n))))
|
(shell-command (concat handler " " (shell-quote-argument n))))
|
||||||
((eq receives 'pipe) (mm-pipe-part handle handler))
|
((eq receives 'pipe) (mm-pipe-part handle handler))
|
||||||
((eq receives 'temp)
|
((eq receives 'temp)
|
||||||
(shell-command
|
(shell-command
|
||||||
(shell-command (concat handler " "
|
(shell-command (concat handler " "
|
||||||
(shell-quote-argument
|
(shell-quote-argument
|
||||||
(mu4e~view-mime-part-to-temp-file handle))))))
|
(mu4e~view-mime-part-to-temp-file handle))))))
|
||||||
(t (mu4e-error "Invalid action %S" action))))))))
|
(t (mu4e-error "Invalid action %S" action))))))))
|
||||||
|
|
||||||
(defun mu4e-view-toggle-html ()
|
(defun mu4e-view-toggle-html ()
|
||||||
"Toggle html-display of the first html-part found."
|
"Toggle html-display of the first html-part found."
|
||||||
@ -1303,9 +1303,9 @@ the third MIME-part."
|
|||||||
;; pertinence, i.e. the first HTML part found in it is the most important one.
|
;; pertinence, i.e. the first HTML part found in it is the most important one.
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(if-let ((html-part
|
(if-let ((html-part
|
||||||
(seq-find (lambda (handle)
|
(seq-find (lambda (handle)
|
||||||
(equal (mm-handle-media-type (cdr handle)) "text/html"))
|
(equal (mm-handle-media-type (cdr handle)) "text/html"))
|
||||||
gnus-article-mime-handle-alist)))
|
gnus-article-mime-handle-alist)))
|
||||||
(gnus-article-inline-part (car html-part))
|
(gnus-article-inline-part (car html-part))
|
||||||
(mu4e-warn "No html part in this message"))))
|
(mu4e-warn "No html part in this message"))))
|
||||||
|
|
||||||
@ -1347,7 +1347,7 @@ value against HEADER-REGEXP in
|
|||||||
header-values))))
|
header-values))))
|
||||||
|
|
||||||
(add-hook 'bug-reference-auto-setup-functions
|
(add-hook 'bug-reference-auto-setup-functions
|
||||||
#'mu4e--view-try-setup-bug-reference-mode)
|
#'mu4e--view-try-setup-bug-reference-mode)
|
||||||
|
|
||||||
|
|
||||||
(provide 'mu4e-view)
|
(provide 'mu4e-view)
|
||||||
|
|||||||
@ -706,46 +706,46 @@ The main view looks something like the following:
|
|||||||
|
|
||||||
Basics
|
Basics
|
||||||
|
|
||||||
* [j]ump to some maildir
|
* [j]ump to some maildir
|
||||||
* enter a [s]earch query
|
* enter a [s]earch query
|
||||||
* [C]ompose a new message
|
* [C]ompose a new message
|
||||||
|
|
||||||
Bookmarks
|
Bookmarks
|
||||||
|
|
||||||
* [bu] Unread messages (13085/13085)
|
* [bu] Unread messages (13085/13085)
|
||||||
* [bt] Today's messages
|
* [bt] Today's messages
|
||||||
* [bw] Last 7 days (53/128)
|
* [bw] Last 7 days (53/128)
|
||||||
* [bp] Messages with images (75/2441)
|
* [bp] Messages with images (75/2441)
|
||||||
|
|
||||||
Maildirs
|
Maildirs
|
||||||
|
|
||||||
* [ja] /archive (2101/18837)
|
* [ja] /archive (2101/18837)
|
||||||
* [ji] /inbox (1/2)
|
* [ji] /inbox (1/2)
|
||||||
* [jb] /bulk (33/35)
|
* [jb] /bulk (33/35)
|
||||||
* [jB] /bulkarchive (179/2090)
|
* [jB] /bulkarchive (179/2090)
|
||||||
* [jm] /mu (694/17687)
|
* [jm] /mu (694/17687)
|
||||||
* [jn] /sauron
|
* [jn] /sauron
|
||||||
* [js] /sent
|
* [js] /sent
|
||||||
|
|
||||||
Misc
|
Misc
|
||||||
|
|
||||||
* [;]Switch context
|
* [;]Switch context
|
||||||
* [U]pdate email & database
|
* [U]pdate email & database
|
||||||
* toggle [m]ail sending mode (currently direct)
|
* toggle [m]ail sending mode (currently direct)
|
||||||
* [f]lush 1 queued mail
|
* [f]lush 1 queued mail
|
||||||
|
|
||||||
* [N]ews
|
* [N]ews
|
||||||
* [A]bout mu4e
|
* [A]bout mu4e
|
||||||
* [H]elp
|
* [H]elp
|
||||||
* [q]uit
|
* [q]uit
|
||||||
|
|
||||||
Info
|
Info
|
||||||
|
|
||||||
* last updated : Sat May 7 20:37:37 2022
|
* last updated : Sat May 7 20:37:37 2022
|
||||||
* database-path : /home/pam/.cache/mu/xapian
|
* database-path : /home/pam/.cache/mu/xapian
|
||||||
* maildir : /home/pam/Maildir
|
* maildir : /home/pam/Maildir
|
||||||
* in store : 86179 messages
|
* in store : 86179 messages
|
||||||
* personal addresses : /.*example.com/, pam@fo
|
* personal addresses : /.*example.com/, pam@fo
|
||||||
|
|
||||||
@end verbatim
|
@end verbatim
|
||||||
@end cartouche
|
@end cartouche
|
||||||
@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user