diff --git a/mu4e/mu4e-compose.el b/mu4e/mu4e-compose.el index f085619a..142b74e5 100644 --- a/mu4e/mu4e-compose.el +++ b/mu4e/mu4e-compose.el @@ -72,6 +72,25 @@ the place to do that." :type 'hook :group 'mu4e-compose) +(defcustom mu4e-compose-post-hook + (list + ;; kill compose frames + #'mu4e-compose-post-kill-frame + ;; attempt to restore the old configuration. + #'mu4e-compose-post-restore-window-configuration) + "Hook run *after* message composition is over. + +This is hook is run when composition buffer, +either by sending, postponing, exiting or killing it. + +This multiplexes the `message-mode' hooks `message-send-actions', +`message-postpone-actions', `message-exit-actions' and +`message-kill-actions', and the hook is run with a variable +`mu4e-compose-post-trigger' set correspondingly to a symbol, +`send', `postpone', `exit' or `kill'." + :type 'hook + :group 'mu4e-compose) + (defvar mu4e-captured-message) diff --git a/mu4e/mu4e-draft.el b/mu4e/mu4e-draft.el index c8200bd4..5e30710d 100644 --- a/mu4e/mu4e-draft.el +++ b/mu4e/mu4e-draft.el @@ -606,22 +606,79 @@ COMPOSE-TYPE and PARENT are as in `mu4e--draft'." (set-buffer-modified-p nil) (undo-boundary)) -(defun mu4e--prepare-message-actions (oldframe) - "Set up some message actions. -In particular, handle closing frames when we created it. OLDFRAME -is the frame from which the message-composition was triggered." - (let* ((msgframe (selected-frame)) - (maybe-kill-frame ;; kill frame when it was created for this - (lambda () - (when (and (frame-live-p msgframe) (not (eq oldframe msgframe))) - (delete-frame msgframe))))) +;; +;; mu4e-compose-pos-hook helpers + +(defvar mu4e--before-draft-window-config nil + "The window configuration just before creating the draft.") + +(defun mu4e-compose-post-restore-window-configuration() + "Function that perhaps restores the window configuration. +I.e. the configuration just before the draft buffer appeared. +This is for use in `mu4e-compose-post-hook'. +See `set-window-configuration' for further details." + (when mu4e--before-draft-window-config + ;;(message "RESTORE to %s" mu4e--before-draft-window-config) + (set-window-configuration mu4e--before-draft-window-config) + (setq mu4e--before-draft-window-config nil))) + +(defvar mu4e--draft-activation-frame nil + "Frame from which composition was activated. +Used internally for mu4e-compose-post-kill-frame.") + +(defun mu4e-compose-post-kill-frame () + "Function that perhaps kills the composition frame. +This is for use in `mu4e-compose-post-hook'." + (let ((msgframe (selected-frame))) + ;;(message "kill frame? %s %s" mu4e--draft-activation-frame msgframe) + (when (and (frame-live-p msgframe) + (not (eq mu4e--draft-activation-frame msgframe))) + (delete-frame msgframe)))) + +(defvar mu4e-message-post-action nil + "Runtime variable for use with `mu4e-compose-post-hook'. +It contains a symbol denoting the action that triggered the hook, +either `send', `exit', `kill' or `postpone'.") + +(defvar mu4e-compose-post-hook) +(defun mu4e--message-post-actions (trigger) + "Invoked after we're done with a message. + +I.e. this multiplexes the `message-(send|exit|kill|postpone)-actions'; +with the mu4e-message-post-action set accordingly." + (setq mu4e-message-post-action trigger) + (run-hooks 'mu4e-compose-post-hook)) + +(defun mu4e--prepare-post (&optional oldframe oldwindconf) + "Prepare the `mu4e-compose-post-hook` handling. + +Set up some message actions. In particular, handle closing frames +when we created it. OLDFRAME is the frame from which the +message-composition was triggered. OLDWINDCONF is the current +window configuration." + ;; remember current frame & window conf + (setq mu4e--draft-activation-frame oldframe + mu4e--before-draft-window-config oldwindconf) + + ;; make message's "post" hooks local, and multiplex them (make-local-variable 'message-send-actions) + (make-local-variable 'message-postpone-actions) (make-local-variable 'message-exit-actions) (make-local-variable 'message-kill-actions) - (make-local-variable 'message-postpone-actions) - (add-to-list 'message-kill-actions maybe-kill-frame) - (add-to-list 'message-postpone-actions maybe-kill-frame))) + (push (lambda () (mu4e--message-post-actions 'send)) + message-send-actions) + (push (lambda () (mu4e--message-post-actions 'postpone)) + message-postpone-actions) + (push (lambda () (mu4e--message-post-actions 'exit)) + message-exit-actions) + (push (lambda () (mu4e--message-post-actions 'kill)) + message-kill-actions)) + +;; +;; creating drafts +;; + (defun mu4e--draft (compose-type compose-func &optional parent) "Create a new message draft. @@ -645,9 +702,11 @@ Returns the new buffer." ;; a temp buffer with contains the parent-message, if any. if there's a ;; PARENT, load the corresponding message into a temp-buffer before calling ;; compose-func - (let ((draft-buffer) (oldframe (selected-frame))) + (let ((draft-buffer) + (oldframe (selected-frame)) + (oldwinconf (current-window-configuration))) (with-temp-buffer - ;; provide a temp buffer so the compose-func can do its thing. without + ;; provide a temp buffer so the compose-func can do its thing. withou ;; interference. (setq draft-buffer (mu4e--validate-hidden-buffer (funcall compose-func))) (with-current-buffer draft-buffer @@ -660,7 +719,7 @@ Returns the new buffer." (pop-to-buffer draft-buffer) (mu4e-display-buffer draft-buffer 'do-select)) ;; prepare possible message actions (such as cleaning-up) - (mu4e--prepare-message-actions oldframe) + (mu4e--prepare-post oldframe oldwinconf) draft-buffer)) (defun mu4e--draft-with-parent (compose-type parent compose-func) diff --git a/mu4e/mu4e.texi b/mu4e/mu4e.texi index de057d40..e3e226c6 100644 --- a/mu4e/mu4e.texi +++ b/mu4e/mu4e.texi @@ -1798,11 +1798,15 @@ value of various properties (and see @ref{Message functions}). starts, when the whole buffer has already been set up. This is a good place for editing-related settings. @code{mu4e-compose-parent-message} (see above) is also at your disposal. +@item @code{mu4e-compose-post-hook}: this hook is run when we're done with +message compositions. See the docstring for details. @end itemize @noindent -Let's look at an examples. As mentioned, @code{mu4e-compose-mode-hook} is especially -useful for editing-related settings. For example: +As mentioned, @code{mu4e-compose-mode-hook} is especially useful for +editing-related settings: + +Let's look at an example: @lisp (add-hook 'mu4e-compose-mode-hook (defun my-do-compose-stuff () @@ -1811,7 +1815,7 @@ useful for editing-related settings. For example: (flyspell-mode))) @end lisp -This hook is also useful for adding headers or changing headers, since the +The hook is also useful for adding headers or changing headers, since the message is fully formed when this hook runs. For example, to add a @t{Bcc:}-header, you could add something like the following, using @code{message-add-header} from @code{message-mode}.