Subject: bug#67462: 30.0.50; prog-fill-reindent-defun does not respect buffer-local fill-paragraph-function

From: Jens Schmidt <[email-masked]>
Date: Mon, 27 Nov 2023 21:08:32 +0100

Eli Zaretskii <[email-masked]> writes:

>> Cc: [email-masked]
>> Date: Sun, 26 Nov 2023 23:52:00 +0100
>> From:  Jens Schmidt via "Bug reports for GNU Emacs,
>>  the Swiss army knife of text editors" <[email-masked]>
>>
>> Dmitry Gutov <[email-masked]> writes:
>>
>> > Maybe makefile-mode-map should simply rebind "M-q" back to 'fill-paragraph'.
>>
>> I tried a cursory grep '(defun .*-fill-paragraph' in lisp/progmodes/.el.
>> The following functions all seem to work outside of comments:
>>
>>   cfengine-fill-paragraph
>>   f90-fill-paragraph
>>   fortran-fill-paragraph
>>   makefile-fill-paragraph
>>   octave-fill-paragraph
>>
>> I could be wrong with that list, though, and I cannot tell how useful
>> these functions are outside of comments.  I just looked at docstrings or
>> for a prominent
>>
>>   (or (fill-comment-paragraph justify)
>>       (do-something ...))
>>
>> pattern.
>
> What would it take to teach prog-fill-reindent-defun to DTRT outside
> comments and strings?

IMO the problem here is that some modes already have an idea of what
could be TRT outside comments and strings, implemented in a
mode-specific fill-paragraph-function.  prog-fill-reindent-defun per se
doesn't have that knowledge, since it currently always just reindents
outside comments and strings.

A very conservative aproach to keep that knowledge of such modes would
be something along the following lines:

diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el
index 37c54a90f42..df5aa845ae3 100644
--- a/lisp/progmodes/prog-mode.el
+++ b/lisp/progmodes/prog-mode.el
@@ -163,7 +163,13 @@ prog-fill-reindent-defun
                 (treesit-parser-list)
                 (treesit-node-match-p
                  (treesit-node-at (point)) 'text t))))
-      (if (or treesit-text-node
+      (if (or ;; Use `fill-paragraph-function' if bound locally,
+              ;; unless its declares to work on comments only.
+              (and (local-variable-p 'fill-paragraph-function)
+                   (or (not (symbolp fill-paragraph-function))
+                       (not (get fill-paragraph-function
+                                 'fills-only-comments))))
+              treesit-text-node
               (nth 8 (syntax-ppss))
               (re-search-forward "\\s-*\\s<" (line-end-position) t))
           (fill-paragraph argument (region-active-p))

That is, a mode using a specific fill-paragraph-function has to
explicitly declare (with property `fills-only-comments') that its
fill-paragraph-function only fills comments.  Only then that mode would
use the new default indentation of prog-fill-reindent-defun outside
comments and strings.

So for javascript mode, for example, we would also need:

diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 5a669fdbd42..5c1c1845378 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -2975,6 +2975,8 @@ js-fill-paragraph
         (fill-paragraph-function #'c-fill-paragraph))
     (c-fill-paragraph justify)))
 
+(put 'js-fill-paragraph 'fills-only-comments t)
+
 (defun js-do-auto-fill ()
   (let ((js--filling-paragraph t))
     (c-do-auto-fill)))