From a4ca32088f7b1a68be9adef0ad3f09244654aef7 Mon Sep 17 00:00:00 2001 From: Wade Berrier Date: Thu, 18 Oct 2018 20:40:11 -0600 Subject: [PATCH] Add another hook to "live encode" format=flow based off some code at: https://emacs.stackexchange.com/questions/19296/retooling-fill-paragraph-to-append-trailing-spaces --- README.org | 18 ++++++++++ messages-are-flowing.el | 74 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/README.org b/README.org index b74a966..10b531a 100644 --- a/README.org +++ b/README.org @@ -26,5 +26,23 @@ then add the following to your =.emacs= file: (add-hook 'message-mode-hook 'messages-are-flowing-use-and-mark-hard-newlines) #+END_SRC +This package also supports inserting spaces for soft newlines via the +following: + +#+BEGIN_SRC emacs-lisp +(add-hook 'message-mode-hook 'messages-are-flowing-enhance-fill-newline) +#+END_SRC + +NOTE: the modes need to be specified when to use the enhanced +fill-newline: + +#+BEGIN_SRC emacs-lisp +(use-package messages-are-flowing + :custom (messages-are-flowing-enhance-fill-newline-modes '(message-mode)) +) +#+END_SRC + +This can be useful if using a mailer that does not post-encode the +text (ie: mutt). #+STARTUP: showall diff --git a/messages-are-flowing.el b/messages-are-flowing.el index 862c0f1..b19329b 100644 --- a/messages-are-flowing.el +++ b/messages-are-flowing.el @@ -42,6 +42,14 @@ ;; ;; (with-eval-after-load "message" ;; (add-hook 'message-mode-hook 'messages-are-flowing-use-and-mark-hard-newlines)) +;; +;; If your mail program does not encode the flowed format, the following +;; can be used to convert soft newlines to spaces: +;; +;; (add-hook 'message-mode-hook 'messages-are-flowing-enhance-fill-newline) +;; +;; Also note that messages-are-flowing-enhance-fill-newline-modes will need to +;; be set with the modes the enhanced fill-newline should be used in ;;; Code: @@ -55,6 +63,23 @@ device, such that messages remain readable on narrow displays." (use-hard-newlines) (add-hook 'after-change-functions 'messages-are-flowing--mark-hard-newlines nil t)) +;;;###autoload +(defun messages-are-flowing-enhance-fill-newline () + "Function to enhance fill-newline, only for certain modes" + (advice-add 'fill-newline :around #'messages-are-flowing--fill-newline-wrapper) + (turn-off-auto-fill) + ) + +(defgroup messages-are-flowing nil + "Utilities for working with format=flowed messages" + ) + +(defcustom messages-are-flowing-enhance-fill-newline-modes nil + "Modes to apply to when messages-are-flowing-enhance-fille-newline is in use" + :type 'function + :group 'messages-are-flowing) + + (defun messages-are-flowing--mark-hard-newlines (beg end &rest _ignore) "Visibly mark hard newlines between BEG and END. For each hard newline, add a display property that makes it visible. @@ -70,5 +95,54 @@ For each soft newline, remove any display property." (add-text-properties pos (1+ pos) (list 'display (copy-sequence "⏎\n"))) (remove-text-properties pos (1+ pos) '(display nil))))))) + +;; fill-newline that puts a space for soft newlines +;; Based on https://emacs.stackexchange.com/questions/19296/retooling-fill-paragraph-to-append-trailing-spaces +(defun messages-are-flowing--fill-newline () + "Custom version of fill-newline to behave 3676ishly" + + ;; 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))) + +(defun messages-are-flowing--fill-newline-wrapper (orig-fun &rest args) + "Call [messages-are-flowing--]fill-newline depending on mode" + + ;; NOTE: this is done so that it doesn't affect other modes + (if (member major-mode messages-are-flowing-enhance-fill-newline-modes) + (progn ;; allow multiple statements + ;; Alter fill-newline + (messages-are-flowing--fill-newline) + ) + (apply orig-fun args) + ) + ) + (provide 'messages-are-flowing) ;;; messages-are-flowing.el ends here