From 6a4d6a49c49594b6feb2496d4eab462128c96b5d Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Tue, 23 Apr 2024 19:19:26 +0300 Subject: [PATCH 1/7] mu4e-compose: split off parts in mu4e-draft; rework Move draft-creation part of message-composition to a new file mu4e-drafts However, this is more than just some refactoring: rework the message (draft) setup as such to ensure we always get a (non-active, live) buffer back from the composition process. This also fixes (progn (compose-mail "test@example.org" "Test") (insert "TEST")) as mentioned on the mailing list. Fixes #2699 --- mu4e/meson.build | 1 + mu4e/mu4e-compose.el | 757 +++++------------------------------------- mu4e/mu4e-draft.el | 673 +++++++++++++++++++++++++++++++++++++ mu4e/mu4e-obsolete.el | 6 +- mu4e/mu4e.texi | 4 +- 5 files changed, 771 insertions(+), 670 deletions(-) create mode 100644 mu4e/mu4e-draft.el diff --git a/mu4e/meson.build b/mu4e/meson.build index 079e7486..a2a22bbd 100644 --- a/mu4e/meson.build +++ b/mu4e/meson.build @@ -43,6 +43,7 @@ mu4e_srcs=[ 'mu4e-contacts.el', 'mu4e-context.el', 'mu4e-contrib.el', + 'mu4e-draft.el', 'mu4e-folders.el', 'mu4e.el', 'mu4e-headers.el', diff --git a/mu4e/mu4e-compose.el b/mu4e/mu4e-compose.el index 701ed93d..f085619a 100644 --- a/mu4e/mu4e-compose.el +++ b/mu4e/mu4e-compose.el @@ -22,10 +22,9 @@ ;;; Commentary: -;; Implements mu4e-compose-mode, which is a `message-mode' derivative. This is a -;; *fairly* thin wrapper around the gnus functions for message composition, -;; integrated with mu4e. Still, quite a bit of code to make it work nicely in -;; the mu4e context. +;; Implements mu4e-compose-mode, which is a `message-mode' derivative. There's +;; quite a bit of trickery involved to make the message-mode functions work in +;; this context; see mu4e-draft for details. ;;; Code: @@ -40,124 +39,14 @@ (require 'mu4e-context) (require 'mu4e-folders) +(require 'mu4e-draft) + ;;; User configuration for compose-mode (defgroup mu4e-compose nil "Customization for composing/sending messages." :group 'mu4e) -(defcustom mu4e-sent-messages-behavior 'sent - "Determines what mu4e does with sent messages. - -This is one of the symbols: -* `sent' move the sent message to the Sent-folder (`mu4e-sent-folder') -* `trash' move the sent message to the Trash-folder (`mu4e-trash-folder') -* `delete' delete the sent message. - -Note, when using GMail/IMAP, you should set this to either -`trash' or `delete', since GMail already takes care of keeping -copies in the sent folder. - -Alternatively, `mu4e-sent-messages-behavior' can be a function -which takes no arguments, and which should return one of the mentioned -symbols, for example: - - (setq mu4e-sent-messages-behavior (lambda () - (if (string= (message-sendmail-envelope-from) \"foo@example.com\") - \\='delete \\='sent))) - -The various `message-' functions from `message-mode' are available -for querying the message information." - :type '(choice (const :tag "move message to mu4e-sent-folder" sent) - (const :tag "move message to mu4e-trash-folder" trash) - (const :tag "delete message" delete)) - :group 'mu4e-compose) - -(defcustom mu4e-compose-switch nil - "Where to display the new message? -A symbol: -- nil : default (new buffer) -- window : compose in new window -- frame or t : compose in new frame -- display-buffer: use `display-buffer' / `display-buffer-alist' - (for fine-tuning). - -For backward compatibility with `mu4e-compose-in-new-frame', t is -treated as =\\'frame." - :type 'symbol - :group 'mu4e-compose) - -(defcustom mu4e-compose-context-policy 'ask - "Policy for determining the context when composing a new message. - -If the value is `always-ask', ask the user unconditionally. - -In all other cases, if any context matches (using its match -function), this context is used. Otherwise, if none of the -contexts match, we have the following choices: - -- `pick-first': pick the first of the contexts available (ie. the default) -- `ask': ask the user -- `ask-if-none': ask if there is no context yet, otherwise leave it as it is -- nil: return nil; leaves the current context as is. - -Also see `mu4e-context-policy'." - :type '(choice - (const :tag "Always ask what context to use" always-ask) - (const :tag "Ask if none of the contexts match" ask) - (const :tag "Ask when there's no context yet" ask-if-none) - (const :tag "Pick the first context if none match" pick-first) - (const :tag "Don't change the context when none match" nil)) - :safe 'symbolp - :group 'mu4e-compose) - -(defcustom mu4e-compose-crypto-policy - '(encrypt-encrypted-replies sign-encrypted-replies) - "Policy to control when messages will be signed/encrypted. - -The value is a list which influence the way draft messages are -created. Specifically, it might contain: - -- `sign-all-messages': Always add a signature. -- `sign-new-messages': Add a signature to new message, ie. - messages that aren't responses to another message. -- `sign-forwarded-messages': Add a signature when forwarding - a message -- `sign-edited-messages': Add a signature to drafts -- `sign-all-replies': Add a signature when responding to - another message. -- `sign-plain-replies': Add a signature when responding to - non-encrypted messages. -- `sign-encrypted-replies': Add a signature when responding - to encrypted messages. - -It should be noted that certain symbols have priorities over one -another. So `sign-all-messages' implies `sign-all-replies', which -in turn implies `sign-plain-replies'. Adding both to the set, is -not a contradiction, but a redundant configuration. - -All `sign-*' options have a `encrypt-*' analogue." - :type '(set :greedy t - (const :tag "Sign all messages" sign-all-messages) - (const :tag "Encrypt all messages" encrypt-all-messages) - (const :tag "Sign new messages" sign-new-messages) - (const :tag "Encrypt new messages" encrypt-new-messages) - (const :tag "Sign forwarded messages" sign-forwarded-messages) - (const :tag "Encrypt forwarded messages" - encrypt-forwarded-messages) - (const :tag "Sign edited messages" sign-edited-messages) - (const :tag "Encrypt edited messages" edited-forwarded-messages) - (const :tag "Sign all replies" sign-all-replies) - (const :tag "Encrypt all replies" encrypt-all-replies) - (const :tag "Sign replies to plain messages" sign-plain-replies) - (const :tag "Encrypt replies to plain messages" - encrypt-plain-replies) - (const :tag "Sign replies to encrypted messages" - sign-encrypted-replies) - (const :tag "Encrypt replies to encrypted messages" - encrypt-encrypted-replies)) - :group 'mu4e-compose) - (defcustom mu4e-compose-format-flowed nil "Whether to compose messages to be sent as format=flowed. \(Or with long lines if variable `use-hard-newlines' is set to @@ -184,15 +73,6 @@ the place to do that." :group 'mu4e-compose) -;;; Runtime variables; useful for user-hooks etc. -(defvar-local mu4e-compose-parent-message nil - "The parent message plist. -This is the message being replied to, forwarded or edited; used -in `mu4e-compose-pre-hook'. For new (non-reply, forward etc.) -messages, it is nil.") - -(defvar-local mu4e-compose-type nil - "The compose-type for the current message.") (defvar mu4e-captured-message) (defun mu4e-compose-attach-captured-message () @@ -285,61 +165,6 @@ the file under our feet, which is a bit fragile." (when message-signature (save-excursion (message-insert-signature)))))))) - -;;; Filenames -(defun mu4e--message-basename() - "Construct a randomized filename for a message with flags FLAGSTR. -It looks something like -