diff --git a/mu4e/mu4e-compose.el b/mu4e/mu4e-compose.el index 96fdb897..963aef69 100644 --- a/mu4e/mu4e-compose.el +++ b/mu4e/mu4e-compose.el @@ -143,6 +143,15 @@ Also see `mu4e-context-policy'." :safe 'symbolp :group 'mu4e-compose)) +(defcustom mu4e-compose-format-flowed nil + "Whether to compose messages to be sent as format=flowed (or + with long lines if `use-hard-newlines' is set to nil). The + variable `fill-flowed-encode-column' lets you customize the + width beyond which format=flowed lines are wrapped." + :type 'boolean + :safe 'booleanp + :group 'mu4e-compose) + (defcustom mu4e-compose-pre-hook nil "Hook run just *before* message composition starts. If the compose-type is either 'reply' or 'forward', the variable @@ -315,8 +324,30 @@ message-thread by removing the In-Reply-To header." (define-key map (kbd "C-S-u") 'mu4e-update-mail-and-index) (define-key map (kbd "C-c C-u") 'mu4e-update-mail-and-index) (define-key map (kbd "C-c C-k") 'mu4e-message-kill-buffer) + (define-key map (kbd "M-q") 'mu4e-fill-paragraph) map))) +(defun mu4e-fill-paragraph (&optional region) + "If `use-hard-newlines', takes a multi-line paragraph and makes +it into a single line of text. Assume paragraphs are separated +by blank lines. If `use-hard-newlines' is not enabled, this +simply executes `fill-paragraph'." + ;; Inspired by https://www.emacswiki.org/emacs/UnfillParagraph + (interactive (progn (barf-if-buffer-read-only) '(t))) + (if mu4e-compose-format-flowed + (let ((fill-column (point-max)) + (use-hard-newlines nil)); rfill "across" hard newlines + (fill-paragraph nil region)) + (fill-paragraph nil region))) + +(defun mu4e-toggle-use-hard-newlines () + (interactive) + (setq use-hard-newlines (not use-hard-newlines)) + (if use-hard-newlines + (turn-off-auto-fill) + (turn-on-auto-fill))) + + (defvar mu4e-compose-mode-abbrev-table nil) (define-derived-mode mu4e-compose-mode message-mode "mu4e:compose" "Major mode for the mu4e message composition, derived from `message-mode'. @@ -346,12 +377,34 @@ message-thread by removing the In-Reply-To header." (when mu4e-compose-complete-addresses (mu4e~compose-setup-completion)) + (when mu4e-compose-format-flowed + (turn-off-auto-fill) + (setq truncate-lines nil + word-wrap t + use-hard-newlines t) + ;; Set the marks in the fringes before activating visual-line-mode + (set (make-local-variable 'visual-line-fringe-indicators) + '(left-curly-arrow right-curly-arrow)) + (visual-line-mode t)) + + (define-key-after + (lookup-key message-mode-map [menu-bar text]) + [mu4e-hard-newlines] + '(menu-item "Format=flowed" mu4e-toggle-use-hard-newlines + :button (:toggle . use-hard-newlines) + :help "Toggle format=flowed" + :visible (eq major-mode 'mu4e-compose-mode) + :enable mu4e-compose-format-flowed) + 'sep) + ;; setup the fcc-stuff, if needed (add-hook 'message-send-hook (lambda () ;; mu4e~compose-save-before-sending ;; when in-reply-to was removed, remove references as well. (when (eq mu4e~compose-type 'reply) (mu4e~remove-refs-maybe)) + (when use-hard-newlines + (mu4e-send-harden-newlines)) ;; for safety, always save the draft before sending (set-buffer-modified-p t) (save-buffer) @@ -366,6 +419,13 @@ message-thread by removing the In-Reply-To header." ;; (put 'mu4e~compose-save-before-sending 'permanent-local-hook t) (put 'mu4e~compose-mark-after-sending 'permanent-local-hook t)) +(defun mu4e-send-harden-newlines () + "Set the hard property to all newlines." + (save-excursion + (goto-char (point-min)) + (while (search-forward "\n" nil t) + (put-text-property (1- (point)) (point) 'hard t)))) + (defconst mu4e~compose-buffer-max-name-length 30 "Maximum length of the mu4e-send-buffer-name.") diff --git a/mu4e/mu4e.texi b/mu4e/mu4e.texi index e5727d52..4ce797fd 100644 --- a/mu4e/mu4e.texi +++ b/mu4e/mu4e.texi @@ -3840,21 +3840,27 @@ don't have it, your mails mostly look quite bad especially on mobile devices) and here's the RFC with all the details: @url{http://www.ietf.org/rfc/rfc2646.txt}. -To add this to outgoing mu4e emails, activate @t{use-hard-newlines} and -use only @t{M-q} or @t{fill-paragraph} for your paragraphs, Emacs -indicates intra-paragraph breaks with soft newlines and inter-paragraph -breaks with hard newlines. When the Gnus code sees these on outgoing -emails, it automatically sets @t{format=flowed}. - -To enable this, you can use something like this in your init.el: +Since version 0.9.17, @t{mu4e} send emails with @t{format=flowed} by +setting @lisp -;; tip submitted by mu4e user cpbotha -(add-hook 'mu4e-compose-mode-hook - (defun cpb-compose-setup () - "Outgoing mails get format=flowed." - (use-hard-newlines t 'guess))) +(setq mu4e-compose-format-flowed t) @end lisp + +in your Emacs init file (@file{~/.emacs} or @file{~/.emacs.d/init.el}). +The transformation of your message into the proper format is +done at the time of sending. In order to happen properly, you should +write each paragraph of your message of as a long line (i.e. without +carriage return). If you introduce unwanted newlines in your paragraph, +use @kbd{M-q} to reformat it as a single line. + +If you want to send the message with paragraphs on single lines but +without @t{format=flowed} (because, say, the receiver does not +understand the latter as it is the case for Google or Github), use +@kbd{M-x use-hard-newlines} (to turn @code{use-hard-newlines} off) or +uncheck the box @t{format=flowed} in the @t{Text} menu when composing a +message. + @end enumerate @node Known issues