Commit | Line | Data |
---|---|---|
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'. |
35 | Non-nil means changing indent doesn't end a paragraph. | |
36 | That mode can handle paragraphs with extra indentation on the first line, | |
37 | but it requires separator lines between paragraphs. | |
9d325ebf RS |
38 | A 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. |
49 | If 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. |
53 | Kinsoku processing is designed to prevent certain characters from being | |
54 | placed at the beginning or end of a line by filling. | |
55 | See 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 |
59 | Filling expects lines to start with the fill prefix and |
60 | reinserts 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 |
83 | If Adaptive Fill mode is enabled, a prefix matching this pattern |
84 | on the first and second lines of a paragraph is used as the | |
85 | standard indentation for the whole paragraph. | |
86 | ||
87 | If the paragraph has just one line, the indentation is taken from that | |
88 | line, but in that case `adaptive-fill-first-line-regexp' also plays | |
89 | a 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. |
95 | When a paragraph has just one line, then after `adaptive-fill-regexp' | |
96 | finds the prefix at the beginning of the line, if it doesn't | |
97 | match this regexp, it is replaced with whitespace. | |
98 | ||
99 | By default, this regexp matches sequences of just spaces and tabs. | |
100 | ||
101 | However, we never use a prefix from a one-line paragraph | |
102 | if 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 | 108 | This 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. | |
117 | The fill-column to use for a buffer is stored in the variable `fill-column', | |
118 | but can be locally modified by the `right-margin' text property, which is | |
119 | subtracted from `fill-column'. | |
120 | ||
121 | The fill column to use for a line is the first column at which the column | |
122 | number 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 | 144 | Leave 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', |
146 | and `sentence-end-without-period'). | |
34a5f45f | 147 | Remove 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 | 200 | This uses the variables `adaptive-fill-regexp' and `adaptive-fill-function' |
849f04e1 RS |
201 | and `adaptive-fill-first-line-regexp'. `paragraph-start' also plays a role; |
202 | we reject a prefix based on a one-line paragraph if that prefix would | |
203 | act 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. | |
293 | This is used in `fill-nobreak-predicate' to prevent breaking lines just | |
294 | after an opening paren or just before a closing paren or a punctuation | |
295 | mark such as `?' or `:'. It is common in French writing to put a space | |
296 | at such places, which would normally allow breaking the line at those | |
297 | places." | |
298 |