From 6814250a0c95e0849c191e7f5fe8e2a8bee31440 Mon Sep 17 00:00:00 2001 From: Aaron LI Date: Tue, 2 Aug 2016 22:49:19 +0800 Subject: spacemacs: update mu/mu4e to git20160802 --- _spacemacs.d/local/mu4e/mu4e-actions.el | 10 +- _spacemacs.d/local/mu4e/mu4e-compose.el | 179 +++++++++++++++++++++---------- _spacemacs.d/local/mu4e/mu4e-contrib.el | 3 +- _spacemacs.d/local/mu4e/mu4e-draft.el | 61 +++++++---- _spacemacs.d/local/mu4e/mu4e-headers.el | 111 +++++++++++-------- _spacemacs.d/local/mu4e/mu4e-main.el | 10 +- _spacemacs.d/local/mu4e/mu4e-proc.el | 5 +- _spacemacs.d/local/mu4e/mu4e-speedbar.el | 7 +- _spacemacs.d/local/mu4e/mu4e-utils.el | 86 +++++++++++---- _spacemacs.d/local/mu4e/mu4e-vars.el | 75 +++++++++++-- _spacemacs.d/local/mu4e/mu4e-view.el | 7 +- _spacemacs.d/local/mu4e/mu4e.el | 9 ++ _spacemacs.d/local/mu4e/org-mu4e.el | 6 +- 13 files changed, 395 insertions(+), 174 deletions(-) diff --git a/_spacemacs.d/local/mu4e/mu4e-actions.el b/_spacemacs.d/local/mu4e/mu4e-actions.el index 7f145a1..0128c52 100644 --- a/_spacemacs.d/local/mu4e/mu4e-actions.el +++ b/_spacemacs.d/local/mu4e/mu4e-actions.el @@ -93,7 +93,7 @@ return the filename." (if (plist-get attachment :temp) (replace-match (format "src=\"%s\"" (plist-get attachment :temp))) (replace-match (format "src=\"%s%s\"" temporary-file-directory (plist-get attachment :name))) - (mu4e~proc-extract 'save (mu4e-message-field :docid) (plist-get attachment :index) mu4e-decryption-policy temporary-file-directory) + (mu4e~proc-extract 'save (mu4e-message-field msg :docid) (plist-get attachment :index) mu4e-decryption-policy temporary-file-directory) (mu4e-remove-file-later (format "%s%s" temporary-file-directory (plist-get attachment :name)))))) attachments) (save-buffer) @@ -299,13 +299,17 @@ store your org-contacts." (defun mu4e-action-show-thread (msg) "Show all messages that are in the same thread as the message -at point." +at point. Point remains on the message with the message-id where +the action was invoked. If invoked in view-mode, continue to +display the message." (let ((msgid (mu4e-message-field msg :message-id))) (when msgid (let ((mu4e-headers-show-threads t) (mu4e-headers-include-related t)) (mu4e-headers-search - (format "msgid:%s" msgid)))))) + (format "msgid:%s" msgid) + nil nil nil + msgid (eq major-mode 'mu4e-view-mode)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/_spacemacs.d/local/mu4e/mu4e-compose.el b/_spacemacs.d/local/mu4e/mu4e-compose.el index af2b34b..32d238d 100644 --- a/_spacemacs.d/local/mu4e/mu4e-compose.el +++ b/_spacemacs.d/local/mu4e/mu4e-compose.el @@ -140,8 +140,25 @@ Also see `mu4e-context-policy'." (const :tag "Ask when there's no context yet" 'ask-if-none) (const :tag "Pick the first context if none match" 'pick-first) (const :tag "Don't change the context when none match" nil) - :safe 'symbolp - :group 'mu4e-compose)) + :safe 'symbolp + :group 'mu4e-compose)) + + +(defcustom mu4e-compose-crypto-reply-policy 'sign-and-encrypt + "Policy for signing/encrypting replies to encrypted messages. +We have the following choices: + +- `sign': sign the reply +- `sign-and-encrypt': sign and encrypt the repy +- `encrypt': encrypt the reply, but don't sign it. +- anything else: do nothing." + :type '(choice + (const :tag "Sign the reply" 'sign) + (const :tag "Sign and encrypt the reply" 'sign-and-encrypt) + (const :tag "Encrypt the reply" 'encrypt) + (const :tag "Don't do anything" nil) + :safe 'symbolp + :group 'mu4e-compose)) (defcustom mu4e-compose-format-flowed nil "Whether to compose messages to be sent as format=flowed (or @@ -165,13 +182,14 @@ it has been constructed, `mu4e-compose-mode-hook' would be the place to do that." :type 'hook :group 'mu4e-compose) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun mu4e-compose-attach-captured-message () "Insert the last captured message file as an attachment. Messages are captured with `mu4e-action-capture-message'." - (interactive) + (interactive) (unless mu4e-captured-message (mu4e-warn "No message has been captured")) (let ((path (plist-get mu4e-captured-message :path))) @@ -224,8 +242,8 @@ If needed, set the Fcc header, and register the handler function." (when fccfile (message-add-header (concat "Fcc: " fccfile "\n")) ;; sadly, we cannot define as 'buffer-local'... this will screw up gnus - ;; etc. if you run it after mu4e so, (hack hack) we reset it to the old - ;; handler after we've done our thing. + ;; etc. if you run it after mu4e so, (hack hack) we reset it to the old + ;; handler after we've done our thing. (setq message-fcc-handler-function (lexical-let ((maildir mdir) (old-handler message-fcc-handler-function)) (lambda (file) @@ -276,7 +294,7 @@ appear on disk." ;; our contacts are already sorted - just need to tell the ;; completion machinery not to try to undo that... '(metadata - (display-sort-function . mu4e~sort-contacts-for-completion) + (display-sort-function . mu4e~sort-contacts-for-completion) (cycle-sort-function . mu4e~sort-contacts-for-completion))))) (defun mu4e~compose-complete-contact (&optional start) @@ -335,18 +353,41 @@ simply executes `fill-paragraph'." ;; Inspired by https://www.emacswiki.org/emacs/UnfillParagraph (interactive (progn (barf-if-buffer-read-only) '(t))) (if mu4e-compose-format-flowed - (let ((fill-column (point-max)) - (use-hard-newlines nil)); rfill "across" hard newlines - (fill-paragraph nil region)) + (let ((fill-column (point-max)) + (use-hard-newlines nil)); rfill "across" hard newlines + (fill-paragraph nil region)) (fill-paragraph nil region))) (defun mu4e-toggle-use-hard-newlines () (interactive) (setq use-hard-newlines (not use-hard-newlines)) (if use-hard-newlines - (turn-off-auto-fill) + (turn-off-auto-fill) (turn-on-auto-fill))) +(defun mu4e~compose-remap-faces () + "Our parent `message-mode' uses font-locking for the compose +buffers; lets remap its faces so it uses the ones for mu4e." + ;; normal headers + (face-remap-add-relative 'message-header-name + '((:inherit mu4e-header-key-face))) + (face-remap-add-relative 'message-header-other + '((:inherit mu4e-header-value-face))) + ;; special headers + (face-remap-add-relative 'message-header-from + '((:inherit mu4e-contact-face))) + (face-remap-add-relative 'message-header-to + '((:inherit mu4e-contact-face))) + (face-remap-add-relative 'message-header-cc + '((:inherit mu4e-contact-face))) + (face-remap-add-relative 'message-header-bcc + '((:inherit mu4e-contact-face))) + (face-remap-add-relative 'message-header-subject + '((:inherit mu4e-special-header-value-face))) + ;; citation + (face-remap-add-relative 'message-cited-text + '((:inherit mu4e-cited-1-face)))) + (defvar mu4e-compose-mode-abbrev-table nil) (define-derived-mode mu4e-compose-mode message-mode "mu4e:compose" @@ -354,13 +395,14 @@ simply executes `fill-paragraph'." \\{message-mode-map}." (progn (use-local-map mu4e-compose-mode-map) - (set (make-local-variable 'global-mode-string) '(:eval (mu4e-context-label))) - (set (make-local-variable 'message-signature) mu4e-compose-signature) ;; set this to allow mu4e to work when gnus-agent is unplugged in gnus (set (make-local-variable 'message-send-mail-real-function) nil) (make-local-variable 'message-default-charset) + ;; message-mode has font-locking, but uses its own faces. Let's + ;; use the mu4e-specific ones instead + (mu4e~compose-remap-faces) ;; if the default charset is not set, use UTF-8 (unless message-default-charset (setq message-default-charset 'utf-8)) @@ -372,7 +414,6 @@ simply executes `fill-paragraph'." ;; useful e.g. when finding an attachment file the directory the current ;; mail files lives in... (setq default-directory (expand-file-name "~/")) - ;; offer completion for e-mail addresses (when mu4e-compose-complete-addresses (mu4e~compose-setup-completion)) @@ -380,31 +421,33 @@ simply executes `fill-paragraph'." (when mu4e-compose-format-flowed (turn-off-auto-fill) (setq truncate-lines nil - word-wrap t - use-hard-newlines t) + word-wrap t + use-hard-newlines t) ;; Set the marks in the fringes before activating visual-line-mode (set (make-local-variable 'visual-line-fringe-indicators) - '(left-curly-arrow right-curly-arrow)) + '(left-curly-arrow right-curly-arrow)) (visual-line-mode t)) - (define-key-after - (lookup-key message-mode-map [menu-bar text]) - [mu4e-hard-newlines] - '(menu-item "Format=flowed" mu4e-toggle-use-hard-newlines - :button (:toggle . use-hard-newlines) - :help "Toggle format=flowed" - :visible (eq major-mode 'mu4e-compose-mode) - :enable mu4e-compose-format-flowed) - 'sep) - - (define-key-after - (lookup-key mml-mode-map [menu-bar Attachments]) - [mu4e-compose-attach-captured-message] - '(menu-item "Attach captured message" - mu4e-compose-attach-captured-message - :help "Attach message captured in Headers View (with 'a c')" - :visible (eq major-mode 'mu4e-compose-mode)) - (quote Attach\ External...)) + (when (lookup-key message-mode-map [menu-bar text]) + (define-key-after + (lookup-key message-mode-map [menu-bar text]) + [mu4e-hard-newlines] + '(menu-item "Format=flowed" mu4e-toggle-use-hard-newlines + :button (:toggle . use-hard-newlines) + :help "Toggle format=flowed" + :visible (eq major-mode 'mu4e-compose-mode) + :enable mu4e-compose-format-flowed) + 'sep)) + + (when (lookup-key mml-mode-map [menu-bar Attachments]) + (define-key-after + (lookup-key mml-mode-map [menu-bar Attachments]) + [mu4e-compose-attach-captured-message] + '(menu-item "Attach captured message" + mu4e-compose-attach-captured-message + :help "Attach message captured in Headers View (with 'a c')" + :visible (eq major-mode 'mu4e-compose-mode)) + (quote Attach\ External...))) ;; setup the fcc-stuff, if needed (add-hook 'message-send-hook @@ -455,6 +498,21 @@ simply executes `fill-paragraph'." mu4e~compose-buffer-max-name-length nil nil t))))) + +(defun mu4e~compose-crypto-reply (parent compose-type) + "When composing a reply to an encrypted message, we can +automatically encrypt that reply." + (message "%S %S" parent compose-type) + (when (and (eq compose-type 'reply) + (and parent (member 'encrypted (mu4e-message-field parent :flags)))) + (case mu4e-compose-crypto-reply-policy + (sign (mml-secure-message-sign)) + (encrypt (mml-secure-message-encrypt)) + (sign-and-encrypt (mml-secure-message-sign-encrypt)) + (message "Do nothing")))) + + + (defun* mu4e~compose-handler (compose-type &optional original-msg includes) "Create a new draft message, or open an existing one. @@ -480,17 +538,21 @@ tempfile)." (put 'mu4e-compose-parent-message 'permanent-local t) ;; maybe switch the context (mu4e~context-autoswitch mu4e-compose-parent-message - mu4e-compose-context-policy) + mu4e-compose-context-policy) (run-hooks 'mu4e-compose-pre-hook) ;; this opens (or re-opens) a messages with all the basic headers set. - (condition-case nil + (let ((winconf (current-window-configuration))) + (condition-case nil (mu4e-draft-open compose-type original-msg) - (quit (kill-buffer) (mu4e-message "Operation aborted") - (return-from mu4e~compose-handler))) + (quit (set-window-configuration winconf) + (mu4e-message "Operation aborted") + (return-from mu4e~compose-handler)))) ;; insert mail-header-separator, which is needed by message mode to separate ;; headers and body. will be removed before saving to disk (mu4e~draft-insert-mail-header-separator) + ;; maybe encrypt/sign replies + (mu4e~compose-crypto-reply original-msg compose-type) ;; include files -- e.g. when forwarding a message with attachments, ;; we take those from the original. (save-excursion @@ -502,7 +564,7 @@ tempfile)." (mu4e~compose-set-friendly-buffer-name compose-type) (set-buffer-modified-p nil) ;; now jump to some useful positions, and start writing that mail! - + (if (member compose-type '(new forward)) (message-goto-to) (message-goto-body)) @@ -512,8 +574,8 @@ tempfile)." ;; remember the compose-type (set (make-local-variable 'mu4e~compose-type) compose-type) (put 'mu4e~compose-type 'permanent-local t) - - ;; hide some headers + + ;; hide some headers (mu4e~compose-hide-headers) ;; switch on the mode (mu4e-compose-mode) @@ -534,17 +596,17 @@ the appropriate flag at the message forwarded or replied-to." ;; this seems a bit hamfisted... (dolist (buf (buffer-list)) (when (and (buffer-file-name buf) - (string= (buffer-file-name buf) path)) + (string= (buffer-file-name buf) path)) (if message-kill-buffer-on-exit - (kill-buffer buf)))) + (kill-buffer buf)))) ;; now, try to go back to some previous buffer, in the order ;; view->headers->main (if (buffer-live-p mu4e~view-buffer) - (switch-to-buffer mu4e~view-buffer) - (if (buffer-live-p mu4e~headers-buffer) - (switch-to-buffer mu4e~headers-buffer) - ;; if all else fails, back to the main view - (when (fboundp 'mu4e) (mu4e)))) + (switch-to-buffer mu4e~view-buffer) + (if (buffer-live-p mu4e~headers-buffer) + (switch-to-buffer mu4e~headers-buffer) + ;; if all else fails, back to the main view + (when (fboundp 'mu4e) (mu4e)))) (mu4e-message "Message sent")) (defun mu4e-message-kill-buffer () @@ -557,11 +619,11 @@ It restores mu4e window layout after killing the compose-buffer." (when (not (equal current-buffer (current-buffer))) ;; Restore mu4e (if mu4e-compose-in-new-frame - (delete-frame) + (delete-frame) (if (buffer-live-p mu4e~view-buffer) - (switch-to-buffer mu4e~view-buffer) + (switch-to-buffer mu4e~view-buffer) (if (buffer-live-p mu4e~headers-buffer) - (switch-to-buffer mu4e~headers-buffer) + (switch-to-buffer mu4e~headers-buffer) ;; if all else fails, back to the main view (when (fboundp 'mu4e) (mu4e)))))))) @@ -627,12 +689,12 @@ is a symbol, one of `reply', `forward', `edit', `resend' (mu4e~compose-handler 'new) ;; otherwise, we need the doc-id (let* ((docid (mu4e-message-field msg :docid)) - ;; decrypt (or not), based on `mu4e-decryption-policy'. - (decrypt - (and (member 'encrypted (mu4e-message-field msg :flags)) - (if (eq mu4e-decryption-policy 'ask) - (yes-or-no-p (mu4e-format "Decrypt message?")) - mu4e-decryption-policy)))) + ;; decrypt (or not), based on `mu4e-decryption-policy'. + (decrypt + (and (member 'encrypted (mu4e-message-field msg :flags)) + (if (eq mu4e-decryption-policy 'ask) + (yes-or-no-p (mu4e-format "Decrypt message?")) + mu4e-decryption-policy)))) ;; if there's a visible view window, select that before starting composing ;; a new message, so that one will be replaced by the compose window. The ;; 10-or-so line headers buffer is not a good place to write it... @@ -669,7 +731,6 @@ draft message." (interactive) (mu4e-compose 'new)) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; mu4e-compose-func and mu4e-send-func are wrappers so we can set ourselves @@ -761,7 +822,7 @@ Go to the end of the message (before signature) or, if already there, go to the end of the buffer." (interactive) (let ((old-position (point)) - (message-position (save-excursion (message-goto-body) (point)))) + (message-position (save-excursion (message-goto-body) (point)))) (goto-char (point-max)) (when (re-search-backward message-signature-separator message-position t) (forward-line -1)) diff --git a/_spacemacs.d/local/mu4e/mu4e-contrib.el b/_spacemacs.d/local/mu4e/mu4e-contrib.el index 8952401..156f5b6 100644 --- a/_spacemacs.d/local/mu4e/mu4e-contrib.el +++ b/_spacemacs.d/local/mu4e/mu4e-contrib.el @@ -67,7 +67,8 @@ 'mu4e-view-bookmark-make-record))) (defun mu4e-view-bookmark-make-record () - "Make a bookmark entry for a mu4e buffer." + "Make a bookmark entry for a mu4e buffer. Note that this is an +emacs bookmark, not to be confused with `mu4e-bookmarks'." (let* ((msg (mu4e-message-at-point)) (maildir (plist-get msg :maildir)) (date (format-time-string "%Y%m%d" (plist-get msg :date))) diff --git a/_spacemacs.d/local/mu4e/mu4e-draft.el b/_spacemacs.d/local/mu4e/mu4e-draft.el index c41e38d..d7df6e0 100644 --- a/_spacemacs.d/local/mu4e/mu4e-draft.el +++ b/_spacemacs.d/local/mu4e/mu4e-draft.el @@ -99,7 +99,6 @@ its settings apply." (funcall mu4e-compose-cite-function)) (pop-mark) (goto-char (point-min)) - (mu4e~fontify-cited) (buffer-string)))) (defun mu4e~draft-header (hdr val) @@ -109,7 +108,17 @@ If VAL is nil, return nil." ;; later. (when val (format "%s: %s\n" (propertize hdr 'face 'mu4e-header-key-face) - (propertize val 'face 'mu4e-header-val-face)))) + (propertize val 'face 'mu4e-header-value-face)))) + +(defconst mu4e~max-reference-num 21 + "Maximum number of References:, as suggested by +`message-shorten-references'.") + +(defun mu4e~shorten-1 (list cut surplus) + "Cut SURPLUS elements out of LIST, beginning with CUTth +one. Code borrowed from `message-shorten-1'." + (setcdr (nthcdr (- cut 2) list) + (nthcdr (+ (- cut 2) surplus 1) list))) (defun mu4e~draft-references-construct (msg) "Construct the value of the References: header based on MSG as a @@ -125,10 +134,16 @@ References. If both are empty, return nil." (refs (if (and msgid (not (string= msgid ""))) (append refs (list msgid)) refs)) ;; no doubles - (refs (delete-duplicates refs :test #'equal))) + (refs (delete-duplicates refs :test #'equal)) + (refnum (length refs)) + (cut 2)) + ;; remove some refs when there are too many + (when (> refnum mu4e~max-reference-num) + (let ((surplus (- refnum mu4e~max-reference-num))) + (mu4e~shorten-1 refs cut surplus))) (mapconcat (lambda (id) (format "<%s>" id)) refs " "))) - + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; determine the recipient fields for new messages @@ -311,7 +326,7 @@ You can append flags." (format-time-string "%s" (current-time)) (random 65535) (random 65535) (random 65535) (random 65535) hostname (or flagstr "")))) - + (defun mu4e~draft-common-construct () "Construct the common headers for each message." (concat @@ -346,11 +361,12 @@ fields will be the same as in the original." (mu4e~draft-header "To" (mu4e~draft-recipients-list-to-string (mu4e-message-field origmsg :to))) (mu4e~draft-header "Cc" (mu4e~draft-recipients-list-to-string - (mu4e-message-field origmsg :cc)))) - + (mu4e-message-field origmsg :cc)))) + ;; if there's no-one in To, copy the CC-list (if (zerop (length (mu4e~draft-create-to-lst origmsg))) - (mu4e~draft-header "To" (mu4e~draft-recipients-construct :cc origmsg reply-all)) + (mu4e~draft-header "To" (mu4e~draft-recipients-construct + :cc origmsg reply-all)) ;; otherwise... (concat (mu4e~draft-header "To" (mu4e~draft-recipients-construct :to origmsg)) @@ -415,9 +431,10 @@ fields will be the same as in the original." (defun mu4e-draft-open (compose-type &optional msg) - "Open a draft file for a new message (when COMPOSE-TYPE is `reply', `forward' or `new'), -open an existing draft (when COMPOSE-TYPE is `edit'), or re-send -an existing message (when COMPOSE-TYPE is `resend'). + "Open a draft file for a new message (when COMPOSE-TYPE is `reply', + `forward' or `new'), open an existing draft (when COMPOSE-TYPE +is `edit'), or re-send an existing message (when COMPOSE-TYPE is +`resend'). The name of the draft folder is constructed from the concatenation of `mu4e-maildir' and `mu4e-drafts-folder' (the @@ -428,10 +445,11 @@ will be created from either `mu4e~draft-reply-construct', or (unless mu4e-maildir (mu4e-error "mu4e-maildir not set")) (let ((draft-dir nil)) (case compose-type - + (edit - ;; case-1: re-editing a draft messages. in this case, we do know the full - ;; path, but we cannot really know 'drafts folder'... we make a guess + ;; case-1: re-editing a draft messages. in this case, we do know the + ;; full path, but we cannot really know 'drafts folder'... we make a + ;; guess (setq draft-dir (mu4e~guess-maildir (mu4e-message-field msg :path))) (mu4e~draft-open-file (mu4e-message-field msg :path))) @@ -442,9 +460,9 @@ will be created from either `mu4e~draft-reply-construct', or (let ((draft-path (mu4e~draft-determine-path draft-dir))) (copy-file (mu4e-message-field msg :path) draft-path) (mu4e~draft-open-file draft-path))) - + ((reply forward new) - ;; case-3: creating a new message; in this case, we can determing + ;; case-3: creating a new message; in this case, we can determine ;; mu4e-get-drafts-folder (setq draft-dir (mu4e-get-drafts-folder msg)) (let ((draft-path (mu4e~draft-determine-path draft-dir)) @@ -454,7 +472,7 @@ will be created from either `mu4e~draft-reply-construct', or (forward (mu4e~draft-forward-construct msg)) (new (mu4e~draft-newmsg-construct))))) (mu4e~draft-open-file draft-path) - (insert initial-contents) + (insert initial-contents) (newline) ;; include the message signature (if it's set) (if (and mu4e-compose-signature-auto-include mu4e-compose-signature) @@ -463,12 +481,15 @@ will be created from either `mu4e~draft-reply-construct', or (message-insert-signature) (mu4e~fontify-signature)))))) (t (mu4e-error "unsupported compose-type %S" compose-type))) - ;; evaluate mu4e~drafts-drafts-folder once, here, and use that value - ;; throughout. + ;; if we didn't find a draft folder yet, try some default + (unless draft-dir + (setq draft-dir (mu4e-get-drafts-folder msg))) + ;; evaluate mu4e~drafts-drafts-folder once, here, and use that value + ;; throughout. (set (make-local-variable 'mu4e~draft-drafts-folder) draft-dir) (put 'mu4e~draft-drafts-folder 'permanent-local t) (unless mu4e~draft-drafts-folder (mu4e-error "failed to determine drafts folder")))) - + (provide 'mu4e-draft) diff --git a/_spacemacs.d/local/mu4e/mu4e-headers.el b/_spacemacs.d/local/mu4e/mu4e-headers.el index f45d7b4..e137c02 100644 --- a/_spacemacs.d/local/mu4e/mu4e-headers.el +++ b/_spacemacs.d/local/mu4e/mu4e-headers.el @@ -135,6 +135,21 @@ sent messages into message threads." :type 'boolean :group 'mu4e-headers) + +(defvar mu4e-headers-hide-predicate nil + "Predicate function applied to headers before they are shown; +if function is nil or evaluates to nil, show the header, +otherwise don't. function takes one parameter MSG, which is the +message plist for the message to be hidden or not. + +Example that hides all 'trashed' messages: + (setq mu4e-headers-hide-predicate + (lambda (msg) + (member 'trashed (mu4e-message-field msg :flags)))) + +Note that this is merely a display filter.") + + (defcustom mu4e-headers-visible-flags '(draft flagged new passed replied seen trashed attach encrypted signed unread) "An ordered list of flags to show in the headers buffer. Each @@ -215,7 +230,7 @@ Field must be a symbol, one of: :date, :subject, :size, :prio, (defvar mu4e-headers-default-prefix '("|" . "│ ") "Default.") (defvar mu4e-headers-actions - '( ("capture message" . mu4e-action-capture-message) + '( ("capture message" . mu4e-action-capture-message) ("show this thread" . mu4e-action-show-thread)) "List of actions to perform on messages in the headers list. The actions are of the form (NAME SHORTCUT FUNC) where: @@ -311,22 +326,23 @@ headers." (when (buffer-live-p mu4e~headers-buffer) (with-current-buffer mu4e~headers-buffer (let* ((docid (mu4e-message-field msg :docid)) - (initial-message-at-point (mu4e~headers-docid-at-point)) - (initial-column (current-column)) - (point (mu4e~headers-docid-pos docid))) + (initial-message-at-point (mu4e~headers-docid-at-point)) + (initial-column (current-column)) + (point (mu4e~headers-docid-pos docid))) + (when point ;; is the message present in this list? ;; if it's marked, unmark it now (when (mu4e-mark-docid-marked-p docid) (mu4e-mark-set 'unmark)) - ;; re-use the thread info from the old one; this is needed because - ;; *update* messages don't have thread info by themselves (unlike - ;; search results) + ;; re-use the thread info from the old one; this is needed because + ;; *update* messages don't have thread info by themselves (unlike + ;; search results) ;; since we still have the search results, re-use - ;; those - (plist-put msg :thread - (mu4e~headers-field-for-docid docid :thread)) + ;; those + (plist-put msg :thread + (mu4e~headers-field-for-docid docid :thread)) ;; first, remove the old one (otherwise, we'd have two headers with ;; the same docid... @@ -337,11 +353,10 @@ headers." ;; (which is useful for viewing the raw message) (when (mu4e~headers-view-this-message-p docid) (mu4e-view msg mu4e~headers-buffer)) - ;; now, if this update was about *moving* a message, we don't show it ;; anymore (of course, we cannot be sure if the message really no - ;; longer matches the query, but this seem a good heuristic. - ;; if it was only a flag-change, show the message with its updated flags. + ;; longer matches the query, but this seem a good heuristic. if it + ;; was only a flag-change, show the message with its updated flags. (unless is-move (mu4e~headers-header-handler msg point)) @@ -351,8 +366,7 @@ headers." (move-to-column initial-column) (mu4e~headers-highlight initial-message-at-point)) ;; attempt to highlight the corresponding line and make it visible - (mu4e~headers-highlight docid)) - ))))) + (mu4e~headers-highlight docid))))))) (defun mu4e~headers-remove-handler (docid) "Remove handler, will be called when a message with DOCID has @@ -382,7 +396,7 @@ into a string." (let ((name (car ct)) (email (cdr ct))) (or name email "?"))) contacts ", ")) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defsubst mu4e~headers-thread-prefix (thread) "Calculate the thread prefix based on thread info THREAD." (when thread @@ -430,7 +444,7 @@ while our display may be different)." ('signed (funcall get-prefix mu4e-headers-signed-mark)) ('unread (funcall get-prefix mu4e-headers-unread-mark))))))) str)) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defconst mu4e-headers-from-or-to-prefix '("" . "To ") @@ -493,7 +507,8 @@ found." (let* ((item (or (assoc field mu4e-header-info-custom) (mu4e-error "field %S not found" field))) (func (or (plist-get (cdr-safe item) :function) - (mu4e-error "no :function defined for field %S %S" field (cdr item))))) + (mu4e-error "no :function defined for field %S %S" + field (cdr item))))) (funcall func msg))) (defun mu4e~headers-field-apply-basic-properties (msg field val width) @@ -571,12 +586,14 @@ found." (defun mu4e~headers-header-handler (msg &optional point) "Create a one line description of MSG in this buffer, at POINT, if provided, or at the end of the buffer otherwise." - (let ((docid (mu4e-message-field msg :docid)) - (line (mapconcat (lambda (f-w) - (mu4e~headers-field-handler f-w msg)) - mu4e-headers-fields " "))) - (setq line (mu4e~headers-line-handler msg line)) - (mu4e~headers-add-header line docid point msg))) + (unless (and mu4e-headers-hide-predicate + (funcall mu4e-headers-hide-predicate msg)) + (let ((docid (mu4e-message-field msg :docid)) + (line (mapconcat (lambda (f-w) + (mu4e~headers-field-handler f-w msg)) + mu4e-headers-fields " "))) + (setq line (mu4e~headers-line-handler msg line)) + (mu4e~headers-add-header line docid point msg)))) (defconst mu4e~no-matches "No matching messages found") (defconst mu4e~end-of-results "End of search results") @@ -598,14 +615,15 @@ after the end of the search results." (goto-char (point-min)) (when mu4e~headers-msgid-target (mu4e-headers-goto-message-id mu4e~headers-msgid-target)) - (when mu4e~headers-view-target - (mu4e-headers-view-message)) ;; view the message at point + (when (and mu4e~headers-view-target (mu4e-message-at-point 'noerror)) + ;; view the message at point when there is one. + (mu4e-headers-view-message)) (setq mu4e~headers-view-target nil mu4e~headers-msgid-target nil)) (when (mu4e~headers-docid-at-point) (mu4e~headers-highlight (mu4e~headers-docid-at-point))) ;; run-hooks - (run-hooks 'mu4e-headers-found-hook))) + (run-hooks 'mu4e-headers-found-hook))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -679,7 +697,7 @@ after the end of the search results." (define-key map (kbd "[") 'mu4e-headers-prev-unread) (define-key map (kbd "]") 'mu4e-headers-next-unread) - + ;; change the number of headers (define-key map (kbd "C-+") 'mu4e-headers-split-view-grow) (define-key map (kbd "C--") 'mu4e-headers-split-view-shrink) @@ -687,7 +705,7 @@ after the end of the search results." (define-key map (kbd "") 'mu4e-headers-split-view-shrink) (define-key map ";" 'mu4e-context-switch) - + ;; switching to view mode (if it's visible) (define-key map "y" 'mu4e-select-other-view) @@ -748,20 +766,24 @@ after the end of the search results." (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)))) + '(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-headers-show-threads) - mu4e-headers-show-threads)))) + :button (:toggle . + (and (boundp 'mu4e-headers-show-threads) + mu4e-headers-show-threads)))) (define-key menumap [sepa1] '("--")) (define-key menumap [execute-marks] '("Execute marks" . mu4e-mark-execute-all)) (define-key menumap [unmark-all] '("Unmark all" . mu4e-mark-unmark-all)) - (define-key menumap [unmark] '("Unmark" . mu4e-headers-mark-for-unmark)) + (define-key menumap [unmark] + '("Unmark" . mu4e-headers-mark-for-unmark)) (define-key menumap [mark-pattern] '("Mark pattern" . mu4e-headers-mark-pattern)) @@ -783,11 +805,12 @@ after the end of the search results." (define-key menumap [forward] '("Forward" . mu4e-compose-forward)) (define-key menumap [reply] '("Reply" . mu4e-compose-reply)) (define-key menumap [compose-new] '("Compose new" . mu4e-compose-new)) - - + + (define-key menumap [sepa3] '("--")) - (define-key menumap [query-next] '("Next query" . mu4e-headers-query-next)) + (define-key menumap [query-next] + '("Next query" . mu4e-headers-query-next)) (define-key menumap [query-prev] '("Previous query" . mu4e-headers-query-prev)) (define-key menumap [narrow-search] '("Narrow search" . @@ -979,7 +1002,7 @@ message plist, or nil if not found." (let ((this-msgid (mu4e-message-field msg :message-id))) (when (and this-msgid (string= msgid this-msgid)) msg))))) - + ;;;; markers mark headers for (defun mu4e~headers-mark (docid mark) "(Visually) mark the header for DOCID with character MARK." @@ -1062,7 +1085,7 @@ the query history stack." 'face 'mu4e-modeline-face) " " (mu4e-context-label))))) - + (switch-to-buffer buf) (run-hook-with-args 'mu4e-headers-search-hook expr) (mu4e~proc-find @@ -1229,7 +1252,7 @@ descendants." (last-marked-point)) (mu4e-headers-for-each (lambda (mymsg) - (let ((my-thread-id (mu4e~headers-get-thread-info mymsg 'thread-id))) + (let ((my-thread-id (mu4e~headers-get-thread-info mymsg 'thread-id))) (if subthread ;; subthread matching; mymsg's thread path should have path as its ;; prefix @@ -1375,8 +1398,8 @@ the last search expression. Note that you can go back to previous query (effectively, 'widen' it), with `mu4e-headers-query-prev'." (interactive (let ((filter - (read-string (mu4e-format "Narrow down to: ") - nil 'mu4e~headers-search-hist nil t))) + (read-string (mu4e-format "Narrow down to: ") + nil 'mu4e~headers-search-hist nil t))) (list filter))) (unless mu4e~headers-last-query (mu4e-warn "There's nothing to filter")) @@ -1586,7 +1609,7 @@ untrashed). If BACKWARDS is non-`nil', move backwards." (interactive) (or (mu4e-headers-find-if-next (lambda (msg) - (let ((flags (mu4e-message-field msg :flags))) + (let ((flags (mu4e-message-field msg :flags))) (and (member 'unread flags) (not (member 'trashed flags))))) backwards) (mu4e-message (format "No %s unread message found" diff --git a/_spacemacs.d/local/mu4e/mu4e-main.el b/_spacemacs.d/local/mu4e/mu4e-main.el index 0f4dc78..a647a2d 100644 --- a/_spacemacs.d/local/mu4e/mu4e-main.el +++ b/_spacemacs.d/local/mu4e/mu4e-main.el @@ -137,11 +137,11 @@ clicked." ;; TODO: it's a bit uncool to hard-code the "b" shortcut... (mapconcat (lambda (bm) - (let* ((query (nth 0 bm)) (title (nth 1 bm)) (key (nth 2 bm))) - (mu4e~main-action-str - (concat "\t* [b" (make-string 1 key) "] " title) - (concat "b" (make-string 1 key))))) - mu4e-bookmarks "\n") + (mu4e~main-action-str + (concat "\t* [b" (make-string 1 (mu4e-bookmark-key bm)) "] " + (mu4e-bookmark-name bm)) + (concat "b" (make-string 1 (mu4e-bookmark-key bm))))) + (mu4e-bookmarks) "\n") "\n\n" (propertize " Misc\n\n" 'face 'mu4e-title-face) diff --git a/_spacemacs.d/local/mu4e/mu4e-proc.el b/_spacemacs.d/local/mu4e/mu4e-proc.el index d93af5d..d6d90e1 100644 --- a/_spacemacs.d/local/mu4e/mu4e-proc.el +++ b/_spacemacs.d/local/mu4e/mu4e-proc.el @@ -401,14 +401,15 @@ or (:error ) sexp, which are handled my `mu4e-update-func' and idparam (or flagstr "") (or path "") (format "newname:%s" rename)))) -(defun mu4e~proc-index (path my-addresses) +(defun mu4e~proc-index (path my-addresses cleanup lazy-check) "Update the message database for filesystem PATH, which should point to some maildir directory structure. MY-ADDRESSES is a list of 'my' email addresses (see `mu4e-user-mail-address-list')." (let ((path (mu4e~proc-escape path)) (addrs (when my-addresses (mapconcat 'identity my-addresses ",")))) (if addrs - (mu4e~proc-send-command "cmd:index path:%s my-addresses:%s" path addrs) + (mu4e~proc-send-command "cmd:index path:%s my-addresses:%s cleanup:%s lazy-check:%s" + path addrs (if cleanup "true" : "false") (if lazy-check "true")) (mu4e~proc-send-command "cmd:index path:%s" path)))) (defun mu4e~proc-add (path maildir) diff --git a/_spacemacs.d/local/mu4e/mu4e-speedbar.el b/_spacemacs.d/local/mu4e/mu4e-speedbar.el index b359511..09a4c49 100644 --- a/_spacemacs.d/local/mu4e/mu4e-speedbar.el +++ b/_spacemacs.d/local/mu4e/mu4e-speedbar.el @@ -34,6 +34,7 @@ (require 'speedbar) (require 'mu4e-vars) (require 'mu4e-headers) +(require 'mu4e-utils) (defvar mu4e-main-speedbar-key-map nil "Keymap used when in mu4e display mode.") @@ -90,12 +91,12 @@ (interactive) (mapcar (lambda (bookmark) (speedbar-insert-button - (concat " " (nth 1 bookmark)) + (concat " " (mu4e-bookmark-name bookmark)) 'mu4e-highlight-face 'highlight 'mu4e~speedbar-bookmark - (nth 0 bookmark))) - mu4e-bookmarks)) + (mu4e-bookmark-query bookmark))) + (mu4e-bookmarks))) (defun mu4e~speedbar-bookmark (&optional text token ident) "Run bookmarked query TOKEN. TEXT and INDENT are not used." diff --git a/_spacemacs.d/local/mu4e/mu4e-utils.el b/_spacemacs.d/local/mu4e/mu4e-utils.el index a969c44..f8110b5 100644 --- a/_spacemacs.d/local/mu4e/mu4e-utils.el +++ b/_spacemacs.d/local/mu4e/mu4e-utils.el @@ -396,46 +396,80 @@ and offer to create it if it does not exist yet." (mu4e~proc-mkdir fullpath))) mdir)) + +(defstruct mu4e-bookmark + "A mu4e bookmarl object with the following members: +- `name': the user-visible name of the bookmark +- `key': a single key to search for this bookmark +- `query': the query for this bookmark. Either a literal string or a function + that evaluates to a string." + name ;; name/description of the bookmark + query ;; a query (a string or a function evaluation to string) + key ;; key to activate the bookmark + ) + +(defun mu4e-bookmarks () + "Get `mu4e-bookmarks' in the (new) format, converting from the old +format if needed." + (map 'list + (lambda (item) + (if (mu4e-bookmark-p item) + item ;; already in the right format + (if (and (listp item) (= (length item) 3)) + (make-mu4e-bookmark + :name (nth 1 item) + :query (nth 0 item) + :key (nth 2 item)) + (mu4e-error "Invalid bookmark in mu4e-bookmarks")))) + mu4e-bookmarks)) + + (defun mu4e-ask-bookmark (prompt &optional kar) "Ask the user for a bookmark (using PROMPT) as defined in `mu4e-bookmarks', then return the corresponding query." - (unless mu4e-bookmarks (mu4e-error "No bookmarks defined")) + (unless (mu4e-bookmarks) (mu4e-error "No bookmarks defined")) (let* ((prompt (mu4e-format "%s" prompt)) (bmarks (mapconcat (lambda (bm) - (let ((query (nth 0 bm)) (title (nth 1 bm)) (key (nth 2 bm))) - (concat - "[" (propertize (make-string 1 key) - 'face 'mu4e-highlight-face) - "]" - title))) mu4e-bookmarks ", ")) - (kar (read-char (concat prompt bmarks)))) + (concat + "[" (propertize (make-string 1 (mu4e-bookmark-key bm)) + 'face 'mu4e-highlight-face) + "]" + (mu4e-bookmark-name bm))) (mu4e-bookmarks) ", ")) + (kar (read-char (concat prompt bmarks)))) (mu4e-get-bookmark-query kar))) - (defun mu4e-get-bookmark-query (kar) "Get the corresponding bookmarked query for shortcut character KAR, or raise an error if none is found." (let* ((chosen-bm (or (find-if (lambda (bm) - (= kar (nth 2 bm))) - mu4e-bookmarks) + (= kar (mu4e-bookmark-key bm))) + (mu4e-bookmarks)) (mu4e-warn "Unknown shortcut '%c'" kar))) - (expr (nth 0 chosen-bm)) + (expr (mu4e-bookmark-query chosen-bm)) (query (eval expr))) (if (stringp query) query (mu4e-warn "Expression must evaluate to query string ('%S')" expr)))) -(defun mu4e-bookmark-define (query descr key) - "Define a bookmark for QUERY with description DESCR and short -character KEY in the list of `mu4e-bookmarks'. This replaces any -existing bookmark with KEY." - (setq mu4e-bookmarks (remove-if (lambda (bm) (= (nth 2 bm) key)) mu4e-bookmarks)) - (add-to-list 'mu4e-bookmarks (list query descr key) t)) +(defun mu4e-bookmark-define (query name key) + "Define a bookmark for QUERY with name NAME and +shortcut-character KEY in the list of `mu4e-bookmarks'. This +replaces any existing bookmark with KEY." + (setq mu4e-bookmarks + (remove-if + (lambda (bm) + (= (mu4e-bookmark-key bm) key)) + (mu4e-bookmarks))) + (add-to-list 'mu4e-bookmarks + (make-mu4e-bookmark + :name name + :query query + :key key) t)) ;;; converting flags->string and vice-versa ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -834,7 +868,8 @@ successful, call FUNC (if non-nil) afterwards." (setq mu4e~update-timer (run-at-time 0 mu4e-update-interval - (lambda () (mu4e-update-mail-and-index mu4e-index-update-in-background))))) + (lambda () (mu4e-update-mail-and-index + mu4e-index-update-in-background))))) (mu4e-message "Started mu4e with %d message%s in store" doccount (if (= doccount 1) "" "s")))))) ;; wake up server @@ -894,7 +929,11 @@ Also scrolls to the final line, and update the progress throbber." ;; Insert at end of buffer. Leave point alone. (with-current-buffer (process-buffer proc) (goto-char (point-max)) - (insert msg)) + (if (string-match ".*\r\\(.*\\)" msg) + (progn + (kill-line 0) + (insert (match-string 1 msg))) + (insert msg))) ;; Auto-scroll unless user is interacting with the window. (when (and (window-live-p procwin) (not (eq (selected-window) procwin))) @@ -906,7 +945,10 @@ Also scrolls to the final line, and update the progress throbber." (interactive) (unless mu4e-maildir (mu4e-error "`mu4e-maildir' is not defined")) - (mu4e~proc-index mu4e-maildir mu4e-user-mail-address-list)) + (mu4e~proc-index mu4e-maildir + mu4e-user-mail-address-list + mu4e-index-cleanup + mu4e-index-lazy-check)) (defvar mu4e~update-buffer nil "Internal, store the buffer of the update process when @@ -1211,7 +1253,7 @@ used in the view and compose modes." (when (search-forward-regexp "^\n" nil t) ;; search the first empty line (while (re-search-forward mu4e-cited-regexp nil t) (let* ((level (string-width (replace-regexp-in-string - " " "" (match-string 1)))) + "[^>]" "" (match-string 0)))) (face (unless (zerop level) (intern-soft (format "mu4e-cited-%d-face" level))))) (when face diff --git a/_spacemacs.d/local/mu4e/mu4e-vars.el b/_spacemacs.d/local/mu4e/mu4e-vars.el index 94c3a86..e07b196 100644 --- a/_spacemacs.d/local/mu4e/mu4e-vars.el +++ b/_spacemacs.d/local/mu4e/mu4e-vars.el @@ -90,6 +90,27 @@ background." :group 'mu4e :safe 'booleanp) +(defcustom mu4e-index-cleanup t + "Whether to run a cleanup face after indexing -- that is, see +if the is a message in the filesystem for each file in the +message store. Having this option as `t' ensures that no +non-existing mesages are shown but can also be quite slow with +large message stores." + :type 'boolean + :group 'mu4e + :safe 'booleanp) + +(defcustom mu4e-index-lazy-check nil + "Whether to run do a 'lazy check' for deciding whether to +indexing a message. When this is set to `t', mu only uses the +directory timestamps to decide on whether it needs to check the +messages beneath it, which would miss messages that are modified +outside mu. On the other hand, it's significantly faster." + :type 'boolean + :group 'mu4e + :safe 'booleanp) + + (defcustom mu4e-update-interval nil "Number of seconds between automatic calls to retrieve mail and update the database. If nil, don't update automatically. Note, @@ -105,9 +126,11 @@ mu4e." You can use this hook for example to `mu4e-get-mail-command' with some specific setting.") -(defvar mu4e-hide-index-messages nil - "If non-nil, mu4e does not show the \"Indexing...\" messages, or - any messages relating to updated contacts.") +(defcustom mu4e-hide-index-messages nil + "Whether to hide the \"Indexing...\" messages, or any messages +relating to updated contacts." + :type 'boolean + :group 'mu4e) (defcustom mu4e-change-filenames-when-moving nil "When moving messages to different folders, normally mu/mu4e keep @@ -177,6 +200,33 @@ is a shortcut key for the query." character)) :group 'mu4e) +(defvar mu4e-bookmarks + `( ,(make-mu4e-bookmark + :name "Unread messages" + :query "flag:unread AND NOT flag:trashed" + :key ?u) + ,(make-mu4e-bookmark + :name "Today's messages" + :query "date:today..now" + :key ?t) + ,(make-mu4e-bookmark + :name "Last 7 days" + :query "date:7d..now" + :key ?w) + ,(make-mu4e-bookmark + :name "Messages with images" + :query "mime:image/*" + :key ?p)) + "A list of pre-defined queries. Each query is represented by a +mu4e-bookmark structure with parameters @t{:name} with the name +of the bookmark, @t{:query} with the query expression (a query +string or an s-expression that evaluates to query string) and a +@t{:key}, which is the shortcut-key for the query. + +An older form of bookmark, a 3-item list with (QUERY DESCRIPTION +KEY) is still recognized as well, for backward-compatibility.") + + (defcustom mu4e-split-view 'horizontal "How to show messages / headers. A symbol which is either: @@ -205,8 +255,10 @@ view buffer." :type 'boolean :group 'mu4e) -(defcustom mu4e-cited-regexp "^ *\\(\\(>+ ?\\)+\\)" - "Regular expression that determines whether a line is a citation." +(defcustom mu4e-cited-regexp "^\\(\\([[:alpha:]]+\\)\\|\\( *\\)\\)\\(\\(>+ ?\\)+\\)" + "Regular expression that determines whether a line is a + citation. This recognizes lines starting with numbers of '>' + and spaces as well as citations of the type \"John> ... \"." :type 'string :group 'mu4e) @@ -502,12 +554,12 @@ I.e. a message with the draft flag set." :group 'mu4e-faces) (defface mu4e-header-value-face - '((t :inherit font-lock-doc-face)) + '((t :inherit font-lock-type-face)) "Face for a header value (such as \"Re: Hello!\")." :group 'mu4e-faces) (defface mu4e-special-header-value-face - '((t :inherit font-lock-variable-name-face)) + '((t :inherit font-lock-builtin-face)) "Face for special header values." :group 'mu4e-faces) @@ -562,7 +614,7 @@ I.e. a message with the draft flag set." :group 'mu4e-faces) (defface mu4e-cited-2-face - '((t :inherit font-lock-type-face :bold nil :italic t)) + '((t :inherit font-lock-preprocessor-face :bold nil :italic t)) "Face for cited message parts (level 2)." :group 'mu4e-faces) @@ -587,7 +639,7 @@ I.e. a message with the draft flag set." :group 'mu4e-faces) (defface mu4e-cited-7-face - '((t :inherit font-lock-preprocessor-face :bold nil :italic t)) + '((t :inherit font-lock-type-face :bold nil :italic t)) "Face for cited message parts (level 7)." :group 'mu4e-faces) @@ -719,6 +771,11 @@ mu4e-compose-mode." ( :name "To" :shortname "To" :help "Recipient of the message" + :sortable t)) + (:user-agent . + ( :name "User-Agent" + :shortname "UA" + :help "Program used for writing this message" :sortable t))) "An alist of all possible header fields and information about them. This is used in the user-interface (the column headers in the header list, and diff --git a/_spacemacs.d/local/mu4e/mu4e-view.el b/_spacemacs.d/local/mu4e/mu4e-view.el index 75fc79f..564835d 100644 --- a/_spacemacs.d/local/mu4e/mu4e-view.el +++ b/_spacemacs.d/local/mu4e/mu4e-view.el @@ -203,9 +203,10 @@ found." (lambda (field) (let ((fieldval (mu4e-message-field msg field))) (case field - (:subject (mu4e~view-construct-header field fieldval)) - (:path (mu4e~view-construct-header field fieldval)) - (:maildir (mu4e~view-construct-header field fieldval)) + (:subject (mu4e~view-construct-header field fieldval)) + (:path (mu4e~view-construct-header field fieldval)) + (:maildir (mu4e~view-construct-header field fieldval)) + (:user-agent (mu4e~view-construct-header field fieldval)) ((:flags :tags) (mu4e~view-construct-flags-tags-header field fieldval)) diff --git a/_spacemacs.d/local/mu4e/mu4e.el b/_spacemacs.d/local/mu4e/mu4e.el index fd01875..b605cb9 100644 --- a/_spacemacs.d/local/mu4e/mu4e.el +++ b/_spacemacs.d/local/mu4e/mu4e.el @@ -38,6 +38,15 @@ (require 'mu4e-context) ;; support for contexts (require 'mu4e-speedbar) ;; support for speedbar + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; we can't properly use compose buffers that are revived using +;; desktop-save-mode; so let's turn that off +(require 'desktop) +(add-to-list 'desktop-modes-not-to-save 'mu4e-compose-mode) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; register our handler functions; these connect server messages to functions diff --git a/_spacemacs.d/local/mu4e/org-mu4e.el b/_spacemacs.d/local/mu4e/org-mu4e.el index b9e9688..545f566 100644 --- a/_spacemacs.d/local/mu4e/org-mu4e.el +++ b/_spacemacs.d/local/mu4e/org-mu4e.el @@ -192,8 +192,6 @@ and images in a multipart/related part." "Convert the current body to html." (unless (fboundp 'org-export-string-as) (mu4e-error "require function 'org-export-string-as not found.")) - (unless (executable-find "dvipng") - (mu4e-error "Required program dvipng not found")) (let* ((begin (save-excursion (goto-char (point-min)) @@ -209,7 +207,9 @@ and images in a multipart/related part." ;; makes the replies with ">"s look nicer (org-export-preserve-breaks t) ;; dvipng for inline latex because MathJax doesn't work in mail - (org-export-with-LaTeX-fragments 'dvipng) + (org-export-with-LaTeX-fragments + (if (executable-find "dvipng") 'dvipng + (mu4e-message "Cannot find dvipng, ignore inline LaTeX") nil)) ;; to hold attachments for inline html images (html-and-images (org~mu4e-mime-replace-images -- cgit v1.2.2