* mu4e: code refactoring / cleanup

This commit is contained in:
djcb 2012-04-11 22:31:52 +03:00
parent b633d0c74a
commit e7247a5e0f
7 changed files with 253 additions and 225 deletions

View File

@ -29,7 +29,7 @@ dist_lisp_LISP= \
mu4e-main.el \
mu4e-proc.el \
mu4e-raw-view.el \
mu4e-send.el \
mu4e-compose.el \
mu4e-speedbar.el \
mu4e-vars.el \
mu4e-version.el \

View File

@ -1,4 +1,4 @@
;; mu4e-send.el -- part of mu4e, the mu mail user agent for emacs
;; mu4e-compose.el -- part of mu4e, the mu mail user agent for emacs
;;
;; Copyright (C) 2011-2012 Dirk-Jan C. Binnema
@ -28,27 +28,16 @@
;;; Code:
;; we use some stuff from gnus..
(require 'cl)
(require 'mu4e-utils)
(require 'mu4e-vars)
(require 'message)
(require 'mail-parse)
(require 'smtpmail)
;; internal variables / constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defconst mu4e-send-draft-name "*mu4e-draft*" "Name for draft messages.")
(require 'mu4e-utils)
(require 'mu4e-vars)
(require 'mu4e-proc)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun mu4e-send-user-agent ()
"Return the User-Agent string for mu4e. This is either the value
of `mu4e-user-agent', or, if not set, a string based on the versions
of mu4e and emacs."
(or mu4e-user-agent
(format "mu4e %s; emacs %s" mu4e-mu-version emacs-version)))
(defun mu4e-send-cite-original (msg)
(defun mu4e--cite-original (msg)
"Cite the body text of MSG, with a \"On %s, %s wrote:\"
line (with the %s's replaced with the date of MSG and the name
or e-mail address of its sender (or 'someone' if nothing
@ -68,14 +57,13 @@ of mu4e and emacs."
(replace-regexp-in-string "^"
mu4e-citation-prefix body)))))
(defun mu4e-send-header (hdr val)
(defun mu4e--header (hdr val)
"Return a header line of the form HDR: VAL\n. If VAL is nil,
return nil."
(when val
(format "%s: %s\n" hdr val)))
(when val (format "%s: %s\n" hdr val)))
(defun mu4e-send-references-create (msg)
(defun mu4e--refererences-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 (which may be empty) and the message-id. If the
@ -90,7 +78,6 @@ return nil."
refs ","))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; determine the recipient fields for new messages
@ -116,6 +103,8 @@ e-mail addresses. If LST is nil, returns nil."
(downcase (or (cdr cell1) ""))
(downcase (or (cdr cell2) ""))))
(defun mu4e--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
@ -160,7 +149,7 @@ the original message ORIGMSG, and whether it's a reply-all."
cc-lst))))
cc-lst)))
(defun mu4e--create-recipient-field (field origmsg &optional reply-all)
(defun mu4e--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
@ -174,7 +163,8 @@ message. Return nil if there are no recipients for the particular field."
(otherwise
(error "Unsupported field")))))
(defun mu4e-send-from-create ()
(defun mu4e--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."
@ -185,9 +175,7 @@ nil, function returns nil."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun mu4e-insert-mail-header-separator ()
(defun mu4e--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-edit-mode, we use
@ -205,10 +193,10 @@ separator is never written to file. Also see
(goto-char (point-max))
(insert (concat "\n" mail-header-separator "\n"))))))
(defun mu4e-remove-mail-header-separator ()
(defun mu4e--remove-mail-header-separator ()
"Remove `mail-header-separator; we do this before saving a
file (and restore it afterwardds), to ensure that the separator
never hits the disk. Also see `mu4e-insert-mail-header-separator."
never hits the disk. Also see `mu4e--insert-mail-header-separator."
(save-excursion
(goto-char (point-min))
;; remove the --text follows this line-- separator
@ -220,10 +208,10 @@ never hits the disk. Also see `mu4e-insert-mail-header-separator."
are more than 1 (based on ORIGMSG)."
(let* ((recipnum
(+ (length (mu4e--create-to-lst origmsg))
(length (mu4e--create-cc-lst origmsg t))))
(length (mu4e--create-cc-lst origmsg t))))
(response
(if (= recipnum 1)
?a ;; with one recipient, we can reply to 'all'....
?a ;; with one recipient, we can reply to 'all'....
(mu4e-read-option
"Reply to "
`( (,(format "all %d recipients" recipnum))
@ -231,7 +219,7 @@ are more than 1 (based on ORIGMSG)."
(= response ?a)))
(defun mu4e-send-create-reply (origmsg)
(defun mu4e--reply-construct (origmsg)
"Create a draft message as a reply to original message ORIGMSG."
(let* ((recipnum
(+ (length (mu4e--create-to-lst origmsg))
@ -241,58 +229,60 @@ are more than 1 (based on ORIGMSG)."
(subject (or (plist-get origmsg :subject) "")))
(concat
(mu4e-send-header "From" (or (mu4e-send-from-create) ""))
(mu4e-send-header "Reply-To" mu4e-reply-to-address)
(mu4e-send-header "To" (mu4e--create-recipient-field :to origmsg))
(mu4e-send-header "Cc" (mu4e--create-recipient-field :cc origmsg
(mu4e--header "From" (or (mu4e--from-construct) ""))
(mu4e--header "Reply-To" mu4e-reply-to-address)
(mu4e--header "To" (mu4e--recipients-construct :to origmsg))
(mu4e--header "Cc" (mu4e--recipients-construct :cc origmsg
reply-all))
(mu4e-send-header "User-agent" (mu4e-send-user-agent))
(mu4e-send-header "References" (mu4e-send-references-create origmsg))
(mu4e--header "User-agent" (mu4e-user-agent))
(mu4e--header "References" (mu4e--refererences-construct origmsg))
(when old-msgid
(mu4e-send-header "In-reply-to" (format "<%s>" old-msgid)))
(mu4e--header "In-reply-to" (format "<%s>" old-msgid)))
(mu4e-send-header "Subject"
(mu4e--header "Subject"
(concat
;; if there's no Re: yet, prepend it
(if (string-match (concat "^" mu4e-reply-prefix) subject)
"" mu4e-reply-prefix)
subject))
"\n\n"
(mu4e-send-cite-original origmsg))))
(mu4e--cite-original origmsg))))
(defun mu4e-send-create-forward (origmsg)
(defun mu4e--forward-construct (origmsg)
"Create a draft forward message for original message ORIGMSG."
(let ((subject
(or (plist-get origmsg :subject) "")))
(concat
(mu4e-send-header "From" (or (mu4e-send-from-create) ""))
(mu4e-send-header "Reply-To" mu4e-reply-to-address)
(mu4e-send-header "To" "")
(mu4e-send-header "User-agent" (mu4e-send-user-agent))
(mu4e-send-header "References" (mu4e-send-references-create origmsg))
(mu4e-send-header "Subject"
(mu4e--header "From" (or (mu4e--from-construct) ""))
(mu4e--header "Reply-To" mu4e-reply-to-address)
(mu4e--header "To" "")
(mu4e--header "User-agent" (mu4e-user-agent))
(mu4e--header "References" (mu4e--refererences-construct origmsg))
(mu4e--header "Subject"
(concat
;; if there's no Re: yet, prepend it
(if (string-match (concat "^" mu4e-forward-prefix) subject)
"" mu4e-forward-prefix)
subject))
"\n\n"
(mu4e-send-cite-original origmsg))))
(mu4e--cite-original origmsg))))
(defun mu4e-send-create-new ()
"Create a new message.."
(defun mu4e--newmsg-construct ()
"Create a new message."
(concat
(mu4e-send-header "From" (or (mu4e-send-from-create) ""))
(mu4e-send-header "Reply-To" mu4e-reply-to-address)
(mu4e-send-header "To" "")
(mu4e-send-header "User-agent" (mu4e-send-user-agent))
(mu4e-send-header "Subject" "")
(mu4e--header "From" (or (mu4e--from-construct) ""))
(mu4e--header "Reply-To" mu4e-reply-to-address)
(mu4e--header "To" "")
(mu4e--header "User-agent" (mu4e-user-agent))
(mu4e--header "Subject" "")
"\n"))
(defun mu4e-send-open-draft (compose-type &optional msg)
(defun mu4e--open-new-draft-file (compose-type &optional msg)
"Open a draft file for a new message, creating it if it does not
already exist, and optionally fill it with STR. Function also adds
the new message to the database. When the draft message is added to
@ -311,9 +301,9 @@ use the new docid. Returns the full path to the new message."
(format-time-string "%Y%m%d" (current-time))
(emacs-pid) (random t) hostname)))
(str (case compose-type
(reply (mu4e-send-create-reply msg))
(forward (mu4e-send-create-forward msg))
(new (mu4e-send-create-new))
(reply (mu4e--reply-construct msg))
(forward (mu4e--forward-construct msg))
(new (mu4e--newmsg-construct))
(t (error "unsupported compose-type %S" compose-type)))))
(when str
(with-current-buffer (find-file-noselect draft)
@ -322,7 +312,7 @@ use the new docid. Returns the full path to the new message."
(define-derived-mode mu4e-edit-mode message-mode "mu4e:edit"
"Major mode for the mu4e main screen.
"Major mode for the mu4e message composition, derived from `message-mode'.
\\{message-mode-map}."
(let ((message-hidden-headers
`("^References:" "^Face:" "^X-Face:" "^X-Draft-From:"
@ -344,11 +334,11 @@ use the new docid. Returns the full path to the new message."
;; hack-hack-hack... just before saving, we remove the
;; mail-header-separator; just after saving we restore it; thus, the
;; separator should never appear on disk
(add-hook 'before-save-hook 'mu4e-remove-mail-header-separator)
(add-hook 'before-save-hook 'mu4e--remove-mail-header-separator)
(add-hook 'after-save-hook
(lambda ()
(mu4e-set-buffer-name)
(mu4e-insert-mail-header-separator)
(mu4e--set-friendly-buffer-name)
(mu4e--insert-mail-header-separator)
(set-buffer-modified-p nil)))
;; update the db when the file is saved...]
@ -357,27 +347,27 @@ use the new docid. Returns the full path to the new message."
(mu4e-proc-add (buffer-file-name) mu4e-drafts-folder))))
;; notify the backend that a message has been sent. The backend will respond
;; with (:sent ...) sexp, which is handled in `mu4e-send-compose-handler'.
;; with (:sent ...) sexp, which is handled in `mu4e-compose-handler'.
(add-hook 'message-sent-hook
(lambda ()
(set-buffer-modified-p t)
(basic-save-buffer)
(mu4e-proc-sent (buffer-file-name) mu4e-drafts-folder)))
;; register the function; this function will be called when the '(:sent...)'
;; message is received (see mu4e-proc.el) with parameters docid and path
(setq mu4e-proc-sent-func 'mu4e-sent-handler)
;; register the function; this function will be called when the '(:sent...)'
;; message is received (see mu4e-proc.el) with parameters docid and path
(setq mu4e-sent-func 'mu4e-sent-handler)
;; set the default directory to the user's home dir; this is probably more
;; useful e.g. when finding an attachment file the directory the current
;; mail files lives in...
(setq default-directory (expand-file-name "~/")))
(setq default-directory (expand-file-name "~/")))
(defconst mu4e-send-buffer-max-name-length 20
(defconst mu4e--buffer-max-name-length 30
"Maximum length of the mu4e-send-buffer-name.")
(defun mu4e-set-buffer-name (&optional compose-type)
(defun mu4e--set-friendly-buffer-name (&optional compose-type)
"Set some user-friendly buffer name based on the compose type."
(let* ((subj (message-field-value "subject"))
(subj (unless (and subj (string-match "^[:blank:]*$" subj)) subj))
@ -388,11 +378,11 @@ use the new docid. Returns the full path to the new message."
(otherwise "*draft*")))))
(rename-buffer (generate-new-buffer-name
(truncate-string-to-width str
mu4e-send-buffer-max-name-length
mu4e--buffer-max-name-length
nil nil t)))))
(defun mu4e-send-compose-handler (compose-type &optional original-msg includes)
(defun mu4e-compose-handler (compose-type &optional original-msg includes)
"Create a new draft message, or open an existing one.
COMPOSE-TYPE determines the kind of message to compose and is a
@ -418,14 +408,14 @@ The name of the draft folder is constructed from the concatenation
The message file name is a unique name determined by
`mu4e-send-draft-file-name'.
The initial STR would be created from either `mu4e-send-create-reply',
ar`mu4e-send-create-forward' or `mu4e-send-create-new'. The editing buffer is
The initial STR would be created from either `mu4e--reply-construct',
ar`mu4e--forward-construct' or `mu4e--newmsg-construct'. The editing buffer is
using Gnus' `message-mode'."
(unless mu4e-maildir (error "mu4e-maildir not set"))
(unless mu4e-drafts-folder (error "mu4e-drafts-folder not set"))
(let ((draft
(if (member compose-type '(reply forward new))
(mu4e-send-open-draft compose-type original-msg)
(mu4e--open-new-draft-file compose-type original-msg)
(if (eq compose-type 'edit)
(plist-get original-msg :path)
(error "unsupported compose-type %S" compose-type)))))
@ -435,7 +425,7 @@ using Gnus' `message-mode'."
;; insert mail-header-separator, which is needed by message mode to separate
;; headers and body. will be removed before saving to disk
(mu4e-insert-mail-header-separator)
(mu4e--insert-mail-header-separator)
;; include files -- e.g. when forwarding a message with attachments,
;; we take those from the original.
@ -455,11 +445,11 @@ using Gnus' `message-mode'."
(message-goto-to)
(message-goto-body))
(mu4e-set-buffer-name compose-type)
(mu4e--set-friendly-buffer-name compose-type)
;; buffer is not user-modified yet
(set-buffer-modified-p nil)))
(defun mu4e-sent-handler (docid path)
@ -468,14 +458,14 @@ message."
(with-current-buffer (find-file-noselect path)
;; for Forward ('Passed') and Replied messages, try to set the appropriate
;; flag at the message forwarded or replied-to
(mu4e-send-set-parent-flag docid path)
(mu4e--set-parent-flag docid path)
;; handle the draft -- should it be moved to the send folder, or elsewhere?
(mu4e-send-save-copy-maybe docid path)
(mu4e--save-copy-maybe docid path)
;; now, get rid of the buffer
(kill-buffer)))
(defun mu4e-send-save-copy-maybe (docid path)
(defun mu4e--save-copy-maybe (docid path)
"Handler function, called with DOCID and PATH for the just-sent
message, which will move it to the sent-folder or elsewhere,
depending on the value of `mu4e-sent-messages-behavior'.
@ -493,7 +483,7 @@ buffer."
(mu4e-proc-move-msg docid mu4e-trash-folder "+T-D+S")
(mu4e-proc-move-msg docid mu4e-sent-folder "-T-D+S")))))
(defun mu4e-send-set-parent-flag (docid path)
(defun mu4e--set-parent-flag (docid path)
"Set the 'replied' \"R\" flag on messages we replied to, and the
'passed' \"F\" flag on message we have forwarded.
@ -530,4 +520,4 @@ buffer.
(when (and forwarded-from (string-match "<\\(.*\\)>" forwarded-from))
(mu4e-proc-flag (match-string 1 forwarded-from) "+P"))))
(provide 'mu4e-send)
(provide 'mu4e-compose)

View File

@ -81,14 +81,6 @@ results, otherwise, limit number of results to
"Handler function for displaying a message."
(mu4e-view msg mu4e-hdrs-buffer))
(defun mu4e-hdrs-error-handler (err)
"Handler function for showing an error."
(let ((errcode (plist-get err :error))
(errmsg (plist-get err :error-message)))
(case errcode
(4 (message "No matches for this search query."))
(t (message (format "Error %d: %s" errcode errmsg))))))
(defun mu4e-hdrs-update-handler (msg is-move)
"Update handler, will be called when a message has been updated
in the database. This function will update the current list of
@ -343,17 +335,6 @@ after the end of the search results."
(fset 'mu4e-hdrs-mode-map mu4e-hdrs-mode-map)
;; we register our handler functions for the mu4e-proc (mu server) output
(setq mu4e-proc-error-func 'mu4e-hdrs-error-handler)
(setq mu4e-proc-update-func 'mu4e-hdrs-update-handler)
(setq mu4e-proc-header-func 'mu4e-hdrs-header-handler)
(setq mu4e-proc-found-func 'mu4e-hdrs-found-handler)
(setq mu4e-proc-view-func 'mu4e-hdrs-view-handler)
(setq mu4e-proc-remove-func 'mu4e-hdrs-remove-handler)
(setq mu4e-proc-erase-func 'mu4e-hdrs-clear)
;; this last one is defined in mu4e-send.el
(setq mu4e-proc-compose-func 'mu4e-send-compose-handler)
(define-derived-mode mu4e-hdrs-mode special-mode
"mu4e:headers"
@ -471,7 +452,7 @@ docid DOCID, or nil if it cannot be found."
with DOCID which must be present in the headers buffer."
(save-excursion
(when (mu4e--goto-docid docid)
(mu4e-field-at-point field))))
(mu4e-field-at-point field))))
;;;; markers mark headers for
(defun mu4e--mark-header (docid mark)
@ -897,7 +878,7 @@ for draft messages."
;; 'new is special, since it takes no existing message as arg therefore,
;; we don't need to call thec backend, and call the handler *directly*
(if (eq compose-type 'new)
(mu4e-send-compose-handler 'new)
(mu4e-compose-handler 'new)
;; otherwise, we need the doc-id
(let ((docid (mu4e--docid-at-point)))
(unless docid (error "No message at point."))

View File

@ -29,68 +29,8 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; internal vars
(defvar mu4e-mu-proc nil
"*internal* The mu-server process")
(defvar mu4e-proc-error-func 'mu4e-default-handler
"*internal* A function called for each error returned from the
server process; the function is passed an error plist as
argument. See `mu4e-proc-filter' for the format.")
(defvar mu4e-proc-update-func 'mu4e-default-handler
"*internal* A function called for each :update sexp returned from
the server process; the function is passed a msg sexp as
argument. See `mu4e-proc-filter' for the format.")
(defvar mu4e-proc-remove-func 'mu4e-default-handler
"*internal* A function called for each :remove sexp returned from
the server process, when some message has been deleted. The
function is passed the docid of the removed message.")
(defvar mu4e-proc-sent-func 'mu4e-default-handler
"*internal* A function called for each :sent sexp returned from
the server process, when some message has been sent. The
function is passed the docid and the draft-path of the sent message.")
(defvar mu4e-proc-view-func 'mu4e-default-handler
"*internal* A function called for each single message sexp
returned from the server process. The function is passed a message
sexp as argument. See `mu4e-proc-filter' for the
format.")
(defvar mu4e-proc-header-func 'mu4e-default-handler
"*internal* A function called for each message returned from the
server process; the function is passed a msg plist as argument. See
`mu4e-proc-filter' for the format.")
(defvar mu4e-proc-found-func 'mu4e-default-handler
"*internal* A function called for when we received a :found sexp
after the headers have returns, to report on the number of
matches. See `mu4e-proc-filter' for the format.")
(defvar mu4e-proc-erase-func 'mu4e-default-handler
"*internal* A function called for when we received an :erase sexp
after the headers have returns, to clear the current headers
buffer. See `mu4e-proc-filter' for the format.")
(defvar mu4e-proc-compose-func 'mu4e-default-handler
"*internal* A function called for each message returned from the
server process that is used as basis for composing a new
message (ie., either a reply or a forward); the function is passed
msg and a symbol (either reply or forward). See `mu4e-proc-filter'
for the format of <msg-plist>.")
(defvar mu4e-proc-info-func 'mu4e-default-handler
"*internal* A function called for each (:info type ....) sexp
received from the server process.")
(defvar mu4e-proc-pong-func 'mu4e-default-handler
"*internal* A function called for each (:pong type ....) sexp
received from the server process.")
(defvar mu4e-buf nil
"*internal* Buffer for results data.")
(defvar mu4e-mu-proc nil "*internal* The mu-server process")
(defvar mu4e-buf nil "*internal* Buffer for results data.")
(defvar mu4e-path-docid-map
(make-hash-table :size 32 :rehash-size 2 :test 'equal :weakness nil)
@ -98,31 +38,6 @@ received from the server process.")
we added ourselves (ie., draft messages), so we can e.g. move them
to the sent folder using their docid")
(defun mu4e-proc-info-handler (info)
"Handler function for (:info ...) sexps received from the server
process."
(let ((type (plist-get info :info)))
(cond
((eq type 'add)
;; update our path=>docid map; we use this when composing messages to
;; add draft messages to the db, so when we're sending them, we can move
;; to the sent folder using the `mu4e-proc-move'.
(puthash (plist-get info :path) (plist-get info :docid) mu4e-path-docid-map))
((eq type 'index)
(if (eq (plist-get info :status) 'running)
(message (format "Indexing... processed %d, updated %d"
(plist-get info :processed) (plist-get info :updated)))
(message
(format "Indexing completed; processed %d, updated %d, cleaned-up %d"
(plist-get info :processed) (plist-get info :updated)
(plist-get info :cleaned-up)))))
((plist-get info :message) (message "%s" (plist-get info :message))))))
(defun mu4e-default-handler (&rest args)
"Dummy handler function."
(error "Not handled: %S" args))
(defconst mu4e-server-name "*mu4e-server*"
"*internal* Name of the server process, buffer.")
@ -140,7 +55,6 @@ process."
mu4e-server-name mu4e-server-name
mu4e-mu-binary args))
;; register a function for (:info ...) sexps
(setq mu4e-proc-info-func 'mu4e-proc-info-handler)
(when mu4e-mu-proc
(set-process-query-on-exit-flag mu4e-mu-proc nil)
(set-process-coding-system mu4e-mu-proc 'binary 'utf-8-unix)
@ -202,7 +116,7 @@ updated as well, with all processed sexp data removed."
1. an error
(:error 2 :error-message \"unknown command\")
;; eox
=> this will be passed to `mu4e-proc-error-func'.
=> this will be passed to `mu4e-error-func'.
2a. a message sexp looks something like:
\(
@ -223,32 +137,32 @@ updated as well, with all processed sexp data removed."
:body-txt \" <message body>\"
\)
;; eox
=> this will be passed to `mu4e-proc-header-func'.
=> this will be passed to `mu4e-header-func'.
2b. After the list of message sexps has been returned (see 2a.),
we'll receive a sexp that looks like
(:found <n>) with n the number of messages found. The <n> will be
passed to `mu4e-proc-found-func'.
passed to `mu4e-found-func'.
3. a view looks like:
(:view <msg-sexp>)
=> the <msg-sexp> (see 2.) will be passed to `mu4e-proc-view-func'.
=> the <msg-sexp> (see 2.) will be passed to `mu4e-view-func'.
4. a database update looks like:
(:update <msg-sexp> :move <nil-or-t>)
=> the <msg-sexp> (see 2.) will be passed to
`mu4e-proc-update-func', :move tells us whether this is a move to
`mu4e-update-func', :move tells us whether this is a move to
another maildir, or merely a flag change.
5. a remove looks like:
(:remove <docid>)
=> the docid will be passed to `mu4e-proc-remove-func'
=> the docid will be passed to `mu4e-remove-func'
6. a compose looks like:
(:compose <msg-sexp> :action <reply|forward>) => the <msg-sexp>
and either 'reply or 'forward will be passed
`mu4e-proc-compose-func'."
`mu4e-compose-func'."
(mu4e-proc-log "* Received %d byte(s)" (length str))
(setq mu4e-buf (concat mu4e-buf str)) ;; update our buffer
(let ((sexp (mu4e-proc-eat-sexp-from-buf)))
@ -257,54 +171,54 @@ updated as well, with all processed sexp data removed."
(cond
;; a header plist can be recognized by the existence of a :date field
((plist-get sexp :date)
(funcall mu4e-proc-header-func sexp))
(funcall mu4e-header-func sexp))
;; the found sexp, we receive after getting all the headers
((plist-get sexp :found)
(funcall mu4e-proc-found-func (plist-get sexp :found)))
(funcall mu4e-found-func (plist-get sexp :found)))
;; viewing a specific message
((plist-get sexp :view)
(funcall mu4e-proc-view-func (plist-get sexp :view)))
(funcall mu4e-view-func (plist-get sexp :view)))
;; receive an erase message
((plist-get sexp :erase)
(funcall mu4e-proc-erase-func))
(funcall mu4e-erase-func))
;; receive a :sent message
((plist-get sexp :sent)
(funcall mu4e-proc-sent-func
(funcall mu4e-sent-func
(plist-get sexp :docid)
(plist-get sexp :path)))
;; receive a pong message
((plist-get sexp :pong)
(funcall mu4e-proc-pong-func
(funcall mu4e-pong-func
(plist-get sexp :version) (plist-get sexp :doccount)))
;; something got moved/flags changed
((plist-get sexp :update)
(funcall mu4e-proc-update-func
(funcall mu4e-update-func
(plist-get sexp :update) (plist-get sexp :move)))
;; a message got removed
((plist-get sexp :remove)
(funcall mu4e-proc-remove-func (plist-get sexp :remove)))
(funcall mu4e-remove-func (plist-get sexp :remove)))
;; start composing a new message
((plist-get sexp :compose-type)
(funcall mu4e-proc-compose-func
(funcall mu4e-compose-func
(plist-get sexp :compose-type)
(plist-get sexp :original)
(plist-get sexp :include)))
;; get some info
((plist-get sexp :info)
(funcall mu4e-proc-info-func sexp))
(funcall mu4e-info-func sexp))
;; receive an error
((plist-get sexp :error)
(funcall mu4e-proc-error-func sexp))
(funcall mu4e-error-func sexp))
(t (message "Unexpected data from server [%S]" sexp)))
(setq sexp (mu4e-proc-eat-sexp-from-buf)))))
@ -359,7 +273,7 @@ terminates."
(defun mu4e-proc-remove-msg (docid)
"Remove message identified by DOCID. The results are reporter
through either (:update ... ) or (:error ) sexp, which are handled
my `mu4e-proc-update-func' and `mu4e-proc-error-func', respectively."
my `mu4e-error-func', respectively."
(mu4e-proc-send-command "remove %d" docid))
@ -367,7 +281,7 @@ my `mu4e-proc-update-func' and `mu4e-proc-error-func', respectively."
"Start a database query for EXPR, getting up to MAXNUM
results (or -1 for unlimited). For each result found, a function is
called, depending on the kind of result. The variables
`mu4e-proc-header-func' and `mu4e-proc-error-func' contain the function
`mu4e-error-func' contain the function
that will be called for, resp., a message (header row) or an
error."
(mu4e-proc-send-command "find \"%s\" %d"
@ -392,10 +306,10 @@ The flags are any of `deleted', `flagged', `new', `passed', `replied' `seen' or
`trashed', or the corresponding \"DFNPRST\" as defined in [1]. See
`mu4e-string-to-flags' and `mu4e-flags-to-string'.
The server reports the results for the operation through
`mu4e-proc-update-func'.
`mu4e-update-func'.
The results are reported through either (:update ... )
or (:error ) sexp, which are handled my `mu4e-proc-update-func' and
`mu4e-proc-error-func', respectively."
or (:error ) sexp, which are handled my `mu4e-update-func' and
`mu4e-error-func', respectively."
(let
((flagstr (if (stringp flags) flags (mu4e-flags-to-string flags)))
(fullpath (concat mu4e-maildir targetmdir)))
@ -446,7 +360,7 @@ expecting a (:sent <docid> :path <draftpath>) in response."
(defun mu4e-proc-view-msg (docid-or-msgid)
"Get one particular message based on its DOCID-OR-MSGID. The result will
be delivered to the function registered as `mu4e-proc-message-func'."
be delivered to the function registered as `mu4e-message-func'."
(if (stringp docid-or-msgid)
(mu4e-proc-send-command "view %s" docid-or-msgid)
(mu4e-proc-send-command "view %d" docid-or-msgid)))
@ -455,7 +369,7 @@ be delivered to the function registered as `mu4e-proc-message-func'."
"Start composing a message with DOCID and COMPOSE-TYPE (a symbol,
either `forward', `reply' or `edit'.
The result will be delivered to the function registered as
`mu4e-proc-compose-func'."
`mu4e-compose-func'."
(unless (member compose-type '(forward reply edit))
(error "Unsupported compose-type %S" compose-type))
(mu4e-proc-send-command "compose %s %d" (symbol-name compose-type) docid))

View File

@ -27,6 +27,7 @@
;;; Code:
(require 'cl)
(require 'html2text)
(require 'mu4e-vars)
(defun mu4e-create-maildir-maybe (dir)
"Offer to create DIR if it does not exist yet. Return t if the
@ -91,7 +92,7 @@ Function returns the CHAR typed."
(setq ;; eat first kar from descr; use it as kar
kar (string-to-char descr)
descr (substring descr 1)))
(add-to-list 'optionkars kar)
(add-to-list 'optionkars kar)
(concat
"[" (propertize (make-string 1 kar) 'face 'mu4e-view-link-face) "]"
descr))) options ", "))
@ -106,7 +107,7 @@ Function returns the CHAR typed."
(mu4e-read-option prompt options))
;; otherwise, return the response char
response))
(defun mu4e-get-maildirs (parentdir)
"List the maildirs under PARENTDIR." ;; TODO: recursive?
@ -335,6 +336,12 @@ top level if there is none."
('mu4e-view-mode "(mu4e)Message view")
(t "mu4e"))))
(defun mu4e-user-agent ()
"Return the User-Agent string for mu4e. This is either the value
of `mu4e-user-agent', or, if not set, a string based on the versions
of mu4e and emacs."
(or mu4e-user-agent
(format "mu4e %s; emacs %s" mu4e-mu-version emacs-version)))
(defun mu4e-field-at-point (field)
"Get FIELD (a symbol, see `mu4e-header-names') for the message at
@ -373,6 +380,46 @@ that has a live window), and vice versa."
(select-window other-win)
(message "No window to switch to"))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; some handler functions for server messages
;;
(defun mu4e-info-handler (info)
"Handler function for (:info ...) sexps received from the server
process."
(let ((type (plist-get info :info)))
(cond
((eq type 'add)
;; update our path=>docid map; we use this when composing messages to
;; add draft messages to the db, so when we're sending them, we can move
;; to the sent folder using the `mu4e-proc-move'.
(puthash (plist-get info :path) (plist-get info :docid) mu4e-path-docid-map))
((eq type 'index)
(if (eq (plist-get info :status) 'running)
(message (format "Indexing... processed %d, updated %d"
(plist-get info :processed) (plist-get info :updated)))
(message
(format "Indexing completed; processed %d, updated %d, cleaned-up %d"
(plist-get info :processed) (plist-get info :updated)
(plist-get info :cleaned-up)))))
((plist-get info :message) (message "%s" (plist-get info :message))))))
(defun mu4e-error-handler (err)
"Handler function for showing an error."
(let ((errcode (plist-get err :error))
(errmsg (plist-get err :error-message)))
(case errcode
(4 (message "No matches for this search query."))
(t (message (format "Error %d: %s" errcode errmsg))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar mu4e-update-timer nil
"*internal* The mu4e update timer.")
@ -390,7 +437,7 @@ server has the expected values."
(if (< emacs-major-version 23)
(error "Emacs >= 23.x is required for mu4e")
(progn
(setq mu4e-proc-pong-func
(setq mu4e-pong-func
(lambda (version doccount)
(unless (string= version mu4e-mu-version)
(error "mu server has version %s, but we need %s"

View File

@ -475,4 +475,72 @@ in which case it will be equal to `:to'.)")
(defvar mu4e-current-msg nil
"*internal* The plist describing the currently viewed message.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; our handlers funcs
;; these handler funcs define what happens when we receive a certain message
;; from the server
(defun mu4e--default-handler (&rest args)
"*internal* Dummy handler function."
(error "Not handled: %S" args))
(defvar mu4e-error-func 'mu4e--default-handler
"A function called for each error returned from the server
process; the function is passed an error plist as argument. See
`mu4e-proc-filter' for the format.")
(defvar mu4e-update-func 'mu4e--default-handler
"A function called for each :update sexp returned from the server
process; the function is passed a msg sexp as argument. See
`mu4e-proc-filter' for the format.")
(defvar mu4e-remove-func 'mu4e--default-handler
"A function called for each :remove sexp returned from the server
process, when some message has been deleted. The function is passed
the docid of the removed message.")
(defvar mu4e-sent-func 'mu4e--default-handler
"A function called for each :sent sexp returned from the server
process, when some message has been sent. The function is passed
the docid and the draft-path of the sent message.")
(defvar mu4e-view-func 'mu4e--default-handler
"A function called for each single message sexp returned from the
server process. The function is passed a message sexp as
argument. See `mu4e-proc-filter' for the format.")
(defvar mu4e-header-func 'mu4e--default-handler
"A function called for each message returned from the server
process; the function is passed a msg plist as argument. See
`mu4e-proc-filter' for the format.")
(defvar mu4e-found-func 'mu4e--default-handler
"A function called for when we received a :found sexp after the
headers have returns, to report on the number of matches. See
`mu4e-proc-filter' for the format.")
(defvar mu4e-erase-func 'mu4e--default-handler
"A function called for when we received an :erase sexp after the
headers have returns, to clear the current headers buffer. See
`mu4e-proc-filter' for the format.")
(defvar mu4e-compose-func 'mu4e--default-handler
"A function called for each message returned from the server
process that is used as basis for composing a new message (ie.,
either a reply or a forward); the function is passed msg and a
symbol (either reply or forward). See `mu4e-proc-filter' for the
format of <msg-plist>.")
(defvar mu4e-info-func 'mu4e--default-handler
"A function called for each (:info type ....) sexp received from
the server process.")
(defvar mu4e-pong-func 'mu4e--default-handler
"A function called for each (:pong type ....) sexp received from
the server process.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(provide 'mu4e-vars)
;;; End of mu4e-vars.el

View File

@ -28,17 +28,45 @@
(eval-when-compile (require 'cl))
(require 'mu4e-version) ;; autogenerated file with the version
(require 'mu4e-hdrs) ;; headers view
(require 'mu4e-view) ;; message view
(require 'mu4e-main) ;; main screen
(require 'mu4e-send) ;; editing / sending
(require 'mu4e-compose) ;; message composition / sending
(require 'mu4e-proc) ;; communication with backend
(require 'mu4e-utils) ;; utility functions
(require 'mu4e-speedbar) ;; support for speedbar
;; mu4e-version.el is autogenerated, and defines mu4e-mu-version
(require 'mu4e-version)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; register our handler functions; these connect server messages to functions
;; to handle them.
;;
;;
;; these are all defined in mu4e-hdrs
(setq mu4e-update-func 'mu4e-hdrs-update-handler)
(setq mu4e-header-func 'mu4e-hdrs-header-handler)
(setq mu4e-found-func 'mu4e-hdrs-found-handler)
(setq mu4e-view-func 'mu4e-hdrs-view-handler)
(setq mu4e-remove-func 'mu4e-hdrs-remove-handler)
(setq mu4e-erase-func 'mu4e-hdrs-clear)
;; these ones are define in mu4e-utils
(setq mu4e-info-func 'mu4e-info-handler)
(setq mu4e-error-func 'mu4e-error-handler)
;; note: mu4e-utils also dynamically (temporarily)
;; registers mu4e-pong func
;; this one is defined in mu4e-compose
(setq mu4e-compose-func 'mu4e-compose-handler)
;; note: mu4e-compose.el dynamically registers mu4e-sent-func
;; we don't do that here, because it's only a local (temporary)
;; handler
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(provide 'mu4e)