Subject: Re: bug#20774: auto-fill doesn't work properly when first-line prefix differs in adaptive-fill-mode

From: Samuel Freilich <[email-masked]>
Date: Wed, 23 Aug 2017 14:20:20 -0400

tab-width = 4 seems consistent with how the rest of the file is formatted.
I didn't want to change the spacing in lines not touched by my diff.

I added tests and a change description, and formatted the patch according
to the current instructions. I made the patch a bit more minimal. I pruned
the part that dealt with adaptive-fill-first-line-regexp didn't work as
well as expected, since that didn't work as well as expected (it didn't
deal with all the complexity possible with adaptive-fill-function). The
updated version at least handles cases where the fill-prefix isn't shorter
than the first-line prefix. That allowed me to simplify the code quite a
bit, since that makes the previous logic for skipping the exact fill-prefix
redundant, fill-move-to-break-point already handles the logic of trying to
skip at least one word after the start position passed to it. Please take
another look.

You're correct about copyright. I'm doing this for work, copyright is
covered by whatever agreements Google has made.

On Tue, Aug 22, 2017 at 11:56 PM, <[email-masked]> wrote:

> Samuel Freilich <[email-masked]> writes:
>
> > Yes, that's correct. Sorry for getting that wrong in my initial
> > description of the bug. That's the same as the indentation behavior
> > with auto-fill-mode disabled. A hanging indent is not assumed with
> > only one line.
>
> Ah okay.  The patch looks fine (apart from the indentation being off, I
> assume because you had tab-width = 4).  Would you mind adding a commit
> message?  (See CONTRIBUTE for the format.)
>
> If you're feeling up to it, a test would be nice too.
>
> Since you're sending from a google.com address, I understand the
> copyright assignment is covered under Google's blanket agreement, is
> that right?
>
From b098b41ca457760a6ddde633cac37e70fbc8aeb9 Mon Sep 17 00:00:00 2001
From: Samuel Freilich <[email-masked]>
Date: Wed, 23 Aug 2017 13:40:45 -0400
Subject: [PATCH] Do not split line before length of fill-prefix

Previous logic already avoided splitting the line immediately after
the exact fill prefix, but in adaptive-fill-mode, the fill-prefix may
not be the same as the prefix of the first line of a paragraph. That
resulted in auto-fill-mode breaking lines in such a way as to make the
subsequent line as long or longer (Bug#20774).
---
 lisp/simple.el            | 26 +++++++++++---------------
 test/lisp/simple-tests.el | 11 +++++++++++
 2 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/lisp/simple.el b/lisp/simple.el
index 072723cd64..a1ba46f586 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -7148,18 +7148,17 @@ do-auto-fill
 	       (setq fill-prefix prefix))))
 
       (while (and (not give-up) (> (current-column) fc))
-	;; Determine where to split the line.
-	(let* (after-prefix
-	       (fill-point
-		(save-excursion
-		  (beginning-of-line)
-		  (setq after-prefix (point))
-		  (and fill-prefix
-		       (looking-at (regexp-quote fill-prefix))
-		       (setq after-prefix (match-end 0)))
-		  (move-to-column (1+ fc))
-		  (fill-move-to-break-point after-prefix)
-		  (point))))
+        ;; Determine where to split the line.
+        (let ((fill-point
+               (save-excursion
+                 (beginning-of-line)
+                 (let ((line-start (point)))
+                    (move-to-column (1+ fc))
+                    ;; Don't split earlier in the line than the length of the fill
+                    ;; prefix, since the resulting line would be longer.
+                    (fill-move-to-break-point (min (line-end-position)
+                                                   (+ line-start (length fill-prefix))))
+                    (point)))))
 
 	  ;; See whether the place we found is any good.
 	  (if (save-excursion
@@ -7167,9 +7166,6 @@ do-auto-fill
 		(or (bolp)
 		    ;; There is no use breaking at end of line.
 		    (save-excursion (skip-chars-forward " ") (eolp))
-		    ;; It is futile to split at the end of the prefix
-		    ;; since we would just insert the prefix again.
-		    (and after-prefix (<= (point) after-prefix))
 		    ;; Don't split right after a comment starter
 		    ;; since we would just make another comment starter.
 		    (and comment-start-skip
diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el
index ad7aee1db1..c7330e4034 100644
--- a/test/lisp/simple-tests.el
+++ b/test/lisp/simple-tests.el
@@ -497,5 +497,16 @@ simple-test-undo-with-switched-buffer
       (should (equal (line-number-at-pos 5) 3))
       (should (equal (line-number-at-pos 7) 4)))))
 
+(ert-deftest auto-fill-mode-no-break-before-length-of-fill-prefix ()
+  (with-temp-buffer
+    (setq-local fill-prefix "   ")
+    (set-fill-column 5)
+    ;; Shouldn't break after 'foo' (3 characters) when the next
+    ;; line is indented >= to that, that woudln't result in shorter
+    ;; lines.
+    (insert "foo bar")
+    (do-auto-fill)
+    (should (string-equal (buffer-string) "foo bar"))))
+
 (provide 'simple-test)
 ;;; simple-test.el ends here
-- 
2.14.1.342.g6490525c54-goog