aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2001-10-30 08:08:12 +0000
committerStefan Monnier2001-10-30 08:08:12 +0000
commit03e3e2e91f3ea169ea3c7878ced22a1ca320e54e (patch)
treee8b1dbf12febc74f33aa1e5cbb4b306012fea83b
parent629261c740735801d073f4251f76f4ddae612771 (diff)
downloademacs-03e3e2e91f3ea169ea3c7878ced22a1ca320e54e.tar.gz
emacs-03e3e2e91f3ea169ea3c7878ced22a1ca320e54e.zip
(sentence-end-double-space, sentence-end-without-period): Move to paragraphs.
(fill-indent-according-to-mode): Change default to t. (fill-context-prefix): Simplify control-flow and use a more sophisticated merge that unifies both previous checks. (fill-single-word-nobreak-p, fill-french-nobreak-p): New funs. (fill-nobreak-predicate): Make it into a defcustom'd hook. (fill-nobreak-p): New fun. (fill-region-as-paragraph): Use it. Handle `fill-indent-according-to-mode' slightly differently. (fill-individual-paragraphs-prefix): Simplify the control-flow. (fill-individual-paragraphs-citation): Fix.
-rw-r--r--lisp/textmodes/fill.el276
1 files changed, 135 insertions, 141 deletions
diff --git a/lisp/textmodes/fill.el b/lisp/textmodes/fill.el
index f894b8d189d..48a4de776cf 100644
--- a/lisp/textmodes/fill.el
+++ b/lisp/textmodes/fill.el
@@ -38,28 +38,11 @@ A value of nil means that any change in indentation starts a new paragraph."
38 :type 'boolean 38 :type 'boolean
39 :group 'fill) 39 :group 'fill)
40 40
41(defcustom sentence-end-double-space t
42 "*Non-nil means a single space does not end a sentence.
43This is relevant for filling. See also `sentence-end-without-period'
44and `colon-double-space'.
45
46If you change this, you should also change `sentence-end'. See Info
47node `Sentences'."
48 :type 'boolean
49 :group 'fill)
50
51(defcustom colon-double-space nil 41(defcustom colon-double-space nil
52 "*Non-nil means put two spaces after a colon when filling." 42 "*Non-nil means put two spaces after a colon when filling."
53 :type 'boolean 43 :type 'boolean
54 :group 'fill) 44 :group 'fill)
55 45
56(defcustom sentence-end-without-period nil
57 "*Non-nil means a sentence will end without a period.
58For example, a sentence in Thai text ends with double space but
59without a period."
60 :type 'boolean
61 :group 'fill)
62
63(defvar fill-paragraph-function nil 46(defvar fill-paragraph-function nil
64 "Mode-specific function to fill a paragraph, or nil if there is none. 47 "Mode-specific function to fill a paragraph, or nil if there is none.
65If the function returns nil, then `fill-paragraph' does its normal work.") 48If the function returns nil, then `fill-paragraph' does its normal work.")
@@ -123,7 +106,7 @@ This function is used when `adaptive-fill-regexp' does not match."
123 :type '(choice (const nil) function) 106 :type '(choice (const nil) function)
124 :group 'fill) 107 :group 'fill)
125 108
126(defvar fill-indent-according-to-mode nil 109(defvar fill-indent-according-to-mode t
127 "Whether or not filling should try to use the major mode's indentation.") 110 "Whether or not filling should try to use the major mode's indentation.")
128 111
129(defun current-fill-column () 112(defun current-fill-column ()
@@ -220,7 +203,6 @@ act as a paragraph-separator."
220 (let ((firstline (point)) 203 (let ((firstline (point))
221 first-line-prefix 204 first-line-prefix
222 ;; Non-nil if we are on the second line. 205 ;; Non-nil if we are on the second line.
223 at-second
224 second-line-prefix 206 second-line-prefix
225 start) 207 start)
226 (move-to-left-margin) 208 (move-to-left-margin)
@@ -232,51 +214,47 @@ act as a paragraph-separator."
232 ;; second-line-prefix from being used. 214 ;; second-line-prefix from being used.
233 (cond ;; ((looking-at paragraph-start) nil) 215 (cond ;; ((looking-at paragraph-start) nil)
234 ((and adaptive-fill-regexp (looking-at adaptive-fill-regexp)) 216 ((and adaptive-fill-regexp (looking-at adaptive-fill-regexp))
235 (buffer-substring-no-properties start (match-end 0))) 217 (match-string-no-properties 0))
236 (adaptive-fill-function (funcall adaptive-fill-function)))) 218 (adaptive-fill-function (funcall adaptive-fill-function))))
237 (forward-line 1) 219 (forward-line 1)
238 (if (>= (point) to) 220 (if (< (point) to)
239 (goto-char firstline) 221 (progn
240 (setq at-second t)
241 (move-to-left-margin) 222 (move-to-left-margin)
242 (setq start (point)) 223 (setq start (point))
243 (setq second-line-prefix 224 (setq second-line-prefix
244 (cond ((looking-at paragraph-start) nil) 225 (cond ((looking-at paragraph-start) nil) ; can it happen ?? -sm
245 ((and adaptive-fill-regexp 226 ((and adaptive-fill-regexp
246 (looking-at adaptive-fill-regexp)) 227 (looking-at adaptive-fill-regexp))
247 (buffer-substring-no-properties start (match-end 0))) 228 (buffer-substring-no-properties start (match-end 0)))
248 (adaptive-fill-function 229 (adaptive-fill-function
249 (funcall adaptive-fill-function))))) 230 (funcall adaptive-fill-function))))
250 (if at-second
251 ;; If we get a fill prefix from the second line, 231 ;; If we get a fill prefix from the second line,
252 ;; make sure it or something compatible is on the first line too. 232 ;; make sure it or something compatible is on the first line too.
253 (and second-line-prefix first-line-prefix 233 (when second-line-prefix
254 ;; If the first line has the second line prefix too, use it. 234 (unless first-line-prefix (setq first-line-prefix ""))
255 (if (or (string-match (concat "\\`" 235
256 (regexp-quote second-line-prefix) 236 (if ;; If the non-whitespace chars match the first line,
257 "\\(\\'\\|[ \t]\\)") 237 ;; just use it (this subsumes the 2 previous checks).
258 first-line-prefix) 238 ;; Used when first line is `/* ...' and second-line is
259 ;; If the second line prefix is whitespace, use it. 239 ;; ` * ...'.
260 (string-match "\\`[ \t]+\\'" second-line-prefix)) 240 (save-excursion
261 second-line-prefix 241 (goto-char start)
262 242 (looking-at
263 ;; If using the common prefix of first-line-prefix 243 (apply 'concat
264 ;; and second-line-prefix leads to problems, consider 244 (mapcar (lambda (c)
265 ;; to restore the code below that's commented out, 245 (if (memq c '(?\t ?\ ))
266 ;; and document why a common prefix cannot be used. 246 ;; The number of chars might not
267 247 ;; match up if there's a mix of
268; ;; If the second line has the first line prefix, 248 ;; tabs and spaces.
269; ;; plus whitespace, use the part that the first line shares. 249 "\\([ \t]*\\|.\\)"
270; (if (string-match (concat "\\`" 250 (regexp-quote (string c))))
271; (regexp-quote first-line-prefix) 251 second-line-prefix))))
272; "[ \t]*\\'") 252 second-line-prefix
273; second-line-prefix)
274; first-line-prefix)))
275 253
276 ;; Use the longest common substring of both prefixes, 254 ;; Use the longest common substring of both prefixes,
277 ;; if there is one. 255 ;; if there is one.
278 (fill-common-string-prefix first-line-prefix 256 (fill-common-string-prefix first-line-prefix
279 second-line-prefix))) 257 second-line-prefix))))
280 ;; If we get a fill prefix from a one-line paragraph, 258 ;; If we get a fill prefix from a one-line paragraph,
281 ;; maybe change it to whitespace, 259 ;; maybe change it to whitespace,
282 ;; and check that it isn't a paragraph starter. 260 ;; and check that it isn't a paragraph starter.
@@ -299,23 +277,75 @@ act as a paragraph-separator."
299 (concat result "a")))) 277 (concat result "a"))))
300 result))))))) 278 result)))))))
301 279
302(defvar fill-nobreak-predicate nil 280(defun fill-single-word-nobreak-p ()
303 "If non-nil, a predicate for recognizing places not to break a line. 281 "Don't break a line after the first or before the last word of a sentence."
304The predicate is called with no arguments, with point at the place 282 (or (looking-at "[ \t]*\\sw+[ \t]*[.?!:][ \t]*$")
305to be tested. If it returns t, fill commands do not break the line there.") 283 (save-excursion
284 (skip-chars-backward " \t")
285 (and (/= (skip-syntax-backward "w") 0)
286 (/= (skip-chars-backward " \t") 0)
287 (/= (skip-chars-backward ".?!:") 0)))))
288
289(defun fill-french-nobreak-p ()
290 "Return nil if French style allows breaking the line at point.
291This is used in `fill-nobreak-predicate' to prevent breaking lines just
292after an opening paren or just before a closing paren or a punctuation
293mark such as `?' or `:'. It is common in French writing to put a space
294at such places, which would normally allow breaking the line at those
295places."
296 (or (looking-at "[ \t]*[])}»?!;:-]")
297 (save-excursion
298 (skip-chars-backward " \t")
299 (unless (bolp)
300 (backward-char 1)
301 (or (looking-at "[([{«]")
302 ;; Don't cut right after a single-letter word.
303 (and (memq (preceding-char) '(?\t ?\ ))
304 (eq (char-syntax (following-char)) ?w)))))))
305
306(defcustom fill-nobreak-predicate nil
307 "List of predicates for recognizing places not to break a line.
308The predicates are called with no arguments, with point at the place to
309be tested. If it returns t, fill commands do not break the line there."
310 :group 'fill
311 :type 'hook
312 :options '(fill-french-nobreak-p fill-single-word-nobreak-p))
313
314(defun fill-nobreak-p ()
315 "Return nil if breaking the line at point is allowed.
316Can be customized with the variable `fill-nobreak-predicate'."
317 (unless (bolp)
318 (or
319 ;; Don't break after a period followed by just one space.
320 ;; Move back to the previous place to break.
321 ;; The reason is that if a period ends up at the end of a
322 ;; line, further fills will assume it ends a sentence.
323 ;; If we now know it does not end a sentence, avoid putting
324 ;; it at the end of the line.
325 (and sentence-end-double-space
326 (save-excursion
327 (skip-chars-backward ". ")
328 (looking-at "\\. \\([^ ]\\|$\\)")))
329 ;; Another approach to the same problem.
330 (save-excursion
331 (skip-chars-backward ". ")
332 (and (looking-at "\\.")
333 (not (looking-at sentence-end))))
334 ;; Don't split a line if the rest would look like a new paragraph.
335 (unless use-hard-newlines
336 (save-excursion
337 (skip-chars-forward " \t") (looking-at paragraph-start)))
338 (run-hook-with-args-until-success 'fill-nobreak-predicate))))
306 339
307;; Put `fill-find-break-point-function' property to charsets which 340;; Put `fill-find-break-point-function' property to charsets which
308;; require special functions to find line breaking point. 341;; require special functions to find line breaking point.
309(let ((alist '((katakana-jisx0201 . kinsoku) 342(dolist (pair '((katakana-jisx0201 . kinsoku)
310 (chinese-gb2312 . kinsoku) 343 (chinese-gb2312 . kinsoku)
311 (japanese-jisx0208 . kinsoku) 344 (japanese-jisx0208 . kinsoku)
312 (japanese-jisx0212 . kinsoku) 345 (japanese-jisx0212 . kinsoku)
313 (chinese-big5-1 . kinsoku) 346 (chinese-big5-1 . kinsoku)
314 (chinese-big5-2 . kinsoku)))) 347 (chinese-big5-2 . kinsoku)))
315 (while alist 348 (put-charset-property (car pair) 'fill-find-break-point-function (cdr pair)))
316 (put-charset-property (car (car alist)) 'fill-find-break-point-function
317 (cdr (car alist)))
318 (setq alist (cdr alist))))
319 349
320(defun fill-find-break-point (limit) 350(defun fill-find-break-point (limit)
321 "Move point to a proper line breaking position of the current line. 351 "Move point to a proper line breaking position of the current line.
@@ -403,6 +433,13 @@ space does not end a sentence, so don't break a line there."
403 433
404 (or justify (setq justify (current-justification))) 434 (or justify (setq justify (current-justification)))
405 435
436 ;; Never indent-according-to-mode with brain dead "indenting" functions.
437 (when (and fill-indent-according-to-mode
438 (memq indent-line-function
439 '(indent-relative-maybe indent-relative
440 indent-to-left-margin)))
441 (set (make-local-variable 'fill-indent-according-to-mode) nil))
442
406 ;; Don't let Adaptive Fill mode alter the fill prefix permanently. 443 ;; Don't let Adaptive Fill mode alter the fill prefix permanently.
407 (let ((fill-prefix fill-prefix)) 444 (let ((fill-prefix fill-prefix))
408 ;; Figure out how this paragraph is indented, if desired. 445 ;; Figure out how this paragraph is indented, if desired.
@@ -528,16 +565,7 @@ space does not end a sentence, so don't break a line there."
528 ;; further fills will assume it ends a sentence. 565 ;; further fills will assume it ends a sentence.
529 ;; If we now know it does not end a sentence, 566 ;; If we now know it does not end a sentence,
530 ;; avoid putting it at the end of the line. 567 ;; avoid putting it at the end of the line.
531 (while (and (> (point) linebeg) 568 (while (and (> (point) linebeg) (fill-nobreak-p))
532 (or (and sentence-end-double-space
533 (> (point) (+ linebeg 2))
534 (eq (preceding-char) ?\ )
535 (not (eq (following-char) ?\ ))
536 (eq (char-after (- (point) 2)) ?\.)
537 (progn (forward-char -2) t))
538 (and fill-nobreak-predicate
539 (funcall fill-nobreak-predicate)
540 (skip-chars-backward " \t"))))
541 (if (re-search-backward " \\|\\c|.\\|.\\c|" linebeg 0) 569 (if (re-search-backward " \\|\\c|.\\|.\\c|" linebeg 0)
542 (forward-char 1))) 570 (forward-char 1)))
543 ;; If the left margin and fill prefix by themselves 571 ;; If the left margin and fill prefix by themselves
@@ -553,18 +581,10 @@ space does not end a sentence, so don't break a line there."
553 (>= prefixcol (current-column))) 581 (>= prefixcol (current-column)))
554 ;; Ok, skip at least one word or one \c| character. 582 ;; Ok, skip at least one word or one \c| character.
555 ;; Meanwhile, don't stop at a period followed by one space. 583 ;; Meanwhile, don't stop at a period followed by one space.
556 (let ((first t)) 584 (let ((fill-nobreak-predicate nil) ;to break sooner.
585 (first t))
557 (move-to-column prefixcol) 586 (move-to-column prefixcol)
558 (while (and (not (eobp)) 587 (while (and (not (eobp)) (or first (fill-nobreak-p)))
559 (or first
560 (and (not (bobp))
561 sentence-end-double-space
562 (save-excursion
563 (forward-char -1)
564 (and (looking-at "\\. ")
565 (not (looking-at "\\. ")))))
566 (and fill-nobreak-predicate
567 (funcall fill-nobreak-predicate))))
568 ;; Find a breakable point while ignoring the 588 ;; Find a breakable point while ignoring the
569 ;; following spaces. 589 ;; following spaces.
570 (skip-chars-forward " \t") 590 (skip-chars-forward " \t")
@@ -579,7 +599,7 @@ space does not end a sentence, so don't break a line there."
579 (setq first nil))) 599 (setq first nil)))
580 ;; Normally, move back over the single space between 600 ;; Normally, move back over the single space between
581 ;; the words. 601 ;; the words.
582 (if (= (preceding-char) ?\ ) (forward-char -1)) 602 (skip-chars-backward " \t")
583 603
584 (if enable-multibyte-characters 604 (if enable-multibyte-characters
585 ;; If we are going to break the line after or 605 ;; If we are going to break the line after or
@@ -613,17 +633,9 @@ space does not end a sentence, so don't break a line there."
613 0 nchars))))))) 633 0 nchars)))))))
614 ;; Ok, skip at least one word. But 634 ;; Ok, skip at least one word. But
615 ;; don't stop at a period followed by just one space. 635 ;; don't stop at a period followed by just one space.
616 (let ((first t)) 636 (let ((fill-nobreak-predicate nil) ;to break sooner.
617 (while (and (not (eobp)) 637 (first t))
618 (or first 638 (while (and (not (eobp)) (or first (fill-nobreak-p)))
619 (and (not (bobp))
620 sentence-end-double-space
621 (save-excursion
622 (forward-char -1)
623 (and (looking-at "\\. ")
624 (not (looking-at "\\. ")))))
625 (and fill-nobreak-predicate
626 (funcall fill-nobreak-predicate))))
627 ;; Find a breakable point while ignoring the 639 ;; Find a breakable point while ignoring the
628 ;; following spaces. 640 ;; following spaces.
629 (skip-chars-forward " \t") 641 (skip-chars-forward " \t")
@@ -656,10 +668,7 @@ space does not end a sentence, so don't break a line there."
656 (set-text-properties (1- (point)) (point) 668 (set-text-properties (1- (point)) (point)
657 (text-properties-at (point))) 669 (text-properties-at (point)))
658 (if (or fill-prefix 670 (if (or fill-prefix
659 (not fill-indent-according-to-mode) 671 (not fill-indent-according-to-mode))
660 (memq indent-line-function
661 ;; Brain dead "indenting" functions.
662 '(indent-relative-maybe indent-relative)))
663 (indent-to-left-margin) 672 (indent-to-left-margin)
664 (indent-according-to-mode)) 673 (indent-according-to-mode))
665 ;; Insert the fill prefix after indentation. 674 ;; Insert the fill prefix after indentation.
@@ -799,8 +808,7 @@ space does not end a sentence, so don't break a line there."
799 "*Method of justifying text not otherwise specified. 808 "*Method of justifying text not otherwise specified.
800Possible values are `left', `right', `full', `center', or `none'. 809Possible values are `left', `right', `full', `center', or `none'.
801The requested kind of justification is done whenever lines are filled. 810The requested kind of justification is done whenever lines are filled.
802The `justification' text-property can locally override this variable. 811The `justification' text-property can locally override this variable."
803This variable automatically becomes buffer-local when set in any fashion."
804 :type '(choice (const left) 812 :type '(choice (const left)
805 (const right) 813 (const right)
806 (const full) 814 (const full)
@@ -1226,61 +1234,47 @@ Also, if CITATION-REGEXP is non-nil, don't fill header lines."
1226 (fill-region-as-paragraph start (point) justify) 1234 (fill-region-as-paragraph start (point) justify)
1227 (if (and (bolp) (not had-newline)) 1235 (if (and (bolp) (not had-newline))
1228 (delete-char -1)))))))) 1236 (delete-char -1))))))))
1229
1230(defun fill-individual-paragraphs-prefix (citation-regexp) 1237(defun fill-individual-paragraphs-prefix (citation-regexp)
1231 (or (let ((adaptive-fill-first-line-regexp "") 1238 (let* ((adaptive-fill-first-line-regexp ".*")
1232 just-one-line-prefix 1239 (just-one-line-prefix
1233 two-lines-prefix 1240 ;; Accept any prefix rather than just the ones matched by
1234 one-line-citation-part 1241 ;; adaptive-fill-first-line-regexp.
1235 two-lines-citation-part 1242 (fill-context-prefix (point) (line-beginning-position 2)))
1236 adjusted-two-lines-citation-part) 1243 (two-lines-prefix
1237 (setq just-one-line-prefix 1244 (fill-context-prefix (point) (line-beginning-position 3))))
1238 (fill-context-prefix 1245 (if (not just-one-line-prefix)
1239 (point) 1246 (buffer-substring
1240 (line-beginning-position 2))) 1247 (point) (save-excursion (skip-chars-forward " \t") (point)))
1241 (setq two-lines-prefix
1242 (fill-context-prefix
1243 (point)
1244 (line-beginning-position 3)))
1245 (when just-one-line-prefix
1246 (setq one-line-citation-part
1247 (if citation-regexp
1248 (fill-individual-paragraphs-citation just-one-line-prefix
1249 citation-regexp)
1250 just-one-line-prefix)))
1251 (when two-lines-prefix
1252 (setq two-lines-citation-part
1253 (if citation-regexp
1254 (fill-individual-paragraphs-citation two-lines-prefix
1255 citation-regexp)
1256 just-one-line-prefix))
1257 (or two-lines-citation-part (setq two-lines-citation-part ""))
1258 (setq adjusted-two-lines-citation-part
1259 (substring two-lines-citation-part 0
1260 (string-match "[ \t]*\\'"
1261 two-lines-citation-part))))
1262 ;; See if the citation part of JUST-ONE-LINE-PREFIX 1248 ;; See if the citation part of JUST-ONE-LINE-PREFIX
1263 ;; is the same as that of TWO-LINES-PREFIX, 1249 ;; is the same as that of TWO-LINES-PREFIX,
1264 ;; except perhaps with longer whitespace. 1250 ;; except perhaps with longer whitespace.
1265 (if (and just-one-line-prefix 1251 (if (and just-one-line-prefix two-lines-prefix
1266 two-lines-prefix 1252 (let* ((one-line-citation-part
1253 (fill-individual-paragraphs-citation
1254 just-one-line-prefix citation-regexp))
1255 (two-lines-citation-part
1256 (fill-individual-paragraphs-citation
1257 two-lines-prefix citation-regexp))
1258 (adjusted-two-lines-citation-part
1259 (substring two-lines-citation-part 0
1260 (string-match "[ \t]*\\'"
1261 two-lines-citation-part))))
1262 (and
1267 (string-match (concat "\\`" 1263 (string-match (concat "\\`"
1268 (regexp-quote 1264 (regexp-quote
1269 adjusted-two-lines-citation-part) 1265 adjusted-two-lines-citation-part)
1270 "[ \t]*\\'") 1266 "[ \t]*\\'")
1271 one-line-citation-part) 1267 one-line-citation-part)
1272 (>= (string-width one-line-citation-part) 1268 (>= (string-width one-line-citation-part)
1273 (string-width two-lines-citation-part))) 1269 (string-width two-lines-citation-part)))))
1274 two-lines-prefix 1270 two-lines-prefix
1275 just-one-line-prefix)) 1271 just-one-line-prefix))))
1276 (buffer-substring
1277 (point)
1278 (save-excursion (skip-chars-forward " \t")
1279 (point)))))
1280 1272
1281(defun fill-individual-paragraphs-citation (string citation-regexp) 1273(defun fill-individual-paragraphs-citation (string citation-regexp)
1282 (string-match citation-regexp 1274 (if citation-regexp
1283 string) 1275 (if (string-match citation-regexp string)
1284 (match-string 0 string)) 1276 (match-string 0 string)
1277 "")
1278 string))
1285 1279
1286;;; fill.el ends here 1280;;; fill.el ends here