Permalink
Browse files

* don't save drafts immediately, and do the post-sending stuff not in…

… hooks,

  but rather by a special 'sent-' message handler
  • Loading branch information...
1 parent 86a1424 commit c2e3eac1def9f5d07625177ce072b27dc5c729ff @djcb committed Mar 27, 2012
Showing with 92 additions and 71 deletions.
  1. +3 −13 emacs/mu4e-main.el
  2. +54 −51 emacs/mu4e-send.el
  3. +16 −0 man/mu-server.1
  4. +19 −7 src/mu-cmd-server.c
View
@@ -37,7 +37,7 @@
(define-key map "b" 'mu4e-search-bookmark)
(define-key map "B" 'mu4e-search-bookmark-edit-first)
-
+
(define-key map "s" 'mu4e-search)
(define-key map "q" 'mu4e-quit)
(define-key map "j" 'mu4e-jump-to-maildir)
@@ -53,24 +53,14 @@
"Keymap for the *mu4e-main* buffer.")
(fset 'mu4e-main-mode-map mu4e-main-mode-map)
-(defun mu4e-main-mode ()
+(define-derived-mode mu4e-main-mode special-mode "mu4e:main"
"Major mode for the mu4e main screen.
-
\\{mu4e-main-mode-map}."
- (interactive)
-
- (kill-all-local-variables)
(use-local-map mu4e-main-mode-map)
-
(setq
- major-mode 'mu4e-main-mode
- mode-name "mu4e-main"
truncate-lines t
- buffer-read-only t
overwrite-mode 'overwrite-mode-binary))
-(put 'mu4e-main-mode 'mode-class 'special)
-
(defun mu4e-action-str (str &optional func-or-shortcut)
"Highlight the first occurence of [..] in STR. If
@@ -181,7 +171,7 @@ split-window."
(error "`smtp-queue-dir' does not exist"))
(setq smtpmail-queue-mail (not smtpmail-queue-mail))
(message
- (concat "Outgoing mail will now be "
+ (concat "Outgoing mail will now be "
(if smtpmail-queue-mail "queued" "sent directly")))
(mu4e-main-view))
View
@@ -282,15 +282,9 @@ use the new docid. Returns the full path to the new message."
(new (mu4e-send-create-new))
(t (error "unsupported compose-type %S" compose-type)))))
(when str
- (with-temp-file draft
- (insert str)
- (write-file draft)))
-
- ;; save our file immediately, add add it to the db; thus, we can retrieve
- ;; the new docid from `mu4e-path-docid-map'.
- (mu4e-proc-add draft mu4e-drafts-folder)
- draft))
-
+ (with-current-buffer (find-file-noselect draft)
+ (insert str)))
+ draft)) ;; return the draft buffer file
(defun mu4e-send-compose-handler (compose-type &optional original-msg includes)
"Create a new draft message, or open an existing one.
@@ -330,9 +324,6 @@ using Gnus' `message-mode'."
(plist-get original-msg :path)
(error "unsupported compose-type %S" compose-type)))))
- (unless (file-readable-p draft)
- (error "Cannot read %s" draft))
-
(find-file draft)
(message-mode)
@@ -344,15 +335,21 @@ using Gnus' `message-mode'."
(mml-attach-file
(plist-get att :file-name) (plist-get att :mime-type))))
- (make-local-variable 'write-file-functions)
+ (make-local-variable 'after-save-hook)
;; update the db when the file is saved...]
- (add-to-list 'write-file-functions
+ (add-hook 'after-save-hook
(lambda() (mu4e-proc-add (buffer-file-name) mu4e-drafts-folder)))
- ;; hook our functions up with sending of the message
- (add-hook 'message-sent-hook 'mu4e-send-save-copy-maybe nil t)
- (add-hook 'message-sent-hook 'mu4e-send-set-parent-flag nil t)
+ ;; notify the backend that a message has been sent. The backend will respond
+ ;; with (:sent ...) sexp, which is handled in .
+ (add-hook 'message-sent-hook
+ (lambda ()
+ (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)
(let ((message-hidden-headers
`("^References:" "^Face:" "^X-Face:" "^X-Draft-From:"
@@ -365,18 +362,27 @@ using Gnus' `message-mode'."
-(defun mu4e-send-save-copy-maybe ()
- "If `mu4e-save-sent-messages-behavior' is a symbol 'delete, move
- the message in this buffer to the sent folder. Otherwise, delete
- the draft message. This is meant to be called from message mode's
- `message-sent-hook'."
- (let ((docid (gethash (buffer-file-name) mu4e-path-docid-map)))
- (unless docid (error "unknown message (%S)" (buffer-file-name)))
+(defun mu4e-sent-handler (docid path)
+ "Handler function, called with DOCID and PATH for the just-sent
+message."
+ ;; 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)
+ ;; handle the draft -- should it be moved to the send folder, or elsewhere?
+ (mu4e-send-save-copy-maybe docid path))
+
+
+(defun mu4e-send-save-copy-maybe (docid path)
+ "Handler function, called with DOCID and PATH for the just-sent
+message."
+ ;; first, what to do with the draft message in PATH?
+ (with-current-buffer (find-file-noselect path)
(if (eq mu4e-sent-messages-behavior 'delete)
(progn
(save-buffer)
(mu4e-proc-remove-msg docid)) ;; remove it
- (progn ;; try to save the message the sent folder
+ ;; otherwise,
+ (progn ;; prepare the message for saving
(save-excursion
(goto-char (point-min))
;; remove the --text follows this line-- separator
@@ -390,10 +396,9 @@ using Gnus' `message-mode'."
(mu4e-proc-move-msg docid mu4e-sent-folder "-T-D+S")))))))
-
-(defun mu4e-send-set-parent-flag ()
- "Set the 'replied' flag on messages we replied to, and the
-'passed' flag on message we have forwarded.
+(defun mu4e-send-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.
If a message has a 'in-reply-to' header, it is considered a reply
to the message with the corresponding message id. If it does not
@@ -404,27 +409,25 @@ corresponding with the /last/ message-id in the references header.
Now, if the message has been determined to be either a forwarded
message or a reply, we instruct the server to update that message
with resp. the 'P' (passed) flag for a forwarded message, or the
-'R' flag for a replied message.
-
-This is meant to be called from message mode's
-`message-sent-hook'."
- (let ((in-reply-to (message-fetch-field "in-reply-to"))
- (forwarded-from)
- (references (message-fetch-field "references")))
- (unless in-reply-to
- (when references
- (with-temp-buffer ;; inspired by `message-shorten-references'.
- (insert references)
- (goto-char (point-min))
- (let ((refs))
- (while (re-search-forward "<[^ <]+@[^ <]+>" nil t)
- (push (match-string 0) refs))
- ;; the last will the first
- (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"))
- (when (and forwarded-from (string-match "<\\(.*\\)>" forwarded-from))
- (mu4e-proc-flag (match-string 1 forwarded-from) "+P"))))
+'R' flag for a replied message."
+ (with-current-buffer (find-file-noselect path)
+ (let ((in-reply-to (message-fetch-field "in-reply-to"))
+ (forwarded-from)
+ (references (message-fetch-field "references")))
+ (unless in-reply-to
+ (when references
+ (with-temp-buffer ;; inspired by `message-shorten-references'.
+ (insert references)
+ (goto-char (point-min))
+ (let ((refs))
+ (while (re-search-forward "<[^ <]+@[^ <]+>" nil t)
+ (push (match-string 0) refs))
+ ;; the last will the first
+ (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"))
+ (when (and forwarded-from (string-match "<\\(.*\\)>" forwarded-from))
+ (mu4e-proc-flag (match-string 1 forwarded-from) "+P")))))
(provide 'mu4e-send)
View
@@ -189,6 +189,22 @@ Using the \fBadd\fR command, we can add a message to the database.
<- (:info add :path <path> :docid <docid>)
.fi
+
+.TP
+.B sent
+
+With the \fBsent\fR command, we tell the backend that a message will be sent.
+
+.nf
+-> sent <path> <maildir>
+<- (:sent :path <path> :docid <docid>)
+.fi
+
+In the frontend, this message can then be used to trigger moving the message
+from the draft folder to the sent folder, setting the Replied/Passed flags on
+the parent messages.
+
+
.TP
.B mkdir
View
@@ -170,6 +170,7 @@ enum _Cmd {
CMD_QUIT,
CMD_REMOVE,
CMD_SAVE,
+ CMD_SENT,
CMD_PING,
CMD_VIEW,
@@ -197,6 +198,7 @@ cmd_from_string (const char *str)
{ CMD_QUIT, "quit"},
{ CMD_REMOVE, "remove" },
{ CMD_SAVE, "save"},
+ { CMD_SENT, "sent"},
{ CMD_PING, "ping"},
{ CMD_VIEW, "view"}
};
@@ -856,7 +858,7 @@ index_msg_cb (MuIndexStats *stats, void *user_data)
if (MU_CAUGHT_SIGNAL)
return MU_STOP;
- if (stats->_processed % 500)
+ if (stats->_processed % 1000)
return MU_OK;
send_expr ("(:info index :status running "
@@ -867,14 +869,16 @@ index_msg_cb (MuIndexStats *stats, void *user_data)
}
static MuError
-cmd_add (MuStore *store, GSList *args, GError **err)
+cmd_add_or_sent (MuStore *store, Cmd add_or_sent, GSList *args, GError **err)
{
unsigned docid;
const char *path, *maildir;
gchar *escpath;
+ g_return_val_if_fail (add_or_sent == CMD_ADD || add_or_sent == CMD_SENT,
+ MU_ERROR_INTERNAL);
return_if_fail_param_num (args, 2, 2,
- "usage: add <path> <maildir>");
+ "usage: add|sent <path> <maildir>");
path = (const char*)args->data;
maildir = (const char*)g_slist_nth (args, 1)->data;
@@ -885,15 +889,20 @@ cmd_add (MuStore *store, GSList *args, GError **err)
"failed to add path '%s'", path);
escpath = mu_str_escape_c_literal (path, TRUE);
- send_expr ("(:info add :path %s :docid %u)", escpath, docid);
+
+ if (add_or_sent == CMD_ADD)
+ send_expr ("(:info add :path %s :docid %u)",
+ escpath, docid);
+ else
+ send_expr ("(:sent t :path %s :docid %u)",
+ escpath, docid);
+
g_free (escpath);
return MU_OK;
}
-
-
static MuError
cmd_index (MuStore *store, GSList *args, GError **err)
{
@@ -953,7 +962,8 @@ handle_command (Cmd cmd, MuStore *store, MuQuery *query, GSList *args,
switch (cmd) {
- case CMD_ADD: rv = cmd_add (store, args, err); break;
+ case CMD_ADD: rv = cmd_add_or_sent (store, CMD_ADD,
+ args, err); break;
case CMD_COMPOSE: rv = cmd_compose (store, args, err); break;
case CMD_FIND: rv = cmd_find (store, query, args, err); break;
case CMD_FLAG: rv = cmd_flag (store, query, args, err); break;
@@ -964,6 +974,8 @@ handle_command (Cmd cmd, MuStore *store, MuQuery *query, GSList *args,
case CMD_QUIT: rv = cmd_quit (args, err); break;
case CMD_REMOVE: rv = cmd_remove (store, args, err); break;
case CMD_SAVE: rv = cmd_save (store, args, err); break;
+ case CMD_SENT: rv = cmd_add_or_sent (store, CMD_SENT,
+ args, err); break;
case CMD_PING: rv = cmd_ping (store, args, err); break;
case CMD_VIEW: rv = cmd_view (store, query, args, err); break;

0 comments on commit c2e3eac

Please sign in to comment.