32750
|
1 ;;; refill.el --- `auto-fill' by refilling paragraphs on changes
|
|
2
|
|
3 ;; Copyright (C) 2000 Free Software Foundation, Inc.
|
|
4
|
|
5 ;; Author: Dave Love <fx@gnu.org>
|
|
6 ;; Keywords: wp
|
|
7
|
|
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.
|
|
12 ;;
|
|
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.
|
|
17 ;;
|
|
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.
|
|
22
|
|
23 ;;; Commentary:
|
|
24
|
|
25 ;; Provides a mode where paragraphs are refilled after changes in them
|
|
26 ;; (using `after-change-hooks'). 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.
|
|
29
|
|
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?
|
|
34
|
|
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.
|
|
38
|
|
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.
|
|
45
|
|
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-hooks' ensures simply that refilling only happens
|
|
49 ;; once per command.
|
|
50
|
|
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-hooks 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.]
|
|
56
|
|
57 ;;; Code:
|
|
58
|
|
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)))))))
|
|
74
|
|
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-hooks' and
|
|
78 unset by `refill-post-command-function' in `post-command-hooks'. 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)
|
|
83
|
|
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)))
|
|
88
|
|
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)))
|
|
121
|
|
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)
|
|
125
|
|
126 (defvar refill-mode-hook nil
|
|
127 "Normal hook run by function `refill-mode'.")
|
|
128
|
|
129 (add-to-list 'minor-mode-alist '(refill-mode " Refill"))
|
|
130
|
|
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.
|
|
135
|
|
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 (add-hook (make-local-hook 'after-change-functions)
|
|
144 'refill-after-change-function nil t)
|
|
145 (add-hook (make-local-hook 'post-command-hook)
|
|
146 'refill-post-command-function nil t)
|
|
147 (set (make-local-variable 'fill-paragraph-function)
|
|
148 'refill-fill-paragraph)
|
|
149 (auto-fill-mode 0))
|
|
150 (remove-hook 'after-change-functions 'refill-after-change-function t)
|
|
151 (remove-hook 'post-command-hook 'refill-post-command-function t)
|
|
152 (setq fill-paragraph-function nil)))
|
|
153
|
|
154 (provide 'refill)
|
|
155
|
|
156 ;;; refill.el ends here
|