# HG changeset patch # User Dave Love # Date 972232099 0 # Node ID dd36de87245d363a1b53859e0562dfe7e493ad6a # Parent a1310ae577487136af9670dfb22806cd042e81ac *** empty log message *** diff -r a1310ae57748 -r dd36de87245d lisp/ChangeLog --- a/lisp/ChangeLog Sun Oct 22 15:45:05 2000 +0000 +++ b/lisp/ChangeLog Sun Oct 22 16:28:19 2000 +0000 @@ -1,3 +1,7 @@ +2000-10-22 Dave Love + + * textmodes/refill.el: New file. + 2000-10-22 Andre Spiegel * vc-hooks.el (vc-version-backup-file-name): New optional args diff -r a1310ae57748 -r dd36de87245d lisp/textmodes/refill.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/textmodes/refill.el Sun Oct 22 16:28:19 2000 +0000 @@ -0,0 +1,156 @@ +;;; refill.el --- `auto-fill' by refilling paragraphs on changes + +;; Copyright (C) 2000 Free Software Foundation, Inc. + +;; Author: Dave Love +;; Keywords: wp + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the +;; Free Software Foundation, Inc., 59 Temple Place, Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Provides a mode where paragraphs are refilled after changes in them +;; (using `after-change-hooks'). This gives something akin to typical +;; word processor-style filling. We restrict refilling due to +;; self-insertion to the characters which trigger auto-fill. + +;; It partly satisfies a todo item in enriched.el for some value of +;; `without slowing down editing too much'. It doesn't attempt to do +;; anything (using `window-size-change-functions'?) about resizing +;; windows -- who cares? + +;; This implementation is probably fragile and missing some special +;; cases -- not extensively tested. Yanking paragraph breaks, for +;; instance, won't DTRT by refilling all the relevant paragraphs. + +;; You could do it a bit more efficiently (and robustly?) with just an +;; auto-fill function, but that doesn't cope with changes other than +;; through self-insertion. (Using auto-fill and after-change +;; functions together didn't seem winning.) This could probably +;; benefit from a less-general and faster `fill-paragraph-function', +;; ideally as a primitive. + +;; The work is done in a local post-command hook but only if +;; `refill-doit' has been set by the after-change function. Using +;; `post-command-hooks' ensures simply that refilling only happens +;; once per command. + +;; [Per Abrahamsen's maniac.el does a similar thing, but operates from +;; post-command-hook. I don't understand the statement in it that +;; after-change-hooks don't work for this purpose; perhaps there was +;; some Emacs bug at the time. ISTR maniac has problems with +;; whitespace at the end of paragraphs.] + +;;; Code: + +(defun refill-fill-paragraph (arg) + "Like `fill-paragraph' but don't delete whitespace at paragraph end." + ;; Should probably use a text property indicating previously-filled + ;; stuff to avoid filling before the point of change. + (let ((before (point))) + (save-excursion + (forward-paragraph) + (skip-syntax-backward "-") + (let ((end (point)) + (beg (progn (backward-paragraph) (point)))) + (goto-char before) + (save-restriction + (if use-hard-newlines + (fill-region beg end arg) + (fill-region-as-paragraph beg end arg))))))) + +(defvar refill-doit nil + "Non-nil means that `refill-post-command-function' does its processing. +Set by `refill-after-change-function' in `after-change-hooks' and +unset by `refill-post-command-function' in `post-command-hooks'. This +ensures refilling is only done once per command that causes a change, +regardless of the number of after-change calls from commands doing +complex processing.") +(make-variable-buffer-local 'refill-doit) + +(defun refill-after-change-function (beg end len) + "Function for `after-change-functions' which just sets `refill-doit'." + (unless undo-in-progress + (setq refill-doit t))) + +(defun refill-post-command-function () + "Post-command function to do refilling (conditionally)." + (when refill-doit ; there was a change + ;; There's probably scope for more special cases here... + (cond + ((eq this-command 'self-insert-command) + ;; Respond to the same characters as auto-fill (other than + ;; newline, covered below). + (if (aref auto-fill-chars (char-before)) + (refill-fill-paragraph nil))) + ((or (eq this-command 'quoted-insert) + (eq this-command 'fill-paragraph) + (eq this-command 'fill-region)) + nil) + ((or (eq this-command 'newline) + (eq this-command 'newline-and-indent) + (eq this-command 'open-line)) + ;; Don't zap what was just inserted. + (save-excursion + (beginning-of-line) ; for newline-and-indent + (skip-chars-backward "\n") + (save-restriction + (narrow-to-region (point-min) (point)) + (refill-fill-paragraph nil))) + (widen) + (save-excursion + (skip-chars-forward "\n") + (save-restriction + (narrow-to-region (line-beginning-position) (point-max)) + (refill-fill-paragraph nil)))) + (t (refill-fill-paragraph nil))) + (setq refill-doit nil))) + +(defvar refill-mode nil + "Non-nil if Refill mode is active. Use `refill-mode' to toggle it.") +(make-variable-buffer-local 'refill-mode) + +(defvar refill-mode-hook nil + "Normal hook run by function `refill-mode'.") + +(add-to-list 'minor-mode-alist '(refill-mode " Refill")) + +;;;###autoload +(define-minor-mode refill-mode + "Toggle Refill minor mode. +With prefix arg, turn Refill mode on iff arg is positive. + +When Refill mode is on, the current paragraph will be formatted when +changes are made within it. Self-inserting characters only cause +refilling if they would cause auto-filling." + nil " Refill" nil + ;; This provides the test for recursive paragraph filling. + (make-local-variable 'fill-paragraph-function) + (if refill-mode + (progn (add-hook (make-local-hook 'after-change-functions) + 'refill-after-change-function nil t) + (add-hook (make-local-hook 'post-command-hook) + 'refill-post-command-function nil t) + (set (make-local-variable 'fill-paragraph-function) + 'refill-fill-paragraph) + (auto-fill-mode 0)) + (remove-hook 'after-change-functions 'refill-after-change-function t) + (remove-hook 'post-command-hook 'refill-post-command-function t) + (setq fill-paragraph-function nil))) + +(provide 'refill) + +;;; refill.el ends here