aboutsummaryrefslogtreecommitdiffstats
path: root/_spacemacs.d/local/mu4e/mu4e-compose.el
diff options
context:
space:
mode:
authorAaron LI <aaronly.me@outlook.com>2016-08-02 22:49:19 +0800
committerAaron LI <aaronly.me@outlook.com>2016-08-02 22:49:19 +0800
commit6814250a0c95e0849c191e7f5fe8e2a8bee31440 (patch)
treee48ff0faa822b1bb7f0d626d58732f40b6b97e8b /_spacemacs.d/local/mu4e/mu4e-compose.el
parent98083f04530335e8f98589373ecfad8948b86ae8 (diff)
downloaddotfiles-6814250a0c95e0849c191e7f5fe8e2a8bee31440.tar.bz2
spacemacs: update mu/mu4e to git20160802
Diffstat (limited to '_spacemacs.d/local/mu4e/mu4e-compose.el')
-rw-r--r--_spacemacs.d/local/mu4e/mu4e-compose.el179
1 files changed, 120 insertions, 59 deletions
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))