X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/119d72b62ca7a8c7becf59bd1a4f796810537068..8dd59f01de203f3f02c3f898a7015bb522a0e4bc:/lisp/textmodes/fill.el diff --git a/lisp/textmodes/fill.el b/lisp/textmodes/fill.el index 9218c565c9..6184680df3 100644 --- a/lisp/textmodes/fill.el +++ b/lisp/textmodes/fill.el @@ -1,7 +1,7 @@ ;;; fill.el --- fill commands for Emacs -*- coding: iso-2022-7bit -*- ;; Copyright (C) 1985, 1986, 1992, 1994, 1995, 1996, 1997, 1999, 2001, 2002, -;; 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +;; 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. ;; Maintainer: FSF ;; Keywords: wp @@ -10,7 +10,7 @@ ;; GNU Emacs is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) +;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; GNU Emacs is distributed in the hope that it will be useful, @@ -52,7 +52,8 @@ A value of nil means that any change in indentation starts a new paragraph." (defvar fill-paragraph-function nil "Mode-specific function to fill a paragraph, or nil if there is none. -If the function returns nil, then `fill-paragraph' does its normal work.") +If the function returns nil, then `fill-paragraph' does its normal work. +A value of t means explicitly \"do nothing special\".") (defvar fill-paragraph-handle-comment t "Non-nil means paragraph filling will try to pay attention to comments.") @@ -89,7 +90,8 @@ reinserts the fill prefix in each resulting line." (defcustom adaptive-fill-regexp ;; Added `!' for doxygen comments starting with `//!' or `/*!'. ;; Added `%' for TeX comments. - (purecopy "[ \t]*\\([-!|#%;>*,A7$,1s"s#sC$,2"F(B]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*") + ;; RMS: deleted the code to match `1.' and `(1)'. + "[ \t]*\\([-!|#%;>*,A7$,1s"s#sC$,2"F(B]+[ \t]*\\)*" "*Regexp to match text at start of line that constitutes indentation. If Adaptive Fill mode is enabled, a prefix matching this pattern on the first and second lines of a paragraph is used as the @@ -115,8 +117,8 @@ if it would act as a paragraph-starter on the second line." :group 'fill) (defcustom adaptive-fill-function nil - "*Function to call to choose a fill prefix for a paragraph, or nil. -nil means the function has not determined the fill prefix." + "Function to call to choose a fill prefix for a paragraph, or nil. +A nil value means the function has not determined the fill prefix." :type '(choice (const nil) function) :group 'fill) @@ -157,6 +159,11 @@ Leave one space between words, two at end of sentences or after colons and `sentence-end-without-period'). Remove indentation from each line." (interactive "*r") + ;; Ideally, we'd want to scan the text from the end, so that changes to + ;; text don't affect the boundary, but the regexp we match against does + ;; not match as eagerly when matching backward, so we instead use + ;; a marker. + (unless (markerp end) (setq end (copy-marker end t))) (let ((end-spc-re (concat "\\(" (sentence-end) "\\) *\\| +"))) (save-excursion (goto-char beg) @@ -292,7 +299,9 @@ act as a paragraph-separator." (defun fill-single-word-nobreak-p () "Don't break a line after the first or before the last word of a sentence." - (or (looking-at (concat "[ \t]*\\sw+" "\\(?:" (sentence-end) "\\)")) + ;; Actually, allow breaking before the last word of a sentence, so long as + ;; it's not the last word of the paragraph. + (or (looking-at (concat "[ \t]*\\sw+" "\\(?:" (sentence-end) "\\)[ \t]*$")) (save-excursion (skip-chars-backward " \t") (and (/= (skip-syntax-backward "w") 0) @@ -335,7 +344,7 @@ be tested. If it returns t, fill commands do not break the line there." Can be customized with the variables `fill-nobreak-predicate' and `fill-nobreak-invisible'." (or - (and fill-nobreak-invisible (line-move-invisible-p (point))) + (and fill-nobreak-invisible (invisible-p (point))) (unless (bolp) (or ;; Don't break after a period followed by just one space. @@ -382,7 +391,7 @@ Don't move back past the buffer position LIMIT. This function is called when we are going to break the current line after or before a non-ASCII character. If the charset of the character has the property `fill-find-break-point-function', this -function calls the property value as a function with one arg LINEBEG. +function calls the property value as a function with one arg LIMIT. If the charset has no such property, do nothing." (let* ((ch (following-char)) (charset (char-charset ch)) @@ -408,18 +417,19 @@ Point is moved to just past the fill prefix on the first line." "\\)?[ \t]*") "[ \t]*"))) (goto-char from) - (if (>= (+ (current-left-margin) (length prefix)) - (current-fill-column)) - (error "fill-prefix too long for specified width")) + ;; Why signal an error here? The problem needs to be caught elsewhere. + ;; (if (>= (+ (current-left-margin) (length prefix)) + ;; (current-fill-column)) + ;; (error "fill-prefix too long for specified width")) (forward-line 1) (while (< (point) to) (if (looking-at fpre) - (delete-region (point) (match-end 0))) + (delete-region (point) (match-end 0))) (forward-line 1)) (goto-char from) (if (looking-at fpre) (goto-char (match-end 0))) - (setq from (point)))) + (point))) ;; The `fill-space' property carries the string with which a newline ;; should be replaced when unbreaking a line (in fill-delete-newlines). @@ -516,7 +526,6 @@ The break position will be always after LINEBEG and generally before point." ;; Ok, skip at least one word or one \c| character. ;; Meanwhile, don't stop at a period followed by one space. (let ((to (line-end-position)) - (fill-nobreak-predicate nil) ;to break sooner. (first t)) (goto-char linebeg) (while (and (< (point) to) (or first (fill-nobreak-p))) @@ -628,7 +637,12 @@ space does not end a sentence, so don't break a line there." (oneleft nil)) (beginning-of-line) - (setq from (point)) + ;; We used to round up to whole line, but that prevents us from + ;; correctly handling filling of mixed code-and-comment where we do want + ;; to fill the comment but not the code. So only use (point) if it's + ;; further than `from', which means that `from' is followed by some + ;; number of empty lines. + (setq from (max (point) from)) ;; Delete all but one soft newline at end of region. ;; And leave TO before that one. @@ -732,8 +746,16 @@ space does not end a sentence, so don't break a line there." (looking-at (regexp-quote prefix)))) (goto-char (match-end 0)))) -(defun fill-paragraph (arg) - "Fill paragraph at or after point. Prefix ARG means justify as well. +(defun fill-minibuffer-function (arg) + "Fill a paragraph in the minibuffer, ignoring the prompt." + (save-restriction + (narrow-to-region (minibuffer-prompt-end) (point-max)) + (fill-paragraph arg))) + +(defun fill-paragraph (&optional justify region) + "Fill paragraph at or after point. + +If JUSTIFY is non-nil (interactively, with prefix argument), justify as well. If `sentence-end-double-space' is non-nil, then period followed by one space does not end a sentence, so don't break a line there. the variable `fill-column' controls the width for filling. @@ -741,65 +763,84 @@ the variable `fill-column' controls the width for filling. If `fill-paragraph-function' is non-nil, we call it (passing our argument to it), and if it returns non-nil, we simply return its value. -If `fill-paragraph-function' is nil, return the `fill-prefix' used for filling." +If `fill-paragraph-function' is nil, return the `fill-prefix' used for filling. + +Interactively (when `region' is non-nil) in Transient Mark mode when +the mark is active, call `fill-region' to fill each of the paragraphs +in the active region." (interactive (progn (barf-if-buffer-read-only) - (list (if current-prefix-arg 'full)))) - ;; First try fill-paragraph-function. - (or (and fill-paragraph-function - (let ((function fill-paragraph-function) - ;; If fill-paragraph-function is set, it probably takes care - ;; of comments and stuff. If not, it will have to set - ;; fill-paragraph-handle-comment back to t explicitly or - ;; return nil. - (fill-paragraph-handle-comment nil) - fill-paragraph-function) - (funcall function arg))) - ;; Then try our syntax-aware filling code. - (and fill-paragraph-handle-comment - ;; Our code only handles \n-terminated comments right now. - comment-start (equal comment-end "") - (let ((fill-paragraph-handle-comment nil)) - (fill-comment-paragraph arg))) - ;; If it all fails, default to the good ol' text paragraph filling. - (let ((before (point)) - (paragraph-start paragraph-start) - ;; Fill prefix used for filling the paragraph. - fill-pfx) - ;; Try to prevent code sections and comment sections from being - ;; filled together. - (when (and fill-paragraph-handle-comment comment-start-skip) - (setq paragraph-start - (concat paragraph-start "\\|[ \t]*\\(?:" - comment-start-skip "\\)"))) - (save-excursion - ;; To make sure the return value of forward-paragraph is meaningful, - ;; we have to start from the beginning of line, otherwise skipping - ;; past the last few chars of a paragraph-separator would count as - ;; a paragraph (and not skipping any chars at EOB would not count - ;; as a paragraph even if it is). - (move-to-left-margin) - (if (not (zerop (forward-paragraph))) - ;; There's no paragraph at or after point: give up. - (setq fill-pfx "") - (let ((end (point)) - (beg (progn (backward-paragraph) (point)))) - (goto-char before) - (setq fill-pfx - (if use-hard-newlines - ;; Can't use fill-region-as-paragraph, since this - ;; paragraph may still contain hard newlines. See - ;; fill-region. - (fill-region beg end arg) - (fill-region-as-paragraph beg end arg)))))) - fill-pfx))) + (list (if current-prefix-arg 'full) t))) + (or + ;; 1. Fill the region if it is active when called interactively. + (and region transient-mark-mode mark-active + (not (eq (region-beginning) (region-end))) + (or (fill-region (region-beginning) (region-end) justify) t)) + ;; 2. Try fill-paragraph-function. + (and (not (eq fill-paragraph-function t)) + (or fill-paragraph-function + (and (minibufferp (current-buffer)) + (= 1 (point-min)))) + (let ((function (or fill-paragraph-function + ;; In the minibuffer, don't count the width + ;; of the prompt. + 'fill-minibuffer-function)) + ;; If fill-paragraph-function is set, it probably takes care + ;; of comments and stuff. If not, it will have to set + ;; fill-paragraph-handle-comment back to t explicitly or + ;; return nil. + (fill-paragraph-handle-comment nil) + (fill-paragraph-function t)) + (funcall function justify))) + ;; 3. Try our syntax-aware filling code. + (and fill-paragraph-handle-comment + ;; Our code only handles \n-terminated comments right now. + comment-start (equal comment-end "") + (let ((fill-paragraph-handle-comment nil)) + (fill-comment-paragraph justify))) + ;; 4. If it all fails, default to the good ol' text paragraph filling. + (let ((before (point)) + (paragraph-start paragraph-start) + ;; Fill prefix used for filling the paragraph. + fill-pfx) + ;; Try to prevent code sections and comment sections from being + ;; filled together. + (when (and fill-paragraph-handle-comment comment-start-skip) + (setq paragraph-start + (concat paragraph-start "\\|[ \t]*\\(?:" + comment-start-skip "\\)"))) + (save-excursion + ;; To make sure the return value of forward-paragraph is meaningful, + ;; we have to start from the beginning of line, otherwise skipping + ;; past the last few chars of a paragraph-separator would count as + ;; a paragraph (and not skipping any chars at EOB would not count + ;; as a paragraph even if it is). + (move-to-left-margin) + (if (not (zerop (forward-paragraph))) + ;; There's no paragraph at or after point: give up. + (setq fill-pfx "") + (let ((end (point)) + (beg (progn (backward-paragraph) (point)))) + (goto-char before) + (setq fill-pfx + (if use-hard-newlines + ;; Can't use fill-region-as-paragraph, since this + ;; paragraph may still contain hard newlines. See + ;; fill-region. + (fill-region beg end justify) + (fill-region-as-paragraph beg end justify)))))) + fill-pfx))) + +(declare-function comment-search-forward "newcomment" (limit &optional noerror)) +(declare-function comment-string-strip "newcomment" (str beforep afterp)) + (defun fill-comment-paragraph (&optional justify) "Fill current comment. If we're not in a comment, just return nil so that the caller can take care of filling. JUSTIFY is used as in `fill-paragraph'." (comment-normalize-vars) - (let (has-code-and-comment ; Non-nil if it contains code and a comment. + (let (has-code-and-comment ; Non-nil if it contains code and a comment. comin comstart) ;; Figure out what kind of comment we are looking at. (save-excursion @@ -818,16 +859,22 @@ can take care of filling. JUSTIFY is used as in `fill-paragraph'." (commark (comment-string-strip (buffer-substring comstart comin) nil t)) (comment-re - (if (string-match comment-start-skip (concat commark "a")) - (concat "[ \t]*" (regexp-quote commark) - ;; Make sure we only match comments that use - ;; the exact same comment marker. - "[^" (substring commark -1) "]") - ;; If the commark needs to be followed by some special - ;; set of characters (like @c in TeXinfo), we can't - ;; rely just on `commark'. - (concat "[ \t]*\\(?:" comment-start-skip "\\)"))) - (comment-fill-prefix ; Compute a fill prefix. + ;; A regexp more specialized than comment-start-skip, that only + ;; matches the current commark rather than any valid commark. + ;; + ;; The specialized regexp only works for "normal" comment + ;; syntax, not for Texinfo's "@c" (which can't be immediately + ;; followed by word-chars) or Fortran's "C" (which needs to be + ;; at bol), so check that comment-start-skip indeed allows the + ;; commark to appear in the middle of the line and followed by + ;; word chars. The choice of "\0" and "a" is mostly arbitrary. + (if (string-match comment-start-skip (concat "\0" commark "a")) + (concat "[ \t]*" (regexp-quote commark) + ;; Make sure we only match comments that + ;; use the exact same comment marker. + "[^" (substring commark -1) "]") + (concat "[ \t]*\\(?:" comment-start-skip "\\)"))) + (comment-fill-prefix ; Compute a fill prefix. (save-excursion (goto-char comstart) (if has-code-and-comment @@ -857,12 +904,13 @@ can take care of filling. JUSTIFY is used as in `fill-paragraph'." (or (comment-search-forward (line-end-position) t) (point))) (looking-at comment-re)) - 1 2)))) - ;; Find the beginning of the first line past the region to fill. - (save-excursion - (while (progn (forward-line 1) - (looking-at comment-re))) - (point))) + (progn (setq comstart (point)) 1) + (progn (setq comstart (point)) 2))))) + ;; Find the beginning of the first line past the region to fill. + (save-excursion + (while (progn (forward-line 1) + (looking-at comment-re))) + (point))) ;; Obey paragraph starters and boundaries within comments. (let* ((paragraph-separate ;; Use the default values since they correspond to @@ -874,7 +922,7 @@ can take care of filling. JUSTIFY is used as in `fill-paragraph'." (concat paragraph-start "\\|[ \t]*\\(?:" comment-start-skip "\\)\\(?:" (default-value 'paragraph-start) "\\)")) - ;; We used to reply on fill-prefix to break paragraph at + ;; We used to rely on fill-prefix to break paragraph at ;; comment-starter changes, but it did not work for the ;; first line (mixed comment&code). ;; We now use comment-re instead to "manually" make sure @@ -893,7 +941,7 @@ can take care of filling. JUSTIFY is used as in `fill-paragraph'." ;; Find the fill-prefix to use. (cond - (fill-prefix) ; Use the user-provided fill prefix. + (fill-prefix) ; Use the user-provided fill prefix. ((and adaptive-fill-mode ; Try adaptive fill mode. (setq fill-prefix (fill-context-prefix beg end)) (string-match comment-start-skip fill-prefix))) @@ -903,7 +951,7 @@ can take care of filling. JUSTIFY is used as in `fill-paragraph'." ;; Don't fill with narrowing. (or (fill-region-as-paragraph - beg end justify nil + (max comstart beg) end justify nil ;; Don't canonicalize spaces within the code just before ;; the comment. (save-excursion @@ -921,13 +969,13 @@ Ordinarily the variable `fill-column' controls the width. Noninteractively, the third argument JUSTIFY specifies which kind of justification to do: `full', `left', `right', `center', -or `none' (equivalent to nil). t means handle each paragraph -as specified by its text properties. +or `none' (equivalent to nil). A value of t means handle each +paragraph as specified by its text properties. -The fourth arg NOSQUEEZE non-nil means to leave -whitespace other than line breaks untouched, and fifth arg TO-EOP -non-nil means to keep filling to the end of the paragraph (or next -hard newline, if variable `use-hard-newlines' is on). +The fourth arg NOSQUEEZE non-nil means to leave whitespace other +than line breaks untouched, and fifth arg TO-EOP non-nil means +to keep filling to the end of the paragraph (or next hard newline, +if variable `use-hard-newlines' is on). Return the fill-prefix used for filling the last paragraph. @@ -1315,8 +1363,8 @@ These lines are filled together. When calling from a program, pass the range to fill as the first two arguments. -Optional third and fourth arguments JUSTIFY and MAIL-FLAG: -JUSTIFY to justify paragraphs (prefix arg), +Optional third and fourth arguments JUSTIFY and CITATION-REGEXP: +JUSTIFY to justify paragraphs (prefix arg). When filling a mail message, pass a regexp for CITATION-REGEXP which will match the prefix of a line which is a citation marker plus whitespace, but no other kind of prefix. @@ -1404,6 +1452,7 @@ Also, if CITATION-REGEXP is non-nil, don't fill header lines." (fill-region-as-paragraph start (point) justify) (if (and (bolp) (not had-newline)) (delete-char -1)))))))) + (defun fill-individual-paragraphs-prefix (citation-regexp) (let* ((adaptive-fill-first-line-regexp ".*") (just-one-line-prefix