From: Maxim Cournoyer <maxim.cournoyer@gmail.com>
To: 56197@debbugs.gnu.org
Cc: Maxim Cournoyer <maxim.cournoyer@gmail.com>,
eliz@gnu.org, larsi@gnus.org, felix.lechner@lease-up.com,
stefankangas@gmail.com
Subject: bug#56197: [PATCH] lisp: Introduce lisp-fill-paragraph-as-displayed option.
Date: Sat, 4 Jan 2025 22:03:43 +0900 [thread overview]
Message-ID: <20250104130343.4801-1-maxim.cournoyer@gmail.com> (raw)
In-Reply-To: <87zgi2xcgm.fsf@gmail.com>
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. Introduce lisp-fill-paragraph-as-displayed
as a new option allowing users to easily opt out of this new behavior.
* lisp/emacs-lisp/lisp-mode.el (lisp-fill-paragraph-as-displayed): New
variable.
(lisp-fill-paragraph): Honor it, by avoiding the logic narrow to strings
before applying fill-paragraph.
* test/lisp/emacs-lisp/lisp-mode-tests.el
(lisp-fill-paragraph-respects-fill-column): Test it.
(lisp-fill-paragraph-docstring-boundaries): New test, as a safeguard to
avoid regressions.
Fixes: bug#56197
---
lisp/emacs-lisp/lisp-mode.el | 74 ++++++++++++++-----------
test/lisp/emacs-lisp/lisp-mode-tests.el | 47 ++++++++++++++++
2 files changed, 90 insertions(+), 31 deletions(-)
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index d0c32d238bc..cc9f6f51cb5 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
@@ -1431,6 +1431,16 @@ emacs-lisp-docstring-fill-column
:group 'lisp
:version "30.1")
+(defcustom lisp-fill-paragraph-as-displayed nil
+ "Fill paragraphs as displayed in the buffer, preserving surrounding
+context such as the leading indentation. This is useful if respecting
+`fill-column' is more important than avoiding surrounding code from
+being filled, and makes `lisp-fill-paragraph' behave as it used to in
+Emacs 27 and prior versions."
+ :type 'boolean
+ :group 'lisp
+ :version "31.0")
+
(defun lisp-fill-paragraph (&optional justify)
"Like \\[fill-paragraph], but handle Emacs Lisp comments and docstrings.
If any of the current line is a comment, fill the comment or the
@@ -1480,42 +1490,44 @@ 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)))
(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))
- ;; 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))
- (1- (point)))))
- ;; Move back to where we were.
- (goto-char start)
- ;; We should fill the first line of a string
- ;; separately (since it's usually a doc string).
- (if (= (line-number-at-pos) 1)
- (narrow-to-region (line-beginning-position)
- (line-beginning-position 2))
- (save-excursion
- (goto-char (point-min))
- (forward-line 1)
- (narrow-to-region (point) (point-max))))
+ (unless lisp-fill-paragraph-as-displayed
+ ;; 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 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+ string-start)
+ (1- (point)))))
+ ;; Move back to where we were.
+ (goto-char start)
+ ;; We should fill the first line of a string
+ ;; separately (since it's usually a doc string).
+ (if (= (line-number-at-pos) 1)
+ (narrow-to-region (line-beginning-position)
+ (line-beginning-position 2))
+ (save-excursion
+ (goto-char (point-min))
+ (forward-line 1)
+ (narrow-to-region (point) (point-max)))))
(fill-paragraph justify)))))))
;; Never return nil.
t)
diff --git a/test/lisp/emacs-lisp/lisp-mode-tests.el b/test/lisp/emacs-lisp/lisp-mode-tests.el
index da02be65d03..347b3d5b642 100644
--- a/test/lisp/emacs-lisp/lisp-mode-tests.el
+++ b/test/lisp/emacs-lisp/lisp-mode-tests.el
@@ -308,6 +308,53 @@ lisp-indent-defun
(indent-region (point-min) (point-max))
(should (equal (buffer-string) orig)))))
+\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-as-displayed ()
+ "Test bug#56197 -- more specifically, validate that a leading indentation
+for a string is preserved in the filled string."
+ (let ((lisp-fill-paragraph-as-displayed t) ;option under test
+ (source "\
+'(description \"This is a very 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.\")"))
+ (with-temp-buffer
+ ;; The following is a contrived example that demonstrates the
+ ;; fill-column problem when the string to fill is indented.
+ (insert source)
+ (emacs-lisp-mode)
+ (search-backward "This is a very long string")
+ (fill-paragraph) ;function under test
+ (goto-char (point-min))
+ (message "%s" (buffer-substring-no-properties (point-min) (point-max)))
+ (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
--
2.46.0
next prev parent reply other threads:[~2025-01-04 13:03 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 ` bug#56197: lisp-fill-paragraph behavior changed in " Maxim Cournoyer
2025-01-04 10:14 ` 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 ` Maxim Cournoyer [this message]
2025-01-04 14:02 ` bug#56197: [PATCH] lisp: Introduce lisp-fill-paragraph-as-displayed option 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=20250104130343.4801-1-maxim.cournoyer@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.