6

I'm using emacs as an external editor for mutt, and am hoping to get format=flowed messages to compose properly. The default behavior for fill-paragraph is to end lines without any whitespace, but the format=flowed style as detailed in RFC 2646 and 3676 requires trailing spaces before "soft" newlines. Is there an easy modification to append a space before every newline added by fill-paragraph? My elisp skill is quite limited.

To elaborate on specifically what kind of text is wanted, RFC 3676 establishes the "format=flowed" parameter to MIME type text/plain to describe text that flows well both on devices that automatically line-wrap and those that don't. The salient idea is that a newline immediately following a space is considered a "soft" newline, one provided for line-wrapping for display on devices which don't automatically line-wrap, and that other devices are free to remove this newline and to wrap text according to their own preferences. A newline without a preceding space is a "hard" newline, one meant to be rendered as a newline regardless of the line-width or wrap capabilities of the display.

So from a text processing point of view, what I'd like for format=flowed text is for fill-paragraph to precede every intra-paragraph line break with at least one whitespace, while leaving the end-of-paragraph line break with no whitespace preceding it. All of this of course could be done with post-processing search-and-replace on all my messages, but it seems like it should be possible to dothis with some appropriate modification of fill-paragraph.

  • 1
    Could you include a short explanation of flowed text to add some context to the problem? I skimmed some of RFC 3676 and it was new to me :-) This page has some information about that struggle with gnus: emacswiki.org/emacs/GnusFormatFlowed (the recommendation seems to be to avoid it ;-) – ebpa Jan 6 '16 at 6:51
  • You didn't mention it, but I assume any correct solution needs to work even for paragraphs indented by any depth of the > quoting prefix. – Adam Spiers Dec 13 '16 at 11:28
  • See also stackoverflow.com/questions/41299350/… which asks a related question without stipulating that the answer should involve fill-paragraph. – Adam Spiers Oct 3 '17 at 22:42
  • I have just created emacswiki.org/emacs/FormatFlowed as a central portal in order to try to collect info on this topic in a single place. – Adam Spiers Oct 4 '17 at 11:47
1

I've kludged together a solution; posting it here for the edification of anyone who might find it handy. It's a complete redefinition of fill-newline which adds a space at the end, and it almost certainly breaks some other things, but since I use it in a very limited context, it doesn't seem to end up causing trouble. Duplicate at your own risk, of course. I added the following to my .emacs:

(defun my-message-configuration ()
  "Redefines fill-newline to beahve 3676ishly, and turns off auto fill"
  (turn-off-auto-fill)
(defun fill-newline ()
  ;; Replace whitespace here with one newline, then
  ;; indent to left margin.
  (skip-chars-backward " \t")
  (insert ?\s)
  (insert ?\n)
  ;; Give newline the properties of the space(s) it replaces
  (set-text-properties (1- (point)) (point)
               (fill-text-properties-at (point)))
  (and (looking-at "\\( [ \t]*\\)\\(\\c|\\)?")
       (or (aref (char-category-set (or (char-before (1- (point))) ?\000)) ?|)
       (match-end 2))
       ;; When refilling later on, this newline would normally not be replaced
       ;; by a space, so we need to mark it specially to re-install the space
       ;; when we unfill.
       (put-text-property (1- (point)) (point) 'fill-space (match-string 1)))
  ;; If we don't want breaks in invisible text, don't insert
  ;; an invisible newline.
  (if fill-nobreak-invisible
      (remove-text-properties (1- (point)) (point)
                  '(invisible t)))
  (if (or fill-prefix
      (not fill-indent-according-to-mode))
      (fill-indent-to-left-margin)
    (indent-according-to-mode))
  ;; Insert the fill prefix after indentation.
  (and fill-prefix (not (equal fill-prefix ""))
       ;; Markers that were after the whitespace are now at point: insert
       ;; before them so they don't get stuck before the prefix.
       (insert-before-markers-and-inherit fill-prefix)))
)

(add-hook 'message-mode-hook 'my-message-configuration)

The only real change this makes to fill-newline is the (insert ?\s) before the newline insert. As I said, an ugly hack which might well break any other code which expects fill-newline to behave conventionally, and I'd welcome a less dirty way to achieve the same result, but for now this works.

  • 1
    what you want is easy to do. You can simply replace newline by space+newline, except the last one. Recently i also wrote a different version, maybe it might be of use. ergoemacs.org/emacs/emacs_reformat_lines.html the idea is that, the default fill-region do smart things. my version only does exchange whitespaces with newline. – Xah Lee Jul 21 '16 at 5:56
  • @XahLee Thanks! This probably deserves to be a separate answer. I commented on your page with a couple of questions. It would be great to have a single solution for all emacs users which works with quoting and is easily available as a package. – Adam Spiers Dec 13 '16 at 11:30
  • Hmm, at the time I wrote the above comment I was under the impression that ergoemacs.org/emacs/emacs_reformat_lines.html was specifically targetting the format=flowed scenario, but actually it's intended for refilling code. I guess the critical part of the suggestion in the above comment was "You can simply replace newline by space+newline", meaning that that should be done via a modified version of xah-reformat-lines. – Adam Spiers Oct 3 '17 at 22:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.