1 |
;;; fill.el --- fill commands for Emacs |
;;; fill.el --- fill commands for Emacs |
2 |
|
|
3 |
;; Copyright (C) 1985, 86, 92, 94, 95, 96, 97, 1999 Free Software Foundation, Inc. |
;; Copyright (C) 1985,86,92,94,95,96,97,1999,2001,2002 |
4 |
|
;; Free Software Foundation, Inc. |
5 |
|
|
6 |
;; Maintainer: FSF |
;; Maintainer: FSF |
7 |
;; Keywords: wp |
;; Keywords: wp |
76 |
:group 'fill) |
:group 'fill) |
77 |
|
|
78 |
(defcustom adaptive-fill-regexp |
(defcustom adaptive-fill-regexp |
79 |
(purecopy "[ \t]*\\([-|#;>*]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*") |
;; Added `!' for doxygen comments starting with `//!' or `/*!'. |
80 |
|
;; Added `%' for TeX comments. |
81 |
|
(purecopy "[ \t]*\\([-!|#%;>*]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*") |
82 |
"*Regexp to match text at start of line that constitutes indentation. |
"*Regexp to match text at start of line that constitutes indentation. |
83 |
If Adaptive Fill mode is enabled, a prefix matching this pattern |
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 |
on the first and second lines of a paragraph is used as the |
237 |
(unless first-line-prefix (setq first-line-prefix "")) |
(unless first-line-prefix (setq first-line-prefix "")) |
238 |
|
|
239 |
(if ;; If the non-whitespace chars match the first line, |
(if ;; If the non-whitespace chars match the first line, |
240 |
;; just use it (this subsumes the 2 previous checks). |
;; just use it (this subsumes the 2 checks used previously). |
241 |
;; Used when first line is `/* ...' and second-line is |
;; Used when first line is `/* ...' and second-line is |
242 |
;; ` * ...'. |
;; ` * ...'. |
243 |
(string-match |
(string-match |
320 |
;; The reason is that if a period ends up at the end of a |
;; The reason is that if a period ends up at the end of a |
321 |
;; line, further fills will assume it ends a sentence. |
;; line, further fills will assume it ends a sentence. |
322 |
;; If we now know it does not end a sentence, avoid putting |
;; If we now know it does not end a sentence, avoid putting |
323 |
;; it at the end of the line. |
;; it at the end of the line. |
324 |
(and sentence-end-double-space |
(and sentence-end-double-space |
325 |
(save-excursion |
(save-excursion |
326 |
(skip-chars-backward ". ") |
(skip-chars-backward ". ") |
371 |
"Delete the fill prefix from every line except the first. |
"Delete the fill prefix from every line except the first. |
372 |
The first line may not even have a fill prefix. |
The first line may not even have a fill prefix. |
373 |
Point is moved to just past the fill prefix on the first line." |
Point is moved to just past the fill prefix on the first line." |
374 |
(goto-char from) |
(let ((fpre (if (and prefix (not (string-match "\\`[ \t]*\\'" prefix))) |
375 |
(let ((fpre (and prefix (not (equal prefix "")) |
(concat "[ \t]*\\(" |
376 |
(concat "[ \t]*" |
(replace-regexp-in-string |
377 |
(replace-regexp-in-string |
"[ \t]+" "[ \t]*" |
378 |
"[ \t]+" "[ \t]*" |
(regexp-quote prefix)) |
379 |
(regexp-quote prefix)) |
"\\)?[ \t]*") |
380 |
"[ \t]*")))) |
"[ \t]*"))) |
381 |
(when fpre |
(goto-char from) |
382 |
(if (>= (+ (current-left-margin) (length prefix)) |
(if (>= (+ (current-left-margin) (length prefix)) |
383 |
(current-fill-column)) |
(current-fill-column)) |
384 |
(error "fill-prefix too long for specified width")) |
(error "fill-prefix too long for specified width")) |
385 |
(forward-line 1) |
(forward-line 1) |
386 |
(while (< (point) to) |
(while (< (point) to) |
|
(if (looking-at fpre) |
|
|
(delete-region (point) (match-end 0))) |
|
|
(forward-line 1)) |
|
|
(goto-char from) |
|
387 |
(if (looking-at fpre) |
(if (looking-at fpre) |
388 |
(goto-char (match-end 0))) |
(delete-region (point) (match-end 0))) |
389 |
(setq from (point)))) |
(forward-line 1)) |
390 |
;; Remove indentation from lines other than the first. |
(goto-char from) |
391 |
(beginning-of-line 2) |
(if (looking-at fpre) |
392 |
(indent-region (point) to 0) |
(goto-char (match-end 0))) |
393 |
(goto-char from)) |
(setq from (point)))) |
394 |
|
|
395 |
(defun fill-delete-newlines (from to justify nosqueeze squeeze-after) |
(defun fill-delete-newlines (from to justify nosqueeze squeeze-after) |
396 |
(goto-char from) |
(goto-char from) |
397 |
;; Make sure sentences ending at end of line get an extra space. |
;; Make sure sentences ending at end of line get an extra space. |
398 |
;; loses on split abbrevs ("Mr.\nSmith") |
;; loses on split abbrevs ("Mr.\nSmith") |
399 |
(let ((eol-double-space-re (if colon-double-space |
(let ((eol-double-space-re |
400 |
"[.?!:][])}\"']*$" |
(cond |
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 "[.?!:][])}\"']*$")))) |
407 |
(while (re-search-forward eol-double-space-re to t) |
(while (re-search-forward eol-double-space-re to t) |
408 |
(or (>= (point) to) (insert-and-inherit ?\ )))) |
(or (>= (point) to) (memq (char-before) '(?\t ?\ )) |
409 |
|
(insert-and-inherit ?\ )))) |
410 |
|
|
411 |
(goto-char from) |
(goto-char from) |
412 |
(if enable-multibyte-characters |
(if enable-multibyte-characters |
442 |
(insert-and-inherit " ")) |
(insert-and-inherit " ")) |
443 |
(goto-char from)) |
(goto-char from)) |
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 |
|
|
531 |
(defun fill-region-as-paragraph (from to &optional justify |
(defun fill-region-as-paragraph (from to &optional justify |
532 |
nosqueeze squeeze-after) |
nosqueeze squeeze-after) |
533 |
"Fill the region as one paragraph. |
"Fill the region as one paragraph. |
589 |
(goto-char from-plus-indent)) |
(goto-char from-plus-indent)) |
590 |
|
|
591 |
(if (not (> to (point))) |
(if (not (> to (point))) |
592 |
nil ; There is no paragraph, only whitespace: exit now. |
nil ;; There is no paragraph, only whitespace: exit now. |
593 |
|
|
594 |
(or justify (setq justify (current-justification))) |
(or justify (setq justify (current-justification))) |
595 |
|
|
|
;; Never indent-according-to-mode with brain dead "indenting" functions. |
|
|
(when (and fill-indent-according-to-mode |
|
|
(memq indent-line-function |
|
|
'(indent-relative-maybe indent-relative |
|
|
indent-to-left-margin))) |
|
|
(set (make-local-variable 'fill-indent-according-to-mode) nil)) |
|
|
|
|
596 |
;; Don't let Adaptive Fill mode alter the fill prefix permanently. |
;; Don't let Adaptive Fill mode alter the fill prefix permanently. |
597 |
(let ((fill-prefix fill-prefix)) |
(let ((fill-prefix fill-prefix)) |
598 |
;; Figure out how this paragraph is indented, if desired. |
;; Figure out how this paragraph is indented, if desired. |
610 |
(beginning-of-line) |
(beginning-of-line) |
611 |
(narrow-to-region (point) to) |
(narrow-to-region (point) to) |
612 |
|
|
613 |
(if (not justify) ; filling disabled: just check indentation |
(if (not justify) ; filling disabled: just check indentation |
614 |
(progn |
(progn |
615 |
(goto-char from) |
(goto-char from) |
616 |
(while (< (point) to) |
(while (< (point) to) |
635 |
(fill-delete-newlines from to justify nosqueeze squeeze-after) |
(fill-delete-newlines from to justify nosqueeze squeeze-after) |
636 |
|
|
637 |
;; This is the actual filling loop. |
;; This is the actual filling loop. |
638 |
(let ((prefixcol 0) linebeg) |
(goto-char from) |
639 |
(while (not (eobp)) |
(let (linebeg) |
640 |
|
(while (< (point) to) |
641 |
(setq linebeg (point)) |
(setq linebeg (point)) |
642 |
(move-to-column (1+ (current-fill-column))) |
(move-to-column (1+ (current-fill-column))) |
643 |
(if (eobp) |
(if (>= (point) to) |
644 |
(or nosqueeze (delete-horizontal-space)) |
(or nosqueeze (delete-horizontal-space)) |
645 |
;; Move back to the point where we can break the line |
;; Find the position where we'll break the line. |
646 |
;; at. We break the line between word or after/before |
(fill-move-to-break-point linebeg) |
647 |
;; the character which has character category `|'. We |
|
|
;; search space, \c| followed by a character, or \c| |
|
|
;; following a character. If not found, place |
|
|
;; the point at linebeg. |
|
|
(while |
|
|
(when (re-search-backward "[ \t]\\|\\c|.\\|.\\c|" linebeg 0) |
|
|
;; In case of space, we place the point at next to |
|
|
;; the point where the break occurs actually, |
|
|
;; because we don't want to change the following |
|
|
;; logic of original Emacs. In case of \c|, the |
|
|
;; point is at the place where the break occurs. |
|
|
(forward-char 1) |
|
|
(when (fill-nobreak-p) (skip-chars-backward " \t")))) |
|
|
;; If the left margin and fill prefix by themselves |
|
|
;; pass the fill-column. or if they are zero |
|
|
;; but we have no room for even one word, |
|
|
;; keep at least one word or a character which has |
|
|
;; category `|'anyway . |
|
|
;; This handles ALL BUT the first line of the paragraph. |
|
|
(if (if (zerop prefixcol) |
|
|
(save-excursion |
|
|
(skip-chars-backward " \t" linebeg) |
|
|
(bolp)) |
|
|
(>= prefixcol (current-column))) |
|
|
;; Ok, skip at least one word or one \c| character. |
|
|
;; Meanwhile, don't stop at a period followed by one space. |
|
|
(let ((fill-nobreak-predicate nil) ;to break sooner. |
|
|
(first t)) |
|
|
(move-to-column prefixcol) |
|
|
(while (and (not (eobp)) (or first (fill-nobreak-p))) |
|
|
;; Find a breakable point while ignoring the |
|
|
;; following spaces. |
|
|
(skip-chars-forward " \t") |
|
|
(if (looking-at "\\c|") |
|
|
(forward-char 1) |
|
|
(let ((pos (save-excursion |
|
|
(skip-chars-forward "^ \n\t") |
|
|
(point)))) |
|
|
(if (re-search-forward "\\c|" pos t) |
|
|
(forward-char -1) |
|
|
(goto-char pos)))) |
|
|
(setq first nil))) |
|
|
;; Normally, move back over the single space between |
|
|
;; the words. |
|
|
(skip-chars-backward " \t") |
|
|
|
|
|
(if enable-multibyte-characters |
|
|
;; If we are going to break the line after or |
|
|
;; before a non-ascii character, we may have to |
|
|
;; run a special function for the charset of the |
|
|
;; character to find the correct break point. |
|
|
(if (not (and (eq (charset-after (1- (point))) 'ascii) |
|
|
(eq (charset-after (point)) 'ascii))) |
|
|
;; Make sure we take SOMETHING after the |
|
|
;; fill prefix if any. |
|
|
(fill-find-break-point |
|
|
(save-excursion |
|
|
(goto-char linebeg) |
|
|
(move-to-column prefixcol) |
|
|
(point)))))) |
|
|
|
|
|
;; If the left margin and fill prefix by themselves |
|
|
;; pass the fill-column, keep at least one word. |
|
|
;; This handles the first line of the paragraph. |
|
|
(if (and (zerop prefixcol) |
|
|
(let ((fill-point (point)) nchars) |
|
|
(save-excursion |
|
|
(move-to-left-margin) |
|
|
(setq nchars (- fill-point (point))) |
|
|
(or (< nchars 0) |
|
|
(and fill-prefix |
|
|
(< nchars (length fill-prefix)) |
|
|
(string= (buffer-substring (point) |
|
|
fill-point) |
|
|
(substring fill-prefix |
|
|
0 nchars))))))) |
|
|
;; Ok, skip at least one word. But |
|
|
;; don't stop at a period followed by just one space. |
|
|
(let ((fill-nobreak-predicate nil) ;to break sooner. |
|
|
(first t)) |
|
|
(while (and (not (eobp)) (or first (fill-nobreak-p))) |
|
|
;; Find a breakable point while ignoring the |
|
|
;; following spaces. |
|
|
(skip-chars-forward " \t") |
|
|
(if (looking-at "\\c|") |
|
|
(forward-char 1) |
|
|
(let ((pos (save-excursion |
|
|
(skip-chars-forward "^ \n\t") |
|
|
(point)))) |
|
|
(if (re-search-forward "\\c|" pos t) |
|
|
(forward-char -1) |
|
|
(goto-char pos)))) |
|
|
(setq first nil)))) |
|
648 |
;; Check again to see if we got to the end of the paragraph. |
;; Check again to see if we got to the end of the paragraph. |
649 |
(if (save-excursion (skip-chars-forward " \t") (eobp)) |
(if (save-excursion (skip-chars-forward " \t") (>= (point) to)) |
650 |
(or nosqueeze (delete-horizontal-space)) |
(or nosqueeze (delete-horizontal-space)) |
651 |
;; Replace whitespace here with one newline, then |
(fill-newline))) |
|
;; indent to left margin. |
|
|
(skip-chars-backward " \t") |
|
|
(if (and (= (following-char) ?\ ) |
|
|
(or (aref (char-category-set (preceding-char)) ?|) |
|
|
(looking-at "[ \t]+\\c|"))) |
|
|
;; We need one space at end of line so that |
|
|
;; further filling won't delete it. NOTE: We |
|
|
;; intentionally leave this one space to |
|
|
;; distingush the case that user wants to put |
|
|
;; space between \c| characters. |
|
|
(forward-char 1)) |
|
|
(insert ?\n) |
|
|
;; Give newline the properties of the space(s) it replaces |
|
|
(set-text-properties (1- (point)) (point) |
|
|
(text-properties-at (point))) |
|
|
(if (or fill-prefix |
|
|
(not fill-indent-according-to-mode)) |
|
|
(indent-to-left-margin) |
|
|
(indent-according-to-mode)) |
|
|
;; Insert the fill prefix after indentation. |
|
|
;; Set prefixcol so whitespace in the prefix won't get lost. |
|
|
(and fill-prefix (not (equal fill-prefix "")) |
|
|
(progn |
|
|
(insert-and-inherit fill-prefix) |
|
|
(setq prefixcol (current-column)))))) |
|
652 |
;; Justify the line just ended, if desired. |
;; Justify the line just ended, if desired. |
653 |
(if justify |
(if justify |
654 |
(if (save-excursion (skip-chars-forward " \t") (eobp)) |
(if (save-excursion (skip-chars-forward " \t") (eobp)) |
659 |
(justify-current-line justify nil t) |
(justify-current-line justify nil t) |
660 |
(forward-line 1)))))) |
(forward-line 1)))))) |
661 |
;; Leave point after final newline. |
;; Leave point after final newline. |
662 |
(goto-char (point-max))) |
(goto-char to)) |
663 |
(unless (eobp) |
(unless (eobp) |
664 |
(forward-char 1)) |
(forward-char 1)) |
665 |
;; Return the fill-prefix we used |
;; Return the fill-prefix we used |