Fix var names in doc.
[emacs.git] / lisp / textmodes / refill.el
blobe130874a2403394baa185003366ec7a1ca72008a
1 ;;; refill.el --- `auto-fill' by refilling paragraphs on changes
3 ;; Copyright (C) 2000 Free Software Foundation, Inc.
5 ;; Author: Dave Love <fx@gnu.org>
6 ;; Keywords: wp
8 ;; This program is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 2 of the License, or
11 ;; (at your option) any later version.
13 ;; This program is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with this program; if not, write to the
20 ;; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
21 ;; Boston, MA 02111-1307, USA.
23 ;;; Commentary:
25 ;; Provides a mode where paragraphs are refilled after changes in them
26 ;; (using `after-change-functions'). This gives something akin to typical
27 ;; word processor-style filling. We restrict refilling due to
28 ;; self-insertion to the characters which trigger auto-fill.
30 ;; It partly satisfies a todo item in enriched.el for some value of
31 ;; `without slowing down editing too much'. It doesn't attempt to do
32 ;; anything (using `window-size-change-functions'?) about resizing
33 ;; windows -- who cares?
35 ;; This implementation is probably fragile and missing some special
36 ;; cases -- not extensively tested. Yanking paragraph breaks, for
37 ;; instance, won't DTRT by refilling all the relevant paragraphs.
39 ;; You could do it a bit more efficiently (and robustly?) with just an
40 ;; auto-fill function, but that doesn't cope with changes other than
41 ;; through self-insertion. (Using auto-fill and after-change
42 ;; functions together didn't seem winning.) This could probably
43 ;; benefit from a less-general and faster `fill-paragraph-function',
44 ;; ideally as a primitive.
46 ;; The work is done in a local post-command hook but only if
47 ;; `refill-doit' has been set by the after-change function. Using
48 ;; `post-command-hook' ensures simply that refilling only happens
49 ;; once per command.
51 ;; [Per Abrahamsen's maniac.el does a similar thing, but operates from
52 ;; post-command-hook. I don't understand the statement in it that
53 ;; after-change-functions don't work for this purpose; perhaps there was
54 ;; some Emacs bug at the time. ISTR maniac has problems with
55 ;; whitespace at the end of paragraphs.]
57 ;;; Code:
59 (defun refill-fill-paragraph (arg)
60 "Like `fill-paragraph' but don't delete whitespace at paragraph end."
61 ;; Should probably use a text property indicating previously-filled
62 ;; stuff to avoid filling before the point of change.
63 (let ((before (point)))
64 (save-excursion
65 (forward-paragraph)
66 (skip-syntax-backward "-")
67 (let ((end (point))
68 (beg (progn (backward-paragraph) (point))))
69 (goto-char before)
70 (save-restriction
71 (if use-hard-newlines
72 (fill-region beg end arg)
73 (fill-region-as-paragraph beg end arg)))))))
75 (defvar refill-doit nil
76 "Non-nil means that `refill-post-command-function' does its processing.
77 Set by `refill-after-change-function' in `after-change-functions' and
78 unset by `refill-post-command-function' in `post-command-hook'. This
79 ensures refilling is only done once per command that causes a change,
80 regardless of the number of after-change calls from commands doing
81 complex processing.")
82 (make-variable-buffer-local 'refill-doit)
84 (defun refill-after-change-function (beg end len)
85 "Function for `after-change-functions' which just sets `refill-doit'."
86 (unless undo-in-progress
87 (setq refill-doit t)))
89 (defun refill-post-command-function ()
90 "Post-command function to do refilling (conditionally)."
91 (when refill-doit ; there was a change
92 ;; There's probably scope for more special cases here...
93 (cond
94 ((eq this-command 'self-insert-command)
95 ;; Respond to the same characters as auto-fill (other than
96 ;; newline, covered below).
97 (if (aref auto-fill-chars (char-before))
98 (refill-fill-paragraph nil)))
99 ((or (eq this-command 'quoted-insert)
100 (eq this-command 'fill-paragraph)
101 (eq this-command 'fill-region))
102 nil)
103 ((or (eq this-command 'newline)
104 (eq this-command 'newline-and-indent)
105 (eq this-command 'open-line))
106 ;; Don't zap what was just inserted.
107 (save-excursion
108 (beginning-of-line) ; for newline-and-indent
109 (skip-chars-backward "\n")
110 (save-restriction
111 (narrow-to-region (point-min) (point))
112 (refill-fill-paragraph nil)))
113 (widen)
114 (save-excursion
115 (skip-chars-forward "\n")
116 (save-restriction
117 (narrow-to-region (line-beginning-position) (point-max))
118 (refill-fill-paragraph nil))))
119 (t (refill-fill-paragraph nil)))
120 (setq refill-doit nil)))
122 (defvar refill-mode nil
123 "Non-nil if Refill mode is active. Use `refill-mode' to toggle it.")
124 (make-variable-buffer-local 'refill-mode)
126 (defvar refill-mode-hook nil
127 "Normal hook run by function `refill-mode'.")
129 (add-to-list 'minor-mode-alist '(refill-mode " Refill"))
131 ;;;###autoload
132 (define-minor-mode refill-mode
133 "Toggle Refill minor mode.
134 With prefix arg, turn Refill mode on iff arg is positive.
136 When Refill mode is on, the current paragraph will be formatted when
137 changes are made within it. Self-inserting characters only cause
138 refilling if they would cause auto-filling."
139 nil " Refill" nil
140 ;; This provides the test for recursive paragraph filling.
141 (make-local-variable 'fill-paragraph-function)
142 (if refill-mode
143 (progn
144 (add-hook 'after-change-functions 'refill-after-change-function nil t)
145 (add-hook 'post-command-hook 'refill-post-command-function nil t)
146 (set (make-local-variable 'fill-paragraph-function)
147 'refill-fill-paragraph)
148 (auto-fill-mode 0))
149 (remove-hook 'after-change-functions 'refill-after-change-function t)
150 (remove-hook 'post-command-hook 'refill-post-command-function t)
151 (setq fill-paragraph-function nil)))
153 (provide 'refill)
155 ;;; refill.el ends here