;;; 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 Free Software Foundation, Inc.
;; Maintainer: FSF
;; Keywords: wp
;; 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,
"*Non-nil means put two spaces after a colon when filling."
:type 'boolean
:group 'fill)
-;;;###autoload(put 'colon-double-space 'safe-local-variable t)
+;;;###autoload(put 'colon-double-space 'safe-local-variable 'booleanp)
(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.")
(defcustom adaptive-fill-regexp
;; Added `!' for doxygen comments starting with `//!' or `/*!'.
;; Added `%' for TeX comments.
- (purecopy "[ \t]*\\([-!|#%;>*\e,A7\e$,1s"s#sC\e$,2"F\e(B]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*")
+ ;; RMS: deleted the code to match `1.' and `(1)'.
+ "[ \t]*\\([-!|#%;>*\e,A7\e$,1s"s#sC\e$,2"F\e(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
: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)
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)
(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)
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.
"\\)?[ \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).
;; 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)))
(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.
(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.
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)))
(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
(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
(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
(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
;; 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)))
;; 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
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.
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.
(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