]> code.delx.au - gnu-emacs/blobdiff - lisp/textmodes/fill.el
(reporter-dont-compact-list): Doc fix.
[gnu-emacs] / lisp / textmodes / fill.el
index 6b80922c8475e11a96275715884d6b8430daf032..98248bbf88643c32fb3478bb46f04bb9c77b0099 100644 (file)
@@ -41,7 +41,8 @@ A value of nil means that any change in indentation starts a new paragraph.")
   "*Non-nil means put two spaces after a colon when filling.")
 
 (defvar fill-paragraph-function nil
-  "Mode-specific function to fill a paragraph.")
+  "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.")
 
 (defun set-fill-prefix ()
   "Set the fill prefix to the current line up to point.
@@ -130,30 +131,43 @@ Remove indentation from each line."
                (re-search-forward "[.?!][])}\"']*$" end t))
       (insert-and-inherit ? ))))
 
-(defun fill-context-prefix (from to)
+(defun fill-context-prefix (from to &optional first-line-regexp)
   "Compute a fill prefix from the text between FROM and TO.
-This uses the variables `adapive-fill-prefix' and `adaptive-fill-function'."
+This uses the variables `adaptive-fill-prefix' and `adaptive-fill-function'.
+If FIRST-LINE-REGEXP is non-nil, then when taking a prefix from the
+first line, insist it must match FIRST-LINE-REGEXP."
   (save-excursion
     (goto-char from)
     (if (eolp) (forward-line 1))
     ;; Move to the second line unless there is just one.
-    (let ((firstline (point)))
+    (let ((firstline (point))
+         ;; Non-nil if we are on the second line.
+         at-second
+         result)
       (forward-line 1)
       (if (>= (point) to)
-         (goto-char firstline)))
-    (move-to-left-margin)
-    (let ((start (point))
-         (eol (save-excursion (end-of-line) (point))))
-      (if (not (looking-at paragraph-start))
-         (cond ((looking-at adaptive-fill-regexp)
-                (buffer-substring-no-properties start (match-end 0)))
-               (t (funcall adaptive-fill-function)))))))
+         (goto-char firstline)
+       (setq at-second t))
+      (move-to-left-margin)
+      (let ((start (point))
+           (eol (save-excursion (end-of-line) (point))))
+       (setq result
+             (if (not (looking-at paragraph-start))
+                 (cond ((and adaptive-fill-regexp (looking-at adaptive-fill-regexp))
+                        (buffer-substring-no-properties start (match-end 0)))
+                       (adaptive-fill-function (funcall adaptive-fill-function)))))
+       (and result
+            (or at-second
+                (null first-line-regexp)
+                (string-match first-line-regexp result))
+            result)))))
 
 (defun fill-region-as-paragraph (from to &optional justify nosqueeze)
   "Fill the region as one paragraph.
-Removes any paragraph breaks in the region and extra newlines at the end,
+It removes any paragraph breaks in the region and extra newlines at the end,
 indents and fills lines between the margins given by the
 `current-left-margin' and `current-fill-column' functions.
+It leaves point at the beginning of the line following the paragraph.
 
 Normally performs justification according to the `current-justification'
 function, but with a prefix arg, does full justification instead.
@@ -170,14 +184,20 @@ space does not end a sentence, so don't break a line there."
   (if (and buffer-undo-list (not (eq buffer-undo-list t)))
       (setq buffer-undo-list (cons (point) buffer-undo-list)))
 
-  ;; Make sure "to" is the endpoint.  Make sure that we end up there.
+  ;; Make sure "to" is the endpoint.
   (goto-char (min from to))
   (setq to   (max from to))
-  (setq from (point))
+  ;; Ignore blank lines at beginning of region.
+  (skip-chars-forward " \t\n")
 
-  ;; Delete all but one soft newline at end of region.
-  (goto-char to)
-  (let ((oneleft nil))
+  (let ((from-plus-indent (point))
+       (oneleft nil))
+
+    (beginning-of-line)
+    (setq from (point))
+  
+    ;; Delete all but one soft newline at end of region.
+    (goto-char to)
     (while (and (> (point) from) (eq ?\n (char-after (1- (point)))))
       (if (and oneleft
               (not (and use-hard-newlines
@@ -185,19 +205,16 @@ space does not end a sentence, so don't break a line there."
          (delete-backward-char 1)
        (backward-char 1)
        (setq oneleft t)))
-    ;; If there was no newline, create one.
-    (if (and (not oneleft) (> (point) from))
-       (save-excursion (newline))))
-  (setq to (point))
+    (setq to (point))
 
-  ;; Ignore blank lines at beginning of region.
-  (goto-char from)
-  (skip-chars-forward " \t\n")
-  (beginning-of-line)
-  (setq from (point))
-  
-  (if (>= from to)
-      nil ; There is no paragraph at all.
+    ;; If there was no newline, and there is text in the paragraph, then
+    ;; create a newline.
+    (if (and (not oneleft) (> to from-plus-indent))
+       (newline))
+    (goto-char from-plus-indent))
+
+  (if (not (> to (point)))
+      nil ; There is no paragraph, only whitespace: exit now.
 
     (or justify (setq justify (current-justification)))
 
@@ -295,13 +312,15 @@ space does not end a sentence, so don't break a line there."
                                (eq (char-after (- (point) 2)) ?\.))
                      (forward-char -2)
                      (skip-chars-backward "^ \n" linebeg)))
+               ;; If the left margin and fill prefix by themselves
+               ;; pass the fill-column, keep at least one word.
+               ;; This handles ALL BUT the first line of the paragraph.
                (if (if (zerop prefixcol)
                        (save-excursion
-                         (skip-chars-backward " " linebeg)
+                         (skip-chars-backward " \t" linebeg)
                          (bolp))
                      (>= prefixcol (current-column)))
-                   ;; Keep at least one word even if fill prefix exceeds margin.
-                   ;; This handles all but the first line of the paragraph.
+                   ;; Ok, skip at least one word.
                    ;; Meanwhile, don't stop at a period followed by one space.
                    (let ((first t))
                      (move-to-column prefixcol)
@@ -312,18 +331,26 @@ space does not end a sentence, so don't break a line there."
                                           (save-excursion (forward-char -1)
                                                           (and (looking-at "\\. ")
                                                                (not (looking-at "\\.  ")))))))
-                       (skip-chars-forward " ")
-                       (skip-chars-forward "^ \n")
+                       (skip-chars-forward " \t")
+                       (skip-chars-forward "^ \n\t")
                        (setq first nil)))
                  ;; Normally, move back over the single space between the words.
                  (forward-char -1))
-               (if (and fill-prefix (zerop prefixcol)
-                        (< (- (point) (point-min)) (length fill-prefix))
-                        (string= (buffer-substring (point-min) (point))
-                                 (substring fill-prefix 0 (- (point) (point-min)))))
-                   ;; Keep at least one word even if fill prefix exceeds margin.
-                   ;; This handles the first line of the paragraph.
-                   ;; Don't stop at a period followed by just one space.
+               ;; 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 ((first t))
                      (while (and (not (eobp))
                                  (or first
@@ -332,12 +359,12 @@ space does not end a sentence, so don't break a line there."
                                           (save-excursion (forward-char -1)
                                                           (and (looking-at "\\. ")
                                                                (not (looking-at "\\.  ")))))))
-                       (skip-chars-forward " ")
-                       (skip-chars-forward "^ \n")
+                       (skip-chars-forward " \t")
+                       (skip-chars-forward "^ \t\n")
                        (setq first nil))))
                ;; Replace whitespace here with one newline, then indent to left
                ;; margin.
-               (skip-chars-backward " ")
+               (skip-chars-backward " \t")
                (insert ?\n)
                ;; Give newline the properties of the space(s) it replaces
                (set-text-properties (1- (point)) (point)
@@ -685,7 +712,7 @@ otherwise it is made canonical."
 (defun unjustify-current-line ()
   "Remove justification whitespace from current line.
 If the line is centered or right-justified, this function removes any
-indentation past the left margin.  If the line is full-jusitified, it removes
+indentation past the left margin.  If the line is full-justified, it removes
 extra spaces between words.  It does nothing in other justification modes."
   (let ((justify (current-justification)))
     (cond ((eq 'left justify) nil)
@@ -711,7 +738,7 @@ extra spaces between words.  It does nothing in other justification modes."
 (defun unjustify-region (&optional begin end)
   "Remove justification whitespace from region.
 For centered or right-justified regions, this function removes any indentation
-past the left margin from each line.  For full-jusitified lines, it removes 
+past the left margin from each line.  For full-justified lines, it removes 
 extra spaces between words.  It does nothing in other justification modes.
 Arguments BEGIN and END are optional; default is the whole buffer."
   (save-excursion