(fill-context-prefix): Fix last change with yet-another-approach.
[bpt/emacs.git] / lisp / textmodes / fill.el
CommitLineData
c0274f38
ER
1;;; fill.el --- fill commands for Emacs
2
d47e9c06
SM
3;; Copyright (C) 1985,86,92,94,95,96,97,1999,2001,2002
4;; Free Software Foundation, Inc.
f53a262d 5
6228c05b 6;; Maintainer: FSF
3a801d0c
ER
7;; Keywords: wp
8
f53a262d 9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
e5167999 13;; the Free Software Foundation; either version 2, or (at your option)
f53a262d 14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
b578f267
EN
22;; along with GNU Emacs; see the file COPYING. If not, write to the
23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24;; Boston, MA 02111-1307, USA.
f53a262d 25
e41b2db1
ER
26;;; Commentary:
27
28;; All the commands for filling text. These are documented in the Emacs
29;; manual.
30
e5167999 31;;; Code:
f53a262d 32
9d325ebf 33(defcustom fill-individual-varying-indent nil
e065a56e
JB
34 "*Controls criterion for a new paragraph in `fill-individual-paragraphs'.
35Non-nil means changing indent doesn't end a paragraph.
36That mode can handle paragraphs with extra indentation on the first line,
37but it requires separator lines between paragraphs.
9d325ebf
RS
38A value of nil means that any change in indentation starts a new paragraph."
39 :type 'boolean
40 :group 'fill)
8f985fe2 41
9d325ebf
RS
42(defcustom colon-double-space nil
43 "*Non-nil means put two spaces after a colon when filling."
44 :type 'boolean
45 :group 'fill)
68152e8f 46
86dfb30a 47(defvar fill-paragraph-function nil
3103b038
RS
48 "Mode-specific function to fill a paragraph, or nil if there is none.
49If the function returns nil, then `fill-paragraph' does its normal work.")
86dfb30a 50
c4cd8760 51(defvar enable-kinsoku t
4dc0f0fc
RS
52 "*Non-nil means enable \"kinsoku\" processing on filling paragraph.
53Kinsoku processing is designed to prevent certain characters from being
54placed at the beginning or end of a line by filling.
55See the documentation of `kinsoku' for more information.")
c9d611f4 56
f53a262d 57(defun set-fill-prefix ()
8f985fe2 58 "Set the fill prefix to the current line up to point.
54d7f650
RS
59Filling expects lines to start with the fill prefix and
60reinserts the fill prefix in each resulting line."
f53a262d 61 (interactive)
2441692d
GM
62 (let ((left-margin-pos (save-excursion (move-to-left-margin) (point))))
63 (if (> (point) left-margin-pos)
64 (progn
65 (setq fill-prefix (buffer-substring left-margin-pos (point)))
66 (if (equal fill-prefix "")
67 (setq fill-prefix nil)))
68 (setq fill-prefix nil)))
f53a262d 69 (if fill-prefix
70 (message "fill-prefix: \"%s\"" fill-prefix)
71 (message "fill-prefix cancelled")))
72
9d325ebf
RS
73(defcustom adaptive-fill-mode t
74 "*Non-nil means determine a paragraph's fill prefix from its text."
75 :type 'boolean
76 :group 'fill)
54d7f650 77
742c1822 78(defcustom adaptive-fill-regexp
d47e9c06
SM
79 ;; Added `!' for doxygen comments starting with `//!' or `/*!'.
80 ;; Added `%' for TeX comments.
81 (purecopy "[ \t]*\\([-!|#%;>*]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*")
54d7f650 82 "*Regexp to match text at start of line that constitutes indentation.
849f04e1
RS
83If Adaptive Fill mode is enabled, a prefix matching this pattern
84on the first and second lines of a paragraph is used as the
85standard indentation for the whole paragraph.
86
87If the paragraph has just one line, the indentation is taken from that
88line, but in that case `adaptive-fill-first-line-regexp' also plays
89a role."
90 :type 'regexp
91 :group 'fill)
92
21942e01 93(defcustom adaptive-fill-first-line-regexp "\\`[ \t]*\\'"
849f04e1
RS
94 "*Regexp specifying whether to set fill prefix from a one-line paragraph.
95When a paragraph has just one line, then after `adaptive-fill-regexp'
96finds the prefix at the beginning of the line, if it doesn't
97match this regexp, it is replaced with whitespace.
98
99By default, this regexp matches sequences of just spaces and tabs.
100
101However, we never use a prefix from a one-line paragraph
102if it would act as a paragraph-starter on the second line."
9d325ebf
RS
103 :type 'regexp
104 :group 'fill)
54d7f650 105
9d325ebf 106(defcustom adaptive-fill-function nil
ef4d4394 107 "*Function to call to choose a fill prefix for a paragraph, or nil.
9d325ebf 108This function is used when `adaptive-fill-regexp' does not match."
ef4d4394 109 :type '(choice (const nil) function)
9d325ebf 110 :group 'fill)
68152e8f 111
4bcb1be1 112(defvar fill-indent-according-to-mode nil ;Screws up CC-mode's filling tricks.
178932de
SM
113 "Whether or not filling should try to use the major mode's indentation.")
114
0cb08f98
RS
115(defun current-fill-column ()
116 "Return the fill-column to use for this line.
117The fill-column to use for a buffer is stored in the variable `fill-column',
118but can be locally modified by the `right-margin' text property, which is
119subtracted from `fill-column'.
120
121The fill column to use for a line is the first column at which the column
122number equals or exceeds the local fill-column - right-margin difference."
123 (save-excursion
1e87252c
RS
124 (if fill-column
125 (let* ((here (progn (beginning-of-line) (point)))
126 (here-col 0)
127 (eol (progn (end-of-line) (point)))
128 margin fill-col change col)
742c1822
DL
129 ;; Look separately at each region of line with a different
130 ;; right-margin.
1e87252c
RS
131 (while (and (setq margin (get-text-property here 'right-margin)
132 fill-col (- fill-column (or margin 0))
133 change (text-property-not-all
134 here eol 'right-margin margin))
135 (progn (goto-char (1- change))
136 (setq col (current-column))
137 (< col fill-col)))
138 (setq here change
139 here-col col))
140 (max here-col fill-col)))))
0cb08f98
RS
141
142(defun canonically-space-region (beg end)
143 "Remove extra spaces between words in region.
8c379895 144Leave one space between words, two at end of sentences or after colons
ce82deed
KH
145\(depending on values of `sentence-end-double-space', `colon-double-space',
146and `sentence-end-without-period').
34a5f45f 147Remove indentation from each line."
369aeb97 148 (interactive "*r")
bb424945
SM
149 (let ((end-spc-re (concat "\\(" sentence-end "\\) *\\| +")))
150 (save-excursion
151 (goto-char beg)
152 ;; Nuke tabs; they get screwed up in a fill.
153 ;; This is quick, but loses when a tab follows the end of a sentence.
154 ;; Actually, it is difficult to tell that from "Mr.\tSmith".
155 ;; Blame the typist.
156 (subst-char-in-region beg end ?\t ?\ )
ea9ae18a 157 (while (and (< (point) end)
bb424945
SM
158 (re-search-forward end-spc-re end t))
159 (delete-region
160 (cond
161 ;; `sentence-end' matched and did not match all spaces.
162 ;; I.e. it only matched the number of spaces it needs: drop the rest.
163 ((and (match-end 1) (> (match-end 0) (match-end 1))) (match-end 1))
164 ;; `sentence-end' matched but with nothing left. Either that means
165 ;; nothing should be removed, or it means it's the "old-style"
166 ;; sentence-end which matches all it can. Keep only 2 spaces.
167 ;; We probably don't even need to check `sentence-end-double-space'.
168 ((match-end 1)
169 (min (match-end 0)
170 (+ (if sentence-end-double-space 2 1)
171 (save-excursion (goto-char (match-end 0))
172 (skip-chars-backward " ")
173 (point)))))
174 (t ;; It's not an end of sentence.
175 (+ (match-beginning 0)
176 ;; Determine number of spaces to leave:
177 (save-excursion
178 (skip-chars-backward " ]})\"'")
179 (cond ((and sentence-end-double-space
180 (or (memq (preceding-char) '(?. ?? ?!))
181 (and sentence-end-without-period
182 (= (char-syntax (preceding-char)) ?w)))) 2)
183 ((and colon-double-space
184 (= (preceding-char) ?:)) 2)
185 ((char-equal (preceding-char) ?\n) 0)
186 (t 1))))))
187 (match-end 0))))))
0cb08f98 188
7190ab87
GM
189(defun fill-common-string-prefix (s1 s2)
190 "Return the longest common prefix of strings S1 and S2, or nil if none."
191 (let ((cmp (compare-strings s1 nil nil s2 nil nil)))
178932de 192 (if (eq cmp t)
7190ab87
GM
193 s1
194 (setq cmp (1- (abs cmp)))
195 (unless (zerop cmp)
196 (substring s1 0 cmp)))))
197
0bcfa3ac 198(defun fill-context-prefix (from to &optional first-line-regexp)
d09d7ba9 199 "Compute a fill prefix from the text between FROM and TO.
39f5988d 200This uses the variables `adaptive-fill-regexp' and `adaptive-fill-function'
849f04e1
RS
201and `adaptive-fill-first-line-regexp'. `paragraph-start' also plays a role;
202we reject a prefix based on a one-line paragraph if that prefix would
203act as a paragraph-separator."
204 (or first-line-regexp
205 (setq first-line-regexp adaptive-fill-first-line-regexp))
d09d7ba9
RS
206 (save-excursion
207 (goto-char from)
208 (if (eolp) (forward-line 1))
209 ;; Move to the second line unless there is just one.
6d1f0a5e 210 (move-to-left-margin)
0bcfa3ac 211 (let ((firstline (point))
b5263b80 212 first-line-prefix
0bcfa3ac 213 ;; Non-nil if we are on the second line.
b5263b80
RS
214 second-line-prefix
215 start)
b5263b80
RS
216 (setq start (point))
217 (setq first-line-prefix
3212cc84
SM
218 ;; We don't need to consider `paragraph-start' here since it
219 ;; will be explicitly checked later on.
220 ;; Also setting first-line-prefix to nil prevents
221 ;; second-line-prefix from being used.
222 (cond ;; ((looking-at paragraph-start) nil)
b5263b80 223 ((and adaptive-fill-regexp (looking-at adaptive-fill-regexp))
03e3e2e9 224 (match-string-no-properties 0))
b5263b80 225 (adaptive-fill-function (funcall adaptive-fill-function))))
d09d7ba9 226 (forward-line 1)
03e3e2e9
SM
227 (if (< (point) to)
228 (progn
dc864d6e
SM
229 (move-to-left-margin)
230 (setq start (point))
231 (setq second-line-prefix
232 (cond ((looking-at paragraph-start) nil) ;Can it happen ? -stef
233 ((and adaptive-fill-regexp
234 (looking-at adaptive-fill-regexp))
235 (buffer-substring-no-properties start (match-end 0)))
236 (adaptive-fill-function
237 (funcall adaptive-fill-function))))
b5263b80
RS
238 ;; If we get a fill prefix from the second line,
239 ;; make sure it or something compatible is on the first line too.
03e3e2e9
SM
240 (when second-line-prefix
241 (unless first-line-prefix (setq first-line-prefix ""))
dc864d6e
SM
242 ;; If the non-whitespace chars match the first line,
243 ;; just use it (this subsumes the 2 checks used previously).
244 ;; Used when first line is `/* ...' and second-line is
245 ;; ` * ...'.
246 (let ((tmp second-line-prefix)
247 (re "\\`"))
248 (while (string-match "\\`[ \t]*\\([^ \t]+\\)" tmp)
249 (setq re (concat re ".*" (regexp-quote (match-string 1 tmp))))
250 (setq tmp (substring tmp (match-end 0))))
251 ;; (assert (string-match "\\`[ \t]*\\'" tmp))
03e3e2e9 252
dc864d6e
SM
253 (if (string-match re first-line-prefix)
254 second-line-prefix
7190ab87 255
dc864d6e
SM
256 ;; Use the longest common substring of both prefixes,
257 ;; if there is one.
258 (fill-common-string-prefix first-line-prefix
259 second-line-prefix)))))
b5263b80
RS
260 ;; If we get a fill prefix from a one-line paragraph,
261 ;; maybe change it to whitespace,
262 ;; and check that it isn't a paragraph starter.
263 (if first-line-prefix
264 (let ((result
265 ;; If first-line-prefix comes from the first line,
266 ;; see if it seems reasonable to use for all lines.
267 ;; If not, replace it with whitespace.
268 (if (or (and first-line-regexp
269 (string-match first-line-regexp
270 first-line-prefix))
271 (and comment-start-skip
272 (string-match comment-start-skip
273 first-line-prefix)))
274 first-line-prefix
275 (make-string (string-width first-line-prefix) ?\ ))))
276 ;; But either way, reject it if it indicates the start
277 ;; of a paragraph when text follows it.
278 (if (not (eq 0 (string-match paragraph-start
279 (concat result "a"))))
44a0dbd7 280 result)))))))
d09d7ba9 281
03e3e2e9
SM
282(defun fill-single-word-nobreak-p ()
283 "Don't break a line after the first or before the last word of a sentence."
284 (or (looking-at "[ \t]*\\sw+[ \t]*[.?!:][ \t]*$")
285 (save-excursion
286 (skip-chars-backward " \t")
287 (and (/= (skip-syntax-backward "w") 0)
288 (/= (skip-chars-backward " \t") 0)
289 (/= (skip-chars-backward ".?!:") 0)))))
290
291(defun fill-french-nobreak-p ()
292 "Return nil if French style allows breaking the line at point.
293This is used in `fill-nobreak-predicate' to prevent breaking lines just
294after an opening paren or just before a closing paren or a punctuation
295mark such as `?' or `:'. It is common in French writing to put a space
296at such places, which would normally allow breaking the line at those
297places."
298