comparison lisp/textmodes/fill.el @ 44491:d85112eaf2d2

(adaptive-fill-regexp): Add ! and %. (fill-delete-prefix): Remove indentation while removing prefix. (fill-delete-newlines): Obey sentence-end. (fill-move-to-break-point, fill-newline): New functions extracted from fill-region-as-paragraph. (fill-region-as-paragraph): Use them. Don't fiddle with fill-indent-according-to-mode.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Wed, 10 Apr 2002 21:21:12 +0000
parents 2539a7fea37f
children 483f757c5f72
comparison
equal deleted inserted replaced
44490:8bb51715e977 44491:d85112eaf2d2
1 ;;; fill.el --- fill commands for Emacs 1 ;;; fill.el --- fill commands for Emacs
2 2
3 ;; Copyright (C) 1985, 86, 92, 94, 95, 96, 97, 1999 Free Software Foundation, Inc. 3 ;; Copyright (C) 1985,86,92,94,95,96,97,1999,2001,2002
4 ;; Free Software Foundation, Inc.
4 5
5 ;; Maintainer: FSF 6 ;; Maintainer: FSF
6 ;; Keywords: wp 7 ;; Keywords: wp
7 8
8 ;; This file is part of GNU Emacs. 9 ;; This file is part of GNU Emacs.
73 "*Non-nil means determine a paragraph's fill prefix from its text." 74 "*Non-nil means determine a paragraph's fill prefix from its text."
74 :type 'boolean 75 :type 'boolean
75 :group 'fill) 76 :group 'fill)
76 77
77 (defcustom adaptive-fill-regexp 78 (defcustom adaptive-fill-regexp
78 (purecopy "[ \t]*\\([-|#;>*]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*") 79 ;; Added `!' for doxygen comments starting with `//!' or `/*!'.
80 ;; Added `%' for TeX comments.
81 (purecopy "[ \t]*\\([-!|#%;>*]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*")
79 "*Regexp to match text at start of line that constitutes indentation. 82 "*Regexp to match text at start of line that constitutes indentation.
80 If Adaptive Fill mode is enabled, a prefix matching this pattern 83 If Adaptive Fill mode is enabled, a prefix matching this pattern
81 on the first and second lines of a paragraph is used as the 84 on the first and second lines of a paragraph is used as the
82 standard indentation for the whole paragraph. 85 standard indentation for the whole paragraph.
83 86
232 ;; make sure it or something compatible is on the first line too. 235 ;; make sure it or something compatible is on the first line too.
233 (when second-line-prefix 236 (when second-line-prefix
234 (unless first-line-prefix (setq first-line-prefix "")) 237 (unless first-line-prefix (setq first-line-prefix ""))
235 238
236 (if ;; If the non-whitespace chars match the first line, 239 (if ;; If the non-whitespace chars match the first line,
237 ;; just use it (this subsumes the 2 previous checks). 240 ;; just use it (this subsumes the 2 checks used previously).
238 ;; Used when first line is `/* ...' and second-line is 241 ;; Used when first line is `/* ...' and second-line is
239 ;; ` * ...'. 242 ;; ` * ...'.
240 (string-match 243 (string-match
241 (concat "\\`" 244 (concat "\\`"
242 (mapconcat 245 (mapconcat
315 ;; Don't break after a period followed by just one space. 318 ;; Don't break after a period followed by just one space.
316 ;; Move back to the previous place to break. 319 ;; Move back to the previous place to break.
317 ;; The reason is that if a period ends up at the end of a 320 ;; The reason is that if a period ends up at the end of a
318 ;; line, further fills will assume it ends a sentence. 321 ;; line, further fills will assume it ends a sentence.
319 ;; If we now know it does not end a sentence, avoid putting 322 ;; If we now know it does not end a sentence, avoid putting
320 ;; it at the end of the line. 323 ;; it at the end of the line.
321 (and sentence-end-double-space 324 (and sentence-end-double-space
322 (save-excursion 325 (save-excursion
323 (skip-chars-backward ". ") 326 (skip-chars-backward ". ")
324 (looking-at "\\. \\([^ ]\\|$\\)"))) 327 (looking-at "\\. \\([^ ]\\|$\\)")))
325 ;; Another approach to the same problem. 328 ;; Another approach to the same problem.
366 369
367 (defun fill-delete-prefix (from to prefix) 370 (defun fill-delete-prefix (from to prefix)
368 "Delete the fill prefix from every line except the first. 371 "Delete the fill prefix from every line except the first.
369 The first line may not even have a fill prefix. 372 The first line may not even have a fill prefix.
370 Point is moved to just past the fill prefix on the first line." 373 Point is moved to just past the fill prefix on the first line."
371 (goto-char from) 374 (let ((fpre (if (and prefix (not (string-match "\\`[ \t]*\\'" prefix)))
372 (let ((fpre (and prefix (not (equal prefix "")) 375 (concat "[ \t]*\\("
373 (concat "[ \t]*" 376 (replace-regexp-in-string
374 (replace-regexp-in-string 377 "[ \t]+" "[ \t]*"
375 "[ \t]+" "[ \t]*" 378 (regexp-quote prefix))
376 (regexp-quote prefix)) 379 "\\)?[ \t]*")
377 "[ \t]*")))) 380 "[ \t]*")))
378 (when fpre 381 (goto-char from)
379 (if (>= (+ (current-left-margin) (length prefix)) 382 (if (>= (+ (current-left-margin) (length prefix))
380 (current-fill-column)) 383 (current-fill-column))
381 (error "fill-prefix too long for specified width")) 384 (error "fill-prefix too long for specified width"))
382 (forward-line 1) 385 (forward-line 1)
383 (while (< (point) to) 386 (while (< (point) to)
384 (if (looking-at fpre)
385 (delete-region (point) (match-end 0)))
386 (forward-line 1))
387 (goto-char from)
388 (if (looking-at fpre) 387 (if (looking-at fpre)
389 (goto-char (match-end 0))) 388 (delete-region (point) (match-end 0)))
390 (setq from (point)))) 389 (forward-line 1))
391 ;; Remove indentation from lines other than the first. 390 (goto-char from)
392 (beginning-of-line 2) 391 (if (looking-at fpre)
393 (indent-region (point) to 0) 392 (goto-char (match-end 0)))
394 (goto-char from)) 393 (setq from (point))))
395 394
396 (defun fill-delete-newlines (from to justify nosqueeze squeeze-after) 395 (defun fill-delete-newlines (from to justify nosqueeze squeeze-after)
397 (goto-char from) 396 (goto-char from)
398 ;; Make sure sentences ending at end of line get an extra space. 397 ;; Make sure sentences ending at end of line get an extra space.
399 ;; loses on split abbrevs ("Mr.\nSmith") 398 ;; loses on split abbrevs ("Mr.\nSmith")
400 (let ((eol-double-space-re (if colon-double-space 399 (let ((eol-double-space-re
401 "[.?!:][])}\"']*$" 400 (cond
402 "[.?!][])}\"']*$"))) 401 ((not colon-double-space) (concat sentence-end "$"))
402 ;; Try to add the : inside the `sentence-end' regexp.
403 ((string-match "\\[[^][]*\\(\\.\\)[^][]*\\]" sentence-end)
404 (concat (replace-match ".:" nil nil sentence-end 1) "$"))
405 ;; Can't find the right spot to insert the colon.
406 (t "[.?!:][])}\"']*$"))))
403 (while (re-search-forward eol-double-space-re to t) 407 (while (re-search-forward eol-double-space-re to t)
404 (or (>= (point) to) (insert-and-inherit ?\ )))) 408 (or (>= (point) to) (memq (char-before) '(?\t ?\ ))
409 (insert-and-inherit ?\ ))))
405 410
406 (goto-char from) 411 (goto-char from)
407 (if enable-multibyte-characters 412 (if enable-multibyte-characters
408 ;; Delete unnecessay newlines surrounded by words. The 413 ;; Delete unnecessay newlines surrounded by words. The
409 ;; character category `|' means that we can break a line 414 ;; character category `|' means that we can break a line
435 (goto-char to) 440 (goto-char to)
436 (delete-horizontal-space) 441 (delete-horizontal-space)
437 (insert-and-inherit " ")) 442 (insert-and-inherit " "))
438 (goto-char from)) 443 (goto-char from))
439 444
445 (defun fill-move-to-break-point (linebeg)
446 "Move to the position where the line should be broken.
447 The break position will normally be after LINEBEG and before point."
448 ;; If the fill column is before linebeg, we have an insanely
449 ;; wide prefix and might as well ignore it.
450 (if (> linebeg (point)) (setq linebeg (line-beginning-position)))
451 ;; Move back to the point where we can break the line
452 ;; at. We break the line between word or after/before
453 ;; the character which has character category `|'. We
454 ;; search space, \c| followed by a character, or \c|
455 ;; following a character. If not found, place
456 ;; the point at linebeg.
457 (while
458 (when (re-search-backward "[ \t]\\|\\c|.\\|.\\c|" linebeg 0)
459 ;; In case of space, we place the point at next to
460 ;; the point where the break occurs actually,
461 ;; because we don't want to change the following
462 ;; logic of original Emacs. In case of \c|, the
463 ;; point is at the place where the break occurs.
464 (forward-char 1)
465 (when (fill-nobreak-p) (skip-chars-backward " \t" linebeg))))
466 ;; If the left margin and fill prefix by themselves
467 ;; pass the fill-column. or if they are zero
468 ;; but we have no room for even one word,
469 ;; keep at least one word or a character which has
470 ;; category `|' anyway.
471 (if (>= linebeg (point))
472 ;; Ok, skip at least one word or one \c| character.
473 ;; Meanwhile, don't stop at a period followed by one space.
474 (let ((to (line-end-position))
475 (fill-nobreak-predicate nil) ;to break sooner.
476 (first t))
477 (goto-char linebeg)
478 (while (and (< (point) to) (or first (fill-nobreak-p)))
479 ;; Find a breakable point while ignoring the
480 ;; following spaces.
481 (skip-chars-forward " \t")
482 (if (looking-at "\\c|")
483 (forward-char 1)
484 (let ((pos (save-excursion
485 (skip-chars-forward "^ \n\t")
486 (point))))
487 (if (re-search-forward "\\c|" pos t)
488 (forward-char -1)
489 (goto-char pos))))
490 (setq first nil)))
491 ;; Normally, move back over the single space between
492 ;; the words.
493 (skip-chars-backward " \t")
494
495 (if enable-multibyte-characters
496 ;; If we are going to break the line after or
497 ;; before a non-ascii character, we may have to
498 ;; run a special function for the charset of the
499 ;; character to find the correct break point.
500 (if (not (and (eq (charset-after (1- (point))) 'ascii)
501 (eq (charset-after (point)) 'ascii)))
502 ;; Make sure we take SOMETHING after the fill prefix if any.
503 (fill-find-break-point linebeg)))))
504
505 (defun fill-newline ()
506 ;; Replace whitespace here with one newline, then
507 ;; indent to left margin.
508 (skip-chars-backward " \t")
509 (if (and (= (following-char) ?\ )
510 (or (aref (char-category-set (preceding-char)) ?|)
511 (looking-at "[ \t]+\\c|")))
512 ;; We need one space at end of line so that
513 ;; further filling won't delete it. NOTE: We
514 ;; intentionally leave this one space to
515 ;; distingush the case that user wants to put
516 ;; space between \c| characters.
517 (forward-char 1))
518 (insert ?\n)
519 ;; Give newline the properties of the space(s) it replaces
520 (set-text-properties (1- (point)) (point)
521 (text-properties-at (point)))
522 (if (or fill-prefix
523 (not fill-indent-according-to-mode))
524 (indent-to-left-margin)
525 (indent-according-to-mode))
526 ;; Insert the fill prefix after indentation.
527 ;; Set prefixcol so whitespace in the prefix won't get lost.
528 (and fill-prefix (not (equal fill-prefix ""))
529 (insert-and-inherit fill-prefix)))
530
440 (defun fill-region-as-paragraph (from to &optional justify 531 (defun fill-region-as-paragraph (from to &optional justify
441 nosqueeze squeeze-after) 532 nosqueeze squeeze-after)
442 "Fill the region as one paragraph. 533 "Fill the region as one paragraph.
443 It removes any paragraph breaks in the region and extra newlines at the end, 534 It removes any paragraph breaks in the region and extra newlines at the end,
444 indents and fills lines between the margins given by the 535 indents and fills lines between the margins given by the
496 ;; (if (and (not oneleft) (> to from-plus-indent)) 587 ;; (if (and (not oneleft) (> to from-plus-indent))
497 ;; (newline)) 588 ;; (newline))
498 (goto-char from-plus-indent)) 589 (goto-char from-plus-indent))
499 590
500 (if (not (> to (point))) 591 (if (not (> to (point)))
501 nil ; There is no paragraph, only whitespace: exit now. 592 nil ;; There is no paragraph, only whitespace: exit now.
502 593
503 (or justify (setq justify (current-justification))) 594 (or justify (setq justify (current-justification)))
504
505 ;; Never indent-according-to-mode with brain dead "indenting" functions.
506 (when (and fill-indent-according-to-mode
507 (memq indent-line-function
508 '(indent-relative-maybe indent-relative
509 indent-to-left-margin)))
510 (set (make-local-variable 'fill-indent-according-to-mode) nil))
511 595
512 ;; Don't let Adaptive Fill mode alter the fill prefix permanently. 596 ;; Don't let Adaptive Fill mode alter the fill prefix permanently.
513 (let ((fill-prefix fill-prefix)) 597 (let ((fill-prefix fill-prefix))
514 ;; Figure out how this paragraph is indented, if desired. 598 ;; Figure out how this paragraph is indented, if desired.
515 (when (and adaptive-fill-mode 599 (when (and adaptive-fill-mode
524 (save-restriction 608 (save-restriction
525 (goto-char from) 609 (goto-char from)
526 (beginning-of-line) 610 (beginning-of-line)
527 (narrow-to-region (point) to) 611 (narrow-to-region (point) to)
528 612
529 (if (not justify) ; filling disabled: just check indentation 613 (if (not justify) ; filling disabled: just check indentation
530 (progn 614 (progn
531 (goto-char from) 615 (goto-char from)
532 (while (< (point) to) 616 (while (< (point) to)
533 (if (and (not (eolp)) 617 (if (and (not (eolp))
534 (< (current-indentation) (current-left-margin))) 618 (< (current-indentation) (current-left-margin)))
549 ;; but after any fill prefix on the first line. 633 ;; but after any fill prefix on the first line.
550 634
551 (fill-delete-newlines from to justify nosqueeze squeeze-after) 635 (fill-delete-newlines from to justify nosqueeze squeeze-after)
552 636
553 ;; This is the actual filling loop. 637 ;; This is the actual filling loop.
554 (let ((prefixcol 0) linebeg) 638 (goto-char from)
555 (while (not (eobp)) 639 (let (linebeg)
640 (while (< (point) to)
556 (setq linebeg (point)) 641 (setq linebeg (point))
557 (move-to-column (1+ (current-fill-column))) 642 (move-to-column (1+ (current-fill-column)))
558 (if (eobp) 643 (if (>= (point) to)
559 (or nosqueeze (delete-horizontal-space)) 644 (or nosqueeze (delete-horizontal-space))
560 ;; Move back to the point where we can break the line 645 ;; Find the position where we'll break the line.
561 ;; at. We break the line between word or after/before 646 (fill-move-to-break-point linebeg)
562 ;; the character which has character category `|'. We 647
563 ;; search space, \c| followed by a character, or \c|
564 ;; following a character. If not found, place
565 ;; the point at linebeg.
566 (while
567 (when (re-search-backward "[ \t]\\|\\c|.\\|.\\c|" linebeg 0)
568 ;; In case of space, we place the point at next to
569 ;; the point where the break occurs actually,
570 ;; because we don't want to change the following
571 ;; logic of original Emacs. In case of \c|, the
572 ;; point is at the place where the break occurs.
573 (forward-char 1)
574 (when (fill-nobreak-p) (skip-chars-backward " \t"))))
575 ;; If the left margin and fill prefix by themselves
576 ;; pass the fill-column. or if they are zero
577 ;; but we have no room for even one word,
578 ;; keep at least one word or a character which has
579 ;; category `|'anyway .
580 ;; This handles ALL BUT the first line of the paragraph.
581 (if (if (zerop prefixcol)
582 (save-excursion
583 (skip-chars-backward " \t" linebeg)
584 (bolp))
585 (>= prefixcol (current-column)))
586 ;; Ok, skip at least one word or one \c| character.
587 ;; Meanwhile, don't stop at a period followed by one space.
588 (let ((fill-nobreak-predicate nil) ;to break sooner.
589 (first t))
590 (move-to-column prefixcol)
591 (while (and (not (eobp)) (or first (fill-nobreak-p)))
592 ;; Find a breakable point while ignoring the
593 ;; following spaces.
594 (skip-chars-forward " \t")
595 (if (looking-at "\\c|")
596 (forward-char 1)
597 (let ((pos (save-excursion
598 (skip-chars-forward "^ \n\t")
599 (point))))
600 (if (re-search-forward "\\c|" pos t)
601 (forward-char -1)
602 (goto-char pos))))
603 (setq first nil)))
604 ;; Normally, move back over the single space between
605 ;; the words.
606 (skip-chars-backward " \t")
607
608 (if enable-multibyte-characters
609 ;; If we are going to break the line after or
610 ;; before a non-ascii character, we may have to
611 ;; run a special function for the charset of the
612 ;; character to find the correct break point.
613 (if (not (and (eq (charset-after (1- (point))) 'ascii)
614 (eq (charset-after (point)) 'ascii)))
615 ;; Make sure we take SOMETHING after the
616 ;; fill prefix if any.
617 (fill-find-break-point
618 (save-excursion
619 (goto-char linebeg)
620 (move-to-column prefixcol)
621 (point))))))
622
623 ;; If the left margin and fill prefix by themselves
624 ;; pass the fill-column, keep at least one word.
625 ;; This handles the first line of the paragraph.
626 (if (and (zerop prefixcol)
627 (let ((fill-point (point)) nchars)
628 (save-excursion
629 (move-to-left-margin)
630 (setq nchars (- fill-point (point)))
631 (or (< nchars 0)
632 (and fill-prefix
633 (< nchars (length fill-prefix))
634 (string= (buffer-substring (point)
635 fill-point)
636 (substring fill-prefix
637 0 nchars)))))))
638 ;; Ok, skip at least one word. But
639 ;; don't stop at a period followed by just one space.
640 (let ((fill-nobreak-predicate nil) ;to break sooner.
641 (first t))
642 (while (and (not (eobp)) (or first (fill-nobreak-p)))
643 ;; Find a breakable point while ignoring the
644 ;; following spaces.
645 (skip-chars-forward " \t")
646 (if (looking-at "\\c|")
647 (forward-char 1)
648 (let ((pos (save-excursion
649 (skip-chars-forward "^ \n\t")
650 (point))))
651 (if (re-search-forward "\\c|" pos t)
652 (forward-char -1)
653 (goto-char pos))))
654 (setq first nil))))
655 ;; Check again to see if we got to the end of the paragraph. 648 ;; Check again to see if we got to the end of the paragraph.
656 (if (save-excursion (skip-chars-forward " \t") (eobp)) 649 (if (save-excursion (skip-chars-forward " \t") (>= (point) to))
657 (or nosqueeze (delete-horizontal-space)) 650 (or nosqueeze (delete-horizontal-space))
658 ;; Replace whitespace here with one newline, then 651 (fill-newline)))
659 ;; indent to left margin.
660 (skip-chars-backward " \t")
661 (if (and (= (following-char) ?\ )
662 (or (aref (char-category-set (preceding-char)) ?|)
663 (looking-at "[ \t]+\\c|")))
664 ;; We need one space at end of line so that
665 ;; further filling won't delete it. NOTE: We
666 ;; intentionally leave this one space to
667 ;; distingush the case that user wants to put
668 ;; space between \c| characters.
669 (forward-char 1))
670 (insert ?\n)
671 ;; Give newline the properties of the space(s) it replaces
672 (set-text-properties (1- (point)) (point)
673 (text-properties-at (point)))
674 (if (or fill-prefix
675 (not fill-indent-according-to-mode))
676 (indent-to-left-margin)
677 (indent-according-to-mode))
678 ;; Insert the fill prefix after indentation.
679 ;; Set prefixcol so whitespace in the prefix won't get lost.
680 (and fill-prefix (not (equal fill-prefix ""))
681 (progn
682 (insert-and-inherit fill-prefix)
683 (setq prefixcol (current-column))))))
684 ;; Justify the line just ended, if desired. 652 ;; Justify the line just ended, if desired.
685 (if justify 653 (if justify
686 (if (save-excursion (skip-chars-forward " \t") (eobp)) 654 (if (save-excursion (skip-chars-forward " \t") (eobp))
687 (progn 655 (progn
688 (delete-horizontal-space) 656 (delete-horizontal-space)
689 (justify-current-line justify t t)) 657 (justify-current-line justify t t))
690 (forward-line -1) 658 (forward-line -1)
691 (justify-current-line justify nil t) 659 (justify-current-line justify nil t)
692 (forward-line 1)))))) 660 (forward-line 1))))))
693 ;; Leave point after final newline. 661 ;; Leave point after final newline.
694 (goto-char (point-max))) 662 (goto-char to))
695 (unless (eobp) 663 (unless (eobp)
696 (forward-char 1)) 664 (forward-char 1))
697 ;; Return the fill-prefix we used 665 ;; Return the fill-prefix we used
698 fill-prefix))) 666 fill-prefix)))
699 667