* mu4e-{compose,hdrs,proc}.el: updates (many!) for the changes in the backend protocol

This commit is contained in:
djcb 2012-04-15 14:21:59 +03:00
parent b06c1c8925
commit c71ccfcd65
3 changed files with 145 additions and 122 deletions

View File

@ -91,7 +91,7 @@ e-mail addresses. If LST is nil, returns nil."
(let ((name (car addrcell))
(email (cdr addrcell)))
(if name
(format "%s <%s>" name email)
(format "\"%s\" <%s>" name email)
(format "%s" email))))
lst ", ")))
@ -318,19 +318,13 @@ use the new docid. Returns the full path to the new message."
`("^References:" "^Face:" "^X-Face:" "^X-Draft-From:"
"^User-agent:")))
(use-local-map mu4e-edit-mode-map)
(message-hide-headers)
(make-local-variable 'before-save-hook)
(make-local-variable 'after-save-hook)
(make-local-variable 'message-default-charset)
;; if the default charset is not set, use UTF-8
(unless message-default-charset
(setq message-default-charset 'utf-8))
;; 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
@ -340,12 +334,10 @@ use the new docid. Returns the full path to the new message."
(mu4e--set-friendly-buffer-name)
(mu4e--insert-mail-header-separator)
(set-buffer-modified-p nil)))
;; update the db when the file is saved...]
(add-hook 'after-save-hook
(lambda()
(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-compose-handler'.
(add-hook 'message-sent-hook
@ -353,11 +345,9 @@ use the new docid. Returns the full path to the new message."
(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-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...
@ -419,14 +409,11 @@ using Gnus' `message-mode'."
(if (eq compose-type 'edit)
(plist-get original-msg :path)
(error "unsupported compose-type %S" compose-type)))))
(find-file draft)
(mu4e-edit-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)
;; include files -- e.g. when forwarding a message with attachments,
;; we take those from the original.
(save-excursion
@ -444,27 +431,22 @@ using Gnus' `message-mode'."
(if (member compose-type '(new forward))
(message-goto-to)
(message-goto-body))
(mu4e--set-friendly-buffer-name compose-type)
;; buffer is not user-modified yet
(set-buffer-modified-p nil)))
(defun mu4e-sent-handler (docid path)
"Handler function, called with DOCID and PATH for the just-sent
message."
(with-current-buffer (find-file-noselect path)
(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--set-parent-flag docid path)
;; handle the draft -- should it be moved to the send folder, or elsewhere?
;; handle the draft -- should it be moved to the sent-folder, or elsewhere?
(mu4e--save-copy-maybe docid path)
;; now, get rid of the buffer
(kill-buffer)))
(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,
@ -474,14 +456,14 @@ Function assumes that it's executed in the context of the message
buffer."
;; first, what to do with the draft message in PATH?
(if (eq mu4e-sent-messages-behavior 'delete)
(mu4e-proc-remove-msg docid) ;; remove it
(mu4e-proc-remove docid) ;; remove it
;; otherwise,
(progn ;; prepare the message for saving
(basic-save-buffer)
;; now either move it to trash or to sent
(if (eq mu4e-sent-messages-behavior 'trash)
(mu4e-proc-move-msg docid mu4e-trash-folder "+T-D+S")
(mu4e-proc-move-msg docid mu4e-sent-folder "-T-D+S")))))
(mu4e-proc-move docid mu4e-trash-folder "+T-D+S")
(mu4e-proc-move docid mu4e-sent-folder "-T-D+S")))))
(defun mu4e--set-parent-flag (docid path)
"Set the 'replied' \"R\" flag on messages we replied to, and the
@ -516,8 +498,8 @@ buffer.
(setq forwarded-from (first refs))))))
;; remove the <>
(when (and in-reply-to (string-match "<\\(.*\\)>" in-reply-to))
(mu4e-proc-flag (match-string 1 in-reply-to) "+R"))
(mu4e-proc-move (match-string 1 in-reply-to) nil "+R"))
(when (and forwarded-from (string-match "<\\(.*\\)>" forwarded-from))
(mu4e-proc-flag (match-string 1 forwarded-from) "+P"))))
(mu4e-proc-move (match-string 1 forwarded-from) nil "+P"))))
(provide 'mu4e-compose)

View File

@ -52,8 +52,7 @@ buffer for the results. If FULL-SEARCH is non-nil return all
results, otherwise, limit number of results to
`mu4e-search-results-limit'."
(let ((buf (get-buffer-create mu4e-hdrs-buffer-name))
(inhibit-read-only t)
(esc (replace-regexp-in-string "\"" "\\\\\"" expr))) ;; escape "\"
(inhibit-read-only t))
(with-current-buffer buf
(mu4e-hdrs-mode)
(setq
@ -61,11 +60,10 @@ results, otherwise, limit number of results to
mu4e-last-expr expr
mu4e-hdrs-buffer buf
mode-name "mu4e-headers"))
(switch-to-buffer buf)
(mu4e-proc-find esc ;; '-1' means 'unlimited search'
(if full-search -1 mu4e-search-results-limit))
(mu4e-proc-find
(replace-regexp-in-string "\"" "\\\\\"" expr) ;; escape "\"
(unless full-search mu4e-search-results-limit))
;;; when we're starting a new search, we also kill the
;;; view buffer, if any
(mu4e-view-kill-buffer-and-window)))
@ -598,14 +596,14 @@ work well."
(lambda (docid val)
(let ((marker (nth 0 val)) (mark (nth 1 val)) (target (nth 2 val)))
(case mark
(move (mu4e-proc-move-msg docid target))
(read (mu4e-proc-flag docid "+S-u-N"))
(unread (mu4e-proc-flag docid "-S+u"))
(move (mu4e-proc-move docid target))
(read (mu4e-proc-move docid nil "+S-u-N"))
(unread (mu4e-proc-move docid nil "-S+u"))
(trash
(unless mu4e-trash-folder
(error "`mu4e-trash-folder' not set"))
(mu4e-proc-move-msg docid mu4e-trash-folder "+T"))
(delete (mu4e-proc-remove-msg docid)))))
(mu4e-proc-move docid mu4e-trash-folder "+T"))
(delete (mu4e-proc-remove docid)))))
mu4e-marks-map)
(mu4e-hdrs-unmark-all)))
@ -656,7 +654,7 @@ current window. "
(erase-buffer)
(insert (propertize "Waiting for message..."
'face 'mu4e-system-face 'intangible t)))
(mu4e-proc-view-msg docid))))
(mu4e-proc-view docid))))
(defun mu4e-hdrs-docid-is-marked (docid)
@ -708,10 +706,9 @@ up to `mu4e-search-results-limit' much quicker."
otherwise, limit to up to `mu4e-search-results-limit'."
(interactive)
(let ((query (mu4e-ask-bookmark "Bookmark: ")))
(when query
(when (and query (mu4e-handle-marks))
(mu4e-hdrs-search query current-prefix-arg))))
(defun mu4e-search-bookmark-edit-first (expr)
"Search using some bookmarked query, but allow for editing the
bookmark before submitting it. With C-u prefix, show /all/ results,
@ -719,7 +716,7 @@ otherwise, limit to up to `mu4e-search-results-limit'."
(interactive
(list (read-string "[mu] search for: "
(concat (or (mu4e-ask-bookmark "Edit bookmark: ") "") " "))))
(when expr
(when (and expr (mu4e-handle-marks))
(mu4e-hdrs-search expr current-prefix-arg)))
(defun mu4e-hdrs-kill-buffer-and-window ()
@ -779,11 +776,10 @@ maildir). With C-u prefix, show /all/ results, otherwise, limit to
up to `mu4e-search-results-limit'."
(interactive)
(let ((fld (mu4e-ask-maildir "Jump to maildir: ")))
(when fld
(when (and fld (mu4e-handle-marks))
(mu4e-hdrs-search (concat "\"maildir:" fld "\"")
current-prefix-arg))))
(defun mu4e-mark-for-move (&optional target)
"Mark message at point for moving to maildir TARGET. If target is
not provided, function asks for it."
@ -860,7 +856,7 @@ parameter NO-CONFIRMATION is is t, don't ask for confirmation."
(message nil)))))
(defun mu4e-compose (&optional compose-type)
(defun mu4e-compose (compose-type)
"Start composing a message of COMPOSE-TYPE, where COMPOSE-TYPE is
a symbol, one of `reply', `forward', `edit', `new'. All but `new'
take the message at point as input. Symbol `edit' is only allowed

View File

@ -26,7 +26,7 @@
(require 'mu4e-vars)
(require 'mu4e-utils)
(require 'mu4e-version)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; internal vars
(defvar mu4e-mu-proc nil "*internal* The mu-server process")
@ -114,7 +114,7 @@ updated as well, with all processed sexp data removed."
The server output is as follows:
1. an error
(:error 2 :error-message \"unknown command\")
(:error 2 :message \"unknown command\")
;; eox
=> this will be passed to `mu4e-error-func'.
@ -160,8 +160,7 @@ updated as well, with all processed sexp data removed."
=> 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
(:compose <reply|forward|edit|new> [:original<msg-sexp>] [:include <attach>])
`mu4e-compose-func'."
(mu4e-proc-log "* Received %d byte(s)" (length str))
(setq mu4e-buf (concat mu4e-buf str)) ;; update our buffer
@ -206,20 +205,31 @@ updated as well, with all processed sexp data removed."
(funcall mu4e-remove-func (plist-get sexp :remove)))
;; start composing a new message
((plist-get sexp :compose-type)
((plist-get sexp :compose)
(funcall mu4e-compose-func
(plist-get sexp :compose-type)
(plist-get sexp :compose)
(plist-get sexp :original)
(plist-get sexp :include)))
;; do something with a temporary file
((plist-get sexp :temp)
(funcall mu4e-temp-func
(plist-get sexp :temp) ;; name of the temp file
(plist-get sexp :what) ;; what to do with it (pipe|emacs|open-with...)
(plist-get sexp :param)));; parameter for the action
;; get some info
((plist-get sexp :info)
(funcall mu4e-info-func sexp))
;; receive an error
((plist-get sexp :error)
(funcall mu4e-error-func sexp))
(funcall mu4e-error-func
(plist-get sexp :error)
(plist-get sexp :message)))
(t (message "Unexpected data from server [%S]" sexp)))
(setq sexp (mu4e-proc-eat-sexp-from-buf)))))
@ -270,31 +280,45 @@ terminates."
(mu4e-proc-log (concat "-> " cmd))
(process-send-string mu4e-mu-proc (concat cmd "\n"))))
(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-error-func', respectively."
(mu4e-proc-send-command "remove %d" docid))
(defun mu4e--docid-msgid-param (docid-or-msgid)
"Construct a backend parameter based on DOCID-OR-MSGID."
(format
(if (stringp docid-or-msgid)
"msgid:\"%s\""
"docid:%d")
docid-or-msgid))
(defun mu4e-proc-find (expr &optional maxnum)
"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-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"
expr (if maxnum maxnum -1)))
(defun mu4e-proc-remove (docid)
"Remove message identified by docid.
The results are reporter through either (:update ... ) or (:error
) sexp, which are handled my `mu4e-error-func', respectively."
(mu4e-proc-send-command "remove docid:%d" docid))
(defun mu4e-proc-find (query &optional maxnum)
"Start a database query for QUERY, (optionally) getting up to
MAXNUM results. For each result found, a function is called,
depending on the kind of result. The variables `mu4e-error-func'
contain the function that will be called for, resp., a
message (header row) or an error."
(mu4e-proc-send-command
"find query:\"%s\"%s" query
(if maxnum (format " maxnum:%d" maxnum) "")))
(defun mu4e-proc-move-msg (docid targetmdir &optional flags)
"Move message identified by DOCID to TARGETMDIR, optionally
setting FLAGS in the process.
(defun mu4e-proc-move (docid-or-msgid &optional maildir flags)
"Move message identified by DOCID-OR-MSGID. At least one of
MAILDIR and FLAGS should be specified. Note, even if MAILDIR is
nil, this is still a move, since a change in flags still implies
a change in message filename.
TARGETDIR must be a maildir, that is, the part _without_ cur/ or
new/ or the root-maildir-prefix. E.g. \"/archive\". This directory
must already exist.
MAILDIR (), optionally
setting FLAGS (keyword argument :flags). optionally setting FLAGS
in the process. If MAILDIR is nil, message will be moved within the
same maildir.
MAILDIR must be a maildir, that is, the part _without_ cur/ or new/
or the root-maildir-prefix. E.g. \"/archive\". This directory must
already exist.
The FLAGS parameter can have the following forms:
1. a list of flags such as '(passed replied seen)
@ -310,70 +334,91 @@ The server reports the results for the operation through
The results are reported through either (:update ... )
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)))
(unless (and (file-directory-p fullpath) (file-writable-p fullpath))
(error "Not a writable directory: %s" fullpath))
;; note, we send the maildir, *not* the full path
(mu4e-proc-send-command "move %d \"%s\" %s" docid
targetmdir flagstr)))
(unless (or maildir flags)
(error "At least one of maildir and flags must be specified"))
(let* ((idparam (mu4e--docid-msgid-param docid-or-msgid))
(flagstr
(when flags
(concat " flags:"
(if (stringp flags) flags (mu4e-flags-to-string flags)))))
(path
(when maildir
(format " maildir:\"%s\"" maildir))))
(mu4e-proc-send-command "move %s %s %s"
idparam (or flagstr "") (or path ""))))
(defun mu4e-proc-flag (docid-or-msgid flags)
"Set FLAGS for the message identified by either DOCID-OR-MSGID."
(let ((flagstr (if (stringp flags) flags (mu4e-flags-to-string flags))))
(mu4e-proc-send-command "flag %S %s" docid-or-msgid flagstr)))
(defun mu4e-proc-index (maildir)
"Update the message database for MAILDIR."
(mu4e-proc-send-command "index \"%s\"" maildir))
(defun mu4e-proc-index (path)
"Update the message database for filesystem PATH, which should
point to some maildir directory structure."
(mu4e-proc-send-command "index path:\"%s\"" path))
(defun mu4e-proc-add (path maildir)
"Add the message at PATH to the database, with MAILDIR
set to e.g. '/drafts'; if this works, we will receive (:info :path
<path> :docid <docid>)."
(mu4e-proc-send-command "add \"%s\" \"%s\"" path maildir))
"Add the message at PATH to the database, with MAILDIR set to the
maildir this message resides in, e.g. '/drafts'; if this works, we
will receive (:info add :path <path> :docid <docid>)."
(mu4e-proc-send-command "add path:\"%s\" maildir:\"%s\""
path maildir))
(defun mu4e-proc-mkdir (maildir)
"Update the message database for MAILDIR."
(mu4e-proc-send-command "mkdir \"%s\"" maildir))
(defun mu4e-proc-sent (path maildir)
"Add the message at PATH to the database, with MAILDIR set to the
maildir this message resides in, e.g. '/drafts'; if this works, we
will receive (:info add :path <path> :docid <docid>)."
(mu4e-proc-send-command "sent path:\"%s\" maildir:\"%s\""
path maildir))
(defun mu4e-proc-save (docid partidx path)
"Save attachment PARTIDX from message with DOCID to PATH."
(mu4e-proc-send-command "save %d %d \"%s\"" docid partidx path))
(defun mu4e-proc-compose (type &optional docid)
"Start composing a message of certain TYPE (a symbol, either
`forward', `reply', `edit' or `new', based on an original
message (ie, replying to, forwarding, editing) with DOCID or nil
for type `new'.
The result will be delivered to the function registered as
`mu4e-compose-func'."
(unless (member type '(forward reply edit new))
(error "Unsupported compose-type %S" type))
(unless (eq (null docid) (eq type 'new))
(error "`new' implies docid not-nil, and vice-versa"))
(mu4e-proc-send-command "compose type:%s docid:%d"
(symbol-name type) docid))
(defun mu4e-proc-mkdir (path)
"Create a new maildir-directory at filesystem PATH."
(mu4e-proc-send-command "mkdir path:\"%s\"" path))
(defun mu4e-proc-extract (action docid partidx &optional path what param)
"Extract an attachment with index PARTIDX from message with DOCID
and perform ACTION on it (as symbol, either `save', `open', `temp') which
mean:
* save: save the part to PARAM1 (a path) (non-optional for save)
* open: open the part with the default application registered for doing so
* temp: save to a temporary file, then respond with
(:temp <path> :what <what> :param <param>)."
(let ((cmd
(concat "extract "
(case action
(save
(format "action:save docid:%d index:%d path:\"%s\""
docid partidx path))
(open (format "action:open docid:%d index:%d" docid partidx))
(temp
(format "action:temp docid:%d index:%d what:%s param:\"%s\""
docid partidx what param))
(otherwise (error "Unsupported action %S" action))))))
(mu4e-proc-send-command cmd)))
(defun mu4e-proc-open (docid partidx)
"Open attachment PARTIDX from message with DOCID."
(mu4e-proc-send-command "open %d %d" docid partidx))
(defun mu4e-proc-ping ()
"Sends a ping to the mu server, expecting a (:pong ...) in
response."
(mu4e-proc-send-command "ping"))
(defun mu4e-proc-sent (draftpath maildir)
"Tell the mu server that message DRAFTPATH has been send and its MAILDIR,
expecting a (:sent <docid> :path <draftpath>) in response."
(mu4e-proc-send-command "sent %s %s" draftpath maildir))
(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-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)))
(defun mu4e-proc-compose (compose-type docid)
"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-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))
(defun mu4e-proc-view (docid-or-msgid)
"Get one particular message based on its DOCID-OR-MSGID (keyword
argument). The result will be delivered to the function registered
as `mu4e-message-func'."
(mu4e-proc-send-command "view %s"
(mu4e--docid-msgid-param docid-or-msgid)))
(provide 'mu4e-proc)