Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add another hook to "live encode" format=flow #8

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README.org
Original file line number Diff line number Diff line change
Expand Up @@ -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
74 changes: 74 additions & 0 deletions messages-are-flowing.el
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand All @@ -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 '()
"Modes to apply to when messages-are-flowing-enhance-fille-newline is in use"
:type '(repeat 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.
Expand All @@ -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