From 75f0ed7873a0c332cd1ba771ee8acc2217843e5a Mon Sep 17 00:00:00 2001
From: Gabor Melis <(none)>
Date: Mon, 24 Apr 2023 11:23:41 +0100
Subject: [PATCH] Add lisp-fill-string-by-source-column

With lisp-fill-string-by-source-column nil (the previous default
behaviour):

    (defgeneric foo ()
      (:documentation "The first line of this indented docstring is roughly as long as
    the rest. Using this option makes sense to ensure that docstrings are
    preformatted."))

With lisp-fill-string-by-source-column t:

    (defgeneric foo ()
      (:documentation "The line of this indented docstring is as
      roughly as long as long as rest. Use this option to make source
      code look nice."))
---
 lisp/emacs-lisp/lisp-mode.el | 31 +++++++++++++++++++++++--------
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index d44c9d6e23da..c8cc1a39de84 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -1435,6 +1435,16 @@ Any non-integer value means do not use a different value of
   :safe (lambda (x) (or (eq x t) (integerp x)))
   :group 'lisp)
 
+(defcustom lisp-fill-string-by-source-column t
+  "When true, `lisp-fill-paragraph' fills strings in `lisp-mode' in
+such a way that the resulting source code respects `fill-column'.
+Else, the lines of the string are filled as if the string started
+in column 0. For function docstrings, which are typically
+indented by 3 characters, the difference between the two is
+small."
+  :type 'boolean
+  :group 'lisp)
+
 (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
@@ -1501,14 +1511,19 @@ and initial semicolons."
                 ;; 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)))))
+                  (let ((beginning (save-excursion
+                                     (if lisp-fill-string-by-source-column
+                                         (progn
+                                           (beginning-of-line)
+                                           (point))
+                                       (1+ (point))))))
+                    ;; The string may be unterminated -- in that case, don't
+                    ;; narrow.
+                    (when (ignore-errors
+                            (progn
+                              (forward-sexp 1)
+                              t))
+                      (narrow-to-region beginning (1- (point))))))
                 ;; Move back to where we were.
                 (goto-char start)
                 ;; We should fill the first line of a string