diff --git a/emacs/mu4e-compose.el b/emacs/mu4e-compose.el index 108b3bdf..ca092e0e 100644 --- a/emacs/mu4e-compose.el +++ b/emacs/mu4e-compose.el @@ -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) diff --git a/emacs/mu4e-hdrs.el b/emacs/mu4e-hdrs.el index a2cff2f6..aa8a3607 100644 --- a/emacs/mu4e-hdrs.el +++ b/emacs/mu4e-hdrs.el @@ -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 diff --git a/emacs/mu4e-proc.el b/emacs/mu4e-proc.el index cbe6df33..cdd69825 100644 --- a/emacs/mu4e-proc.el +++ b/emacs/mu4e-proc.el @@ -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 :action ) => the - and either 'reply or 'forward will be passed + (:compose [:original] [:include ]) `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 - :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 :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 :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 :what :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 :path ) 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)