all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Maxim Cournoyer <maxim.cournoyer@gmail.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: larsi@gnus.org, 56197@debbugs.gnu.org,
	felix.lechner@lease-up.com, stefankangas@gmail.com
Subject: bug#56197: lisp-fill-paragraph behavior changed in Emacs 28
Date: Sat, 04 Jan 2025 19:09:42 +0900	[thread overview]
Message-ID: <87v7uuevq1.fsf_-_@gmail.com> (raw)
In-Reply-To: <87ttanrg9h.fsf@gmail.com> (Maxim Cournoyer's message of "Sun, 29 Dec 2024 00:14:50 +0900")

[-- Attachment #1: Type: text/plain, Size: 1176 bytes --]

Hi Eli et al.,

Maxim Cournoyer <maxim.cournoyer@gmail.com> writes:

[...]

>> I don't see how a user option to control this could be useful, since
>> the preferred behavior is not only buffer-local, but also specific to
>> certain syntactic constructs.  But I won't object to having such an
>> option.
>
> Having the behavior defined per-project or even globally (reverting to
> the the pre-Emacs 28 behavior) via a simple option seems like it'd
> simplify things, and make them discoverable.

I tried fixing this generally, as it seems to me that something in
lisp-mode should be meet the needs of all lisp-derived languages such as
Scheme and not just Elisp.  I first added two tests, one of which
ensures no regression to the original bug that lead to this current
behavioral change (bug#28937) and the other one that should pass once
the issue reported here (bug#56197) is resolved.

The last patch is a WIP that didn't work; I was hoping that inserting
spaces corresponding to the width of the indent in the narrowed string
would cause the indent to be preserved only for the first line.  I don't
have other ideas at the moment; I'd appreciate if someone could tip in.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-test-lisp-Add-new-test-for-filling-behavior-change.patch --]
[-- Type: text/x-patch, Size: 2115 bytes --]

From aacf65440070df2ba356af1d118a50993fc8f865 Mon Sep 17 00:00:00 2001
From: Maxim Cournoyer <maxim.cournoyer@gmail.com>
Date: Mon, 30 Dec 2024 12:02:36 +0900
Subject: [PATCH 1/3] test/lisp: Add new test for filling behavior change.

Starting with Emacs 28, filling strings now happens in a narrowed scope,
and looses the leading indentation and can cause the string to extend
past the fill-column value (see bug#56197).

* test/lisp/emacs-lisp/lisp-mode-tests.el
(lisp-fill-paragraph-respects-fill-column): New test.
---
 test/lisp/emacs-lisp/lisp-mode-tests.el | 27 +++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/test/lisp/emacs-lisp/lisp-mode-tests.el b/test/lisp/emacs-lisp/lisp-mode-tests.el
index da02be65d03..9a2b1ea4654 100644
--- a/test/lisp/emacs-lisp/lisp-mode-tests.el
+++ b/test/lisp/emacs-lisp/lisp-mode-tests.el
@@ -308,6 +308,33 @@ lisp-indent-defun
       (indent-region (point-min) (point-max))
       (should (equal (buffer-string) orig)))))
 
+\f
+;;; Filling
+
+(ert-deftest lisp-fill-paragraph-respects-fill-column ()
+  "Test bug#56197 -- more specifically, validate that a leading indentation
+for a string is preserved in the filled string."
+  (with-temp-buffer
+    ;; The following is a contrived example that demonstrates the
+    ;; fill-column problem when the string to fill is indented.
+    (insert "\
+\(defun test ()
+                         \"This is a long string which is indented by a considerable value,
+causing it to protrude from the configured `fill-column' since
+lisp-fill-paragraph was refactored in version 28.\"
+  (message \"Hi!\"))")
+    (emacs-lisp-mode)
+    (search-backward "This is a long string")
+    (fill-paragraph)                    ;function under test
+    (goto-char (point-min))
+    (let ((i 1)
+          (lines-count (count-lines (point-min) (point-max))))
+      (while (< i lines-count)
+        (beginning-of-line i)
+        (end-of-line)
+        (should (<= (current-column) fill-column))
+        (setq i (1+ i))))))
+
 \f
 ;;; Fontification
 

base-commit: e32484547d0813665334bfd34b741492dde0d374
-- 
2.46.0


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-test-lisp-Add-a-test-checking-docstring-boundaries-w.patch --]
[-- Type: text/x-patch, Size: 1436 bytes --]

From e5685497111ef71e57948f023f8d2a03647c3d69 Mon Sep 17 00:00:00 2001
From: Maxim Cournoyer <maxim.cournoyer@gmail.com>
Date: Mon, 30 Dec 2024 14:26:46 +0900
Subject: [PATCH 2/3] test/lisp: Add a test checking docstring boundaries when
 filling.

* test/lisp/emacs-lisp/lisp-mode-tests.el
(lisp-fill-paragraph-docstring-boundaries): New test.
---
 test/lisp/emacs-lisp/lisp-mode-tests.el | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/test/lisp/emacs-lisp/lisp-mode-tests.el b/test/lisp/emacs-lisp/lisp-mode-tests.el
index 9a2b1ea4654..eac2763c595 100644
--- a/test/lisp/emacs-lisp/lisp-mode-tests.el
+++ b/test/lisp/emacs-lisp/lisp-mode-tests.el
@@ -311,6 +311,25 @@ lisp-indent-defun
 \f
 ;;; Filling
 
+(ert-deftest lisp-fill-paragraph-docstring-boundaries ()
+  "Test bug#28937, ensuring filling the docstring filled is properly
+bounded."
+  (with-temp-buffer
+    (insert "\
+(defun test ()
+  \"This is a test docstring.
+Here is some more text.\"
+  1
+  2
+  3
+  4
+  5)")
+    (let ((correct (buffer-string)))
+      (emacs-lisp-mode)
+      (search-backward "This is a test docstring")
+      (fill-paragraph)                  ;function under test
+      (should (equal (buffer-string) correct)))))
+
 (ert-deftest lisp-fill-paragraph-respects-fill-column ()
   "Test bug#56197 -- more specifically, validate that a leading indentation
 for a string is preserved in the filled string."
-- 
2.46.0


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: 0003-wip-work-on-solution.patch --]
[-- Type: text/x-patch, Size: 3778 bytes --]

From 5bc5de2fc6f7783b0cd71c5945755fc98431aa60 Mon Sep 17 00:00:00 2001
From: Maxim Cournoyer <maxim.cournoyer@gmail.com>
Date: Tue, 31 Dec 2024 10:18:30 +0900
Subject: [PATCH 3/3] wip: work on solution

---
 lisp/emacs-lisp/lisp-mode.el | 33 +++++++++++++++++++++++----------
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index d0c32d238bc..6c6d88f73a5 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -1,6 +1,6 @@
 ;;; lisp-mode.el --- Lisp mode, and its idiosyncratic commands  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1985-1986, 1999-2024 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1999-2025 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: lisp, languages
@@ -1480,30 +1480,34 @@ lisp-fill-paragraph
                                   (derived-mode-p 'emacs-lisp-mode))
                              emacs-lisp-docstring-fill-column
                            fill-column)))
-        (let ((ppss (syntax-ppss))
-              (start (point))
-              ;; Avoid recursion if we're being called directly with
-              ;; `M-x lisp-fill-paragraph' in an `emacs-lisp-mode' buffer.
-              (fill-paragraph-function t))
+        (let* ((ppss (syntax-ppss))
+               (start (point))
+               ;; Avoid recursion if we're being called directly with
+               ;; `M-x lisp-fill-paragraph' in an `emacs-lisp-mode' buffer.
+               (fill-paragraph-function t)
+               (string-start (ppss-comment-or-string-start ppss))
+               (indent (save-excursion
+                         (goto-char string-start)
+                         (current-column))))
           (save-excursion
             (save-restriction
               ;; If we're not inside a string, then do very basic
               ;; filling.  This avoids corrupting embedded strings in
               ;; code.
-              (if (not (ppss-comment-or-string-start ppss))
+              (if (not string-start)
                   (lisp--fill-line-simple)
                 ;; If we're in a string, then narrow (roughly) to that
                 ;; string before filling.  This avoids filling Lisp
                 ;; statements that follow the string.
                 (when (ppss-string-terminator ppss)
-                  (goto-char (ppss-comment-or-string-start ppss))
+                  (goto-char string-start)
                   ;; The string may be unterminated -- in that case, don't
                   ;; narrow.
                   (when (ignore-errors
                           (progn
                             (forward-sexp 1)
                             t))
-                    (narrow-to-region (1+ (ppss-comment-or-string-start ppss))
+                    (narrow-to-region (1+ string-start)
                                       (1- (point)))))
                 ;; Move back to where we were.
                 (goto-char start)
@@ -1516,7 +1520,16 @@ lisp-fill-paragraph
                     (goto-char (point-min))
                     (forward-line 1)
                     (narrow-to-region (point) (point-max))))
-	        (fill-paragraph justify)))))))
+                ;; Insert spaces to reproduce the same leading indent
+                ;; for the string inside the narrowed region, to avoid
+                ;; bug#56197.
+                (save-excursion
+                  (goto-char (point-min))
+                  (insert (make-string indent ?\s)))
+	        (fill-paragraph justify)
+                (save-excursion         ;clean up
+                  (goto-char (point-min))
+                  (delete-char indent))))))))
   ;; Never return nil.
   t)
 
-- 
2.46.0


[-- Attachment #5: Type: text/plain, Size: 443 bytes --]


If that's not easily fixable, perhaps I'll submit a patch to the paredit
project so that they stop relying on lisp-paragraph-fill [0] and instead
use the default (which is fill-paragraph).  That's how I came to notice
this behavior change in GNU Guix, which is written in Scheme; using
scheme-mode doesn't exhibit the issue since it's just using
fill-paragraph.

[0]  https://paredit.org/cgit/paredit/tree/paredit.el#n1066

-- 
Thanks,
Maxim

  reply	other threads:[~2025-01-04 10:09 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-24 16:17 bug#56197: 28.1; lisp-fill-paragraph result regressed with Emacs 28 Maxim Cournoyer
2022-06-25 11:53 ` Lars Ingebrigtsen
2022-06-25 12:42   ` Eli Zaretskii
2022-06-25 12:45     ` Lars Ingebrigtsen
2022-06-25 12:48       ` Lars Ingebrigtsen
2022-06-25 13:00         ` Lars Ingebrigtsen
2022-06-29 18:03           ` Stefan Kangas
2022-06-30  9:32             ` Lars Ingebrigtsen
2022-06-30  9:33               ` Lars Ingebrigtsen
2024-12-26 15:16                 ` Stefan Kangas
2024-12-28  5:52                   ` Maxim Cournoyer
2024-12-28  8:47                     ` Eli Zaretskii
2024-12-28 14:51                       ` Maxim Cournoyer
2024-12-28  8:52                     ` Stefan Kangas
2022-06-30 11:31               ` Maxim Cournoyer
2022-07-01  9:05                 ` Lars Ingebrigtsen
2024-12-25 20:15             ` Felix Lechner via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-12-26  6:21               ` Eli Zaretskii
2024-12-28  5:26                 ` Maxim Cournoyer
2024-12-28  8:45                   ` Eli Zaretskii
2024-12-28 15:14                     ` Maxim Cournoyer
2025-01-04 10:09                       ` Maxim Cournoyer [this message]
2025-01-04 10:14                         ` bug#56197: lisp-fill-paragraph behavior changed in " Maxim Cournoyer
2025-01-04 14:04                         ` Eli Zaretskii
2025-01-04 14:19                           ` Eli Zaretskii
2022-06-27  1:53   ` bug#56197: 28.1; lisp-fill-paragraph result regressed with " Maxim Cournoyer
2025-01-04 13:03 ` bug#56197: [PATCH] lisp: Introduce lisp-fill-paragraph-as-displayed option Maxim Cournoyer
2025-01-04 14:02   ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87v7uuevq1.fsf_-_@gmail.com \
    --to=maxim.cournoyer@gmail.com \
    --cc=56197@debbugs.gnu.org \
    --cc=eliz@gnu.org \
    --cc=felix.lechner@lease-up.com \
    --cc=larsi@gnus.org \
    --cc=stefankangas@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.