Mercurial > emacs
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 |