aboutsummaryrefslogtreecommitdiffstats
path: root/_spacemacs.d/local/mu4e/mu4e-draft.el
diff options
context:
space:
mode:
authorAaron LI <aaronly.me@outlook.com>2016-12-04 18:48:12 +0800
committerAaron LI <aaronly.me@outlook.com>2016-12-04 18:48:12 +0800
commitdd08c1a07c5311570fc47e07909ffa8d196f365b (patch)
tree2b1b610d2ee3be4facf34f9493f5dec8f1d966bb /_spacemacs.d/local/mu4e/mu4e-draft.el
parentde6be2b383668de5011c38491227fbf91da0c06c (diff)
downloaddotfiles-dd08c1a07c5311570fc47e07909ffa8d196f365b.tar.bz2
_spacemacs: Do not track "mu4e" package
Diffstat (limited to '_spacemacs.d/local/mu4e/mu4e-draft.el')
-rw-r--r--_spacemacs.d/local/mu4e/mu4e-draft.el495
1 files changed, 0 insertions, 495 deletions
diff --git a/_spacemacs.d/local/mu4e/mu4e-draft.el b/_spacemacs.d/local/mu4e/mu4e-draft.el
deleted file mode 100644
index d7df6e0..0000000
--- a/_spacemacs.d/local/mu4e/mu4e-draft.el
+++ /dev/null
@@ -1,495 +0,0 @@
-;; mu4e-draft.el -- part of mu4e, the mu mail user agent for emacs
-;;
-;; Copyright (C) 2011-2016 Dirk-Jan C. Binnema
-
-;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
-;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
-
-;; This file is not part of GNU Emacs.
-;;
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; In this file, various functions to create draft messages
-
-;; Code
-
-(eval-when-compile (byte-compile-disable-warning 'cl-functions))
-(require 'cl)
-
-(require 'mu4e-vars)
-(require 'mu4e-utils)
-(require 'mu4e-message)
-(require 'message) ;; mail-header-separator
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defcustom mu4e-compose-dont-reply-to-self nil
- "If non-nil, don't include self (that is, any member of
-`mu4e-user-mail-address-list') in replies."
- :type 'boolean
- :group 'mu4e-compose)
-
-(defcustom mu4e-compose-cite-function
- (or message-cite-function 'message-cite-original-without-signature)
- "The function to use to cite message in replies and forwarded
-messages. This is the mu4e-specific version of
-`message-cite-function'."
- :type 'function
- :group 'mu4e-compose)
-
-(defcustom mu4e-compose-signature
- (or message-signature "Sent with my mu4e")
- "The message signature (i.e. the blob at the bottom of
-messages). This is the mu4e-specific version of
-`message-signature'."
- :group 'mu4e-compose)
-
-(defcustom mu4e-compose-signature-auto-include t
- "Whether to automatically include a message-signature in new
-messages (if it is set)."
- :type 'boolean
- :group 'mu4e-compose)
-
-(defcustom mu4e-compose-auto-include-date nil
- "Whether to include a date header when starting to draft a
-message; if nil, only do so when sending the message."
- :type 'boolean
- :group 'mu4e-compose)
-
-(defcustom mu4e-compose-in-new-frame nil
- "Whether to compose messages in a new frame instead of the
-current window."
- :type 'boolean
- :group 'mu4e-compose)
-
-(defvar mu4e-user-agent-string
- (format "mu4e %s; emacs %s" mu4e-mu-version emacs-version)
- "The User-Agent string for mu4e.")
-
-(defun mu4e~draft-cite-original (msg)
- "Return a cited version of the original message MSG as a plist.
-This function uses `mu4e-compose-cite-function', and as such all
-its settings apply."
- (with-temp-buffer
- (when (fboundp 'mu4e-view-message-text) ;; keep bytecompiler happy
- (let ((mu4e-view-date-format "%Y-%m-%dT%T%z"))
- (insert (mu4e-view-message-text msg)))
- (message-yank-original)
- (goto-char (point-min))
- (push-mark (point-max))
- ;; set the the signature separator to 'loose', since in the real world,
- ;; many message don't follow the standard...
- (let ((message-signature-separator "^-- *$")
- (message-signature-insert-empty-line t))
- (funcall mu4e-compose-cite-function))
- (pop-mark)
- (goto-char (point-min))
- (buffer-string))))
-
-(defun mu4e~draft-header (hdr val)
- "Return a header line of the form \"HDR: VAL\".
-If VAL is nil, return nil."
- ;; note: the propertize here is currently useless, since gnus sets its own
- ;; later.
- (when val (format "%s: %s\n"
- (propertize hdr 'face 'mu4e-header-key-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
-comma-separated string. Normally, this the concatenation of the
-existing References + In-Reply-To (which may be empty, an note
-that :references includes the old in-reply-to as well) and the
-message-id. If the message-id is empty, returns the old
-References. If both are empty, return nil."
- (let* ( ;; these are the ones from the message being replied to / forwarded
- (refs (mu4e-message-field msg :references))
- (msgid (mu4e-message-field msg :message-id))
- ;; now, append in
- (refs (if (and msgid (not (string= msgid "")))
- (append refs (list msgid)) refs))
- ;; no doubles
- (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
-
-(defun mu4e~draft-recipients-list-to-string (lst)
- "Convert a lst LST of address cells into a string with a list of
-e-mail addresses. If LST is nil, returns nil."
- (when lst
- (mapconcat
- (lambda (addrcell)
- (let ((name (car addrcell))
- (email (cdr addrcell)))
- (if name
- (format "%s <%s>" (mu4e~rfc822-quoteit name) email)
- (format "%s" email))))
- lst ", ")))
-
-(defun mu4e~draft-address-cell-equal (cell1 cell2)
- "Return t if CELL1 and CELL2 have the same e-mail address.
-The comparison is done case-insensitively. If the cells done
-match return nil. CELL1 and CELL2 are cons cells of the
-form (NAME . EMAIL)."
- (string=
- (downcase (or (cdr cell1) ""))
- (downcase (or (cdr cell2) ""))))
-
-
-(defun mu4e~draft-create-to-lst (origmsg)
- "Create a list of address for the To: in a new message, based on
-the original message ORIGMSG. If the Reply-To address is set, use
-that, otherwise use the From address. Note, whatever was in the To:
-field before, goes to the Cc:-list (if we're doing a reply-to-all).
-Special case: if we were the sender of the original, we simple copy
-the list form the original."
- (let ((reply-to
- (or (plist-get origmsg :reply-to) (plist-get origmsg :from))))
- (delete-duplicates reply-to :test #'mu4e~draft-address-cell-equal)
- (if mu4e-compose-dont-reply-to-self
- (delete-if
- (lambda (to-cell)
- (member-if
- (lambda (addr)
- (string= (downcase addr) (downcase (cdr to-cell))))
- mu4e-user-mail-address-list))
- reply-to)
- reply-to)))
-
-
-(defun mu4e~draft-create-cc-lst (origmsg reply-all)
- "Create a list of address for the Cc: in a new message, based on
-the original message ORIGMSG, and whether it's a reply-all."
- (when reply-all
- (let* ((cc-lst ;; get the cc-field from the original, remove dups
- (delete-duplicates
- (append
- (plist-get origmsg :to)
- (plist-get origmsg :cc))
- :test #'mu4e~draft-address-cell-equal))
- ;; now we have the basic list, but we must remove
- ;; addresses also in the to list
- (cc-lst
- (delete-if
- (lambda (cc-cell)
- (find-if
- (lambda (to-cell)
- (mu4e~draft-address-cell-equal cc-cell to-cell))
- (mu4e~draft-create-to-lst origmsg)))
- cc-lst))
- ;; finally, we need to remove ourselves from the cc-list
- ;; unless mu4e-compose-keep-self-cc is non-nil
- (cc-lst
- (if (or mu4e-compose-keep-self-cc (null user-mail-address))
- cc-lst
- (delete-if
- (lambda (cc-cell)
- (member-if
- (lambda (addr)
- (string= (downcase addr) (downcase (cdr cc-cell))))
- mu4e-user-mail-address-list))
- cc-lst))))
- cc-lst)))
-
-(defun mu4e~draft-recipients-construct (field origmsg &optional reply-all)
- "Create value (a string) for the recipient field FIELD (a
-symbol, :to or :cc), based on the original message ORIGMSG,
-and (optionally) REPLY-ALL which indicates this is a reply-to-all
-message. Return nil if there are no recipients for the particular field."
- (mu4e~draft-recipients-list-to-string
- (case field
- (:to
- (mu4e~draft-create-to-lst origmsg))
- (:cc
- (mu4e~draft-create-cc-lst origmsg reply-all))
- (otherwise
- (mu4e-error "Unsupported field")))))
-
-
-(defun mu4e~draft-from-construct ()
- "Construct a value for the From:-field of the reply to MSG,
-based on `user-full-name' and `user-mail-address'; if the latter is
-nil, function returns nil."
- (when user-mail-address
- (if user-full-name
- (format "%s <%s>" (mu4e~rfc822-quoteit user-full-name) user-mail-address)
- (format "%s" user-mail-address))))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun mu4e~draft-insert-mail-header-separator ()
- "Insert `mail-header-separator' in the first empty line of the message.
-`message-mode' needs this line to know where the headers end and
-the body starts. Note, in `mu4e-compose-mode', we use
-`before-save-hook' and `after-save-hook' to ensure that this
-separator is never written to the message file. Also see
-`mu4e-remove-mail-header-separator'."
- ;; we set this here explicitly, since (as it has happened) a wrong
- ;; value for this (such as "") breaks address completion and other things
- (set (make-local-variable 'mail-header-separator) "--text follows this line--")
- (put 'mail-header-separator 'permanent-local t)
- (save-excursion
- ;; make sure there's not one already
- (mu4e~draft-remove-mail-header-separator)
- (let ((sepa (propertize mail-header-separator
- 'intangible t
- ;; don't make this read-only, message-mode
- ;; seems to require it being writable in some cases
- ;;'read-only "Can't touch this"
- 'rear-nonsticky t
- 'font-lock-face 'mu4e-compose-separator-face)))
- (widen)
- ;; search for the first empty line
- (goto-char (point-min))
- (if (search-forward-regexp "^$" nil t)
- (replace-match sepa)
- (progn ;; no empty line? then prepend one
- (goto-char (point-max))
- (insert "\n" sepa))))))
-
-(defun mu4e~draft-remove-mail-header-separator ()
- "Remove `mail-header-separator; we do this before saving a
-file (and restore it afterwards), to ensure that the separator
-never hits the disk. Also see `mu4e~draft-insert-mail-header-separator."
- (save-excursion
- (widen)
- (goto-char (point-min))
- ;; remove the --text follows this line-- separator
- (when (search-forward-regexp (concat "^" mail-header-separator) nil t)
- (let ((inhibit-read-only t))
- (replace-match "")))))
-
-
-(defun mu4e~draft-reply-all-p (origmsg)
- "Ask user whether she wants to reply to *all* recipients.
-If there is just one recipient of ORIGMSG do nothing."
- (let* ((recipnum
- (+ (length (mu4e~draft-create-to-lst origmsg))
- (length (mu4e~draft-create-cc-lst origmsg t))))
- (response
- (if (= recipnum 1)
- 'all ;; with one recipient, we can reply to 'all'....
- (mu4e-read-option
- "Reply to "
- `( (,(format "all %d recipients" recipnum) . all)
- ("sender only" . sender-only))))))
- (eq response 'all)))
-
-(defun mu4e~draft-message-filename-construct (&optional flagstr)
- "Construct a randomized name for a message file with flags FLAGSTR.
-It looks something like
- <time>-<random>.<hostname>:2,
-You can append flags."
- (let* ((sysname (if (fboundp 'system-name)
- (system-name)
- (with-no-warnings system-name)))
- (hostname (downcase
- (save-match-data
- (substring sysname
- (string-match "^[^.]+" sysname)
- (match-end 0))))))
- (format "%s.%04x%04x%04x%04x.%s:2,%s"
- (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
- (mu4e~draft-header "User-agent" mu4e-user-agent-string)
- (when mu4e-compose-auto-include-date
- (mu4e~draft-header "Date" (message-make-date)))))
-
-(defconst mu4e~draft-reply-prefix "Re: "
- "String to prefix replies with.")
-
-(defun mu4e~draft-reply-construct (origmsg)
- "Create a draft message as a reply to original message
-ORIGMSG. Replying-to-self is a special; in that case, the To and Cc
-fields will be the same as in the original."
- (let* ((reply-to-self (mu4e-message-contact-field-matches-me origmsg :from))
- (recipnum
- (+ (length (mu4e~draft-create-to-lst origmsg))
- (length (mu4e~draft-create-cc-lst origmsg t))))
- ;; reply-to-self implies reply-all
- (reply-all (or reply-to-self (mu4e~draft-reply-all-p origmsg)))
- (old-msgid (plist-get origmsg :message-id))
- (subject
- (concat mu4e~draft-reply-prefix
- (message-strip-subject-re (or (plist-get origmsg :subject) "")))))
- (concat
- (mu4e~draft-header "From" (or (mu4e~draft-from-construct) ""))
- (mu4e~draft-header "Reply-To" mu4e-compose-reply-to-address)
-
- (if reply-to-self
- ;; When we're replying to ourselves, simply keep the same headers.
- (concat
- (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))))
-
- ;; 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))
- ;; otherwise...
- (concat
- (mu4e~draft-header "To" (mu4e~draft-recipients-construct :to origmsg))
- (mu4e~draft-header "Cc" (mu4e~draft-recipients-construct :cc origmsg
- reply-all)))))
- (mu4e~draft-header "Subject" subject)
- (mu4e~draft-header "References"
- (mu4e~draft-references-construct origmsg))
- (mu4e~draft-common-construct)
- (when old-msgid
- (mu4e~draft-header "In-reply-to" (format "<%s>" old-msgid)))
- "\n\n"
- (mu4e~draft-cite-original origmsg))))
-
-(defconst mu4e~draft-forward-prefix "Fwd: "
- "String to prefix replies with.")
-
-(defun mu4e~draft-forward-construct (origmsg)
- "Create a draft forward message for original message ORIGMSG."
- (let ((subject
- (or (plist-get origmsg :subject) "")))
- (concat
- (mu4e~draft-header "From" (or (mu4e~draft-from-construct) ""))
- (mu4e~draft-header "Reply-To" mu4e-compose-reply-to-address)
- (mu4e~draft-header "To" "")
- (mu4e~draft-common-construct)
- (mu4e~draft-header "References"
- (mu4e~draft-references-construct origmsg))
- (mu4e~draft-header "Subject"
- (concat
- ;; if there's no Fwd: yet, prepend it
- (if (string-match "^Fwd:" subject)
- ""
- mu4e~draft-forward-prefix)
- subject))
- "\n\n"
- (mu4e~draft-cite-original origmsg))))
-
-(defun mu4e~draft-newmsg-construct ()
- "Create a new message."
- (concat
- (mu4e~draft-header "From" (or (mu4e~draft-from-construct) ""))
- (mu4e~draft-header "Reply-To" mu4e-compose-reply-to-address)
- (mu4e~draft-header "To" "")
- (mu4e~draft-header "Subject" "")
- (mu4e~draft-common-construct)))
-
-(defvar mu4e~draft-drafts-folder nil
- "The drafts-folder for this compose buffer, based on
-`mu4e-drafts-folder', which is evaluated once.")
-
-(defun mu4e~draft-open-file (path)
- "Open the the draft file at PATH."
- (if mu4e-compose-in-new-frame
- (find-file-other-frame path)
- (find-file path)))
-
-(defun mu4e~draft-determine-path (draft-dir)
- "Determine the path for a new draft file."
- (format "%s/%s/cur/%s"
- mu4e-maildir draft-dir (mu4e~draft-message-filename-construct "DS")))
-
-
-(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').
-
-The name of the draft folder is constructed from the
-concatenation of `mu4e-maildir' and `mu4e-drafts-folder' (the
-latter will be evaluated). The message file name is a unique name
-determined by `mu4e-send-draft-file-name'. The initial contents
-will be created from either `mu4e~draft-reply-construct', or
-`mu4e~draft-forward-construct' or `mu4e~draft-newmsg-construct'."
- (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
- (setq draft-dir (mu4e~guess-maildir (mu4e-message-field msg :path)))
- (mu4e~draft-open-file (mu4e-message-field msg :path)))
-
- (resend
- ;; case-2: copy some exisisting message to a draft message, then edit
- ;; that.
- (setq draft-dir (mu4e~guess-maildir (mu4e-message-field msg :path)))
- (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 determine
- ;; mu4e-get-drafts-folder
- (setq draft-dir (mu4e-get-drafts-folder msg))
- (let ((draft-path (mu4e~draft-determine-path draft-dir))
- (initial-contents
- (case compose-type
- (reply (mu4e~draft-reply-construct msg))
- (forward (mu4e~draft-forward-construct msg))
- (new (mu4e~draft-newmsg-construct)))))
- (mu4e~draft-open-file draft-path)
- (insert initial-contents)
- (newline)
- ;; include the message signature (if it's set)
- (if (and mu4e-compose-signature-auto-include mu4e-compose-signature)
- (let ((message-signature mu4e-compose-signature))
- (save-excursion
- (message-insert-signature)
- (mu4e~fontify-signature))))))
- (t (mu4e-error "unsupported compose-type %S" compose-type)))
- ;; 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)