Subject: Re: bug#20256: 25.0.50; css-mode: filling multi-line comments

From: Simen Heggestøyl <[email-masked]>
Date: Sun, 26 Apr 2015 22:56:25 +0200

On Mon, Apr 20, 2015 at 6:09 PM, Stefan Monnier 
<[email-masked]> wrote:
> Would you like to do it?  I think all it would take is to move the 
> code
> there, set it in prog-mode (so that modes that derive from prog-mode 
> get
> to use this new code by default) and then make a few random tests in
> various major modes (mostly those that don't themselves set
> fill-paragraph-function).

Something along these lines?

 From 4b9c83f99c34fbe6a9b66dfbf9425f3daba2c8cd Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Simen=20Heggest=C3=B8yl?= <[email-masked]>
Date: Sat, 25 Apr 2015 19:19:08 +0200
Subject: [PATCH] Set default `fill-paragraph-function' in prog-mode

* lisp/progmodes/prog-mode.el (prog-fill-paragraph): New
function. Intended to be the default `fill-paragraph-function' for
modes that derive from prog-mode. Grown in css-mode, but now factored
out to prog-mode.
* lisp/progmodes/prog-mode.el (prog-mode): Set
`fill-paragraph-function'.
* lisp/textmodes/css-mode.el (css-fill-paragraph): Factor out code for
filling multi-line comments.
---
 lisp/progmodes/prog-mode.el |  46 ++++++++++++++++
 lisp/textmodes/css-mode.el  | 126 
++++++++++++++++----------------------------
 2 files changed, 91 insertions(+), 81 deletions(-)

diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el
index 0d9fabd..b64a3ee 100644
--- a/lisp/progmodes/prog-mode.el
+++ b/lisp/progmodes/prog-mode.el
@@ -145,11 +145,57 @@ support it."
 (define-globalized-minor-mode global-prettify-symbols-mode
   prettify-symbols-mode turn-on-prettify-symbols-mode)

+(defvar comment-continue)
+
+(defun prog-fill-paragraph (&optional justify)
+  (save-excursion
+    ;; Fill succeeding comment when invoked right before a multi-line
+    ;; comment.
+    (when (save-excursion
+            (beginning-of-line)
+            (comment-search-forward (point-at-eol) t))
+      (goto-char (match-end 0)))
+    (let ((ppss (syntax-ppss))
+          (eol (line-end-position)))
+      (when (and (nth 4 ppss)
+                 (save-excursion
+                   (goto-char (nth 8 ppss))
+                   (forward-comment 1)
+                   (prog1 (not (bolp))
+                     (setq eol (point)))))
+        ;; Filling inside a comment whose comment-end marker is not
+        ;; \n.  This code is meant to be generic, so that it works for
+        ;; all modes.
+        (save-restriction
+          (narrow-to-region (nth 8 ppss) eol)
+          (comment-normalize-vars)     ; Will define comment-continue.
+          (let ((fill-paragraph-function nil)
+                (paragraph-separate
+                 (if (and comment-continue
+                          (string-match "[^ \t]" comment-continue))
+                     (concat "\\(?:[ \t]*\\(?:"
+                             (regexp-quote comment-continue) "\\|"
+                             comment-start-skip "\\|"
+                             comment-end-skip "\\)\\)?"
+                             "\\(?:" paragraph-separate "\\)")
+                   paragraph-separate))
+                (paragraph-start
+                 (if (and comment-continue
+                          (string-match "[^ \t]" comment-continue))
+                     (concat "\\(?:[ \t]*"
+                             (regexp-quote comment-continue)
+                             "\\)?\\(?:" paragraph-start "\\)")
+                   paragraph-start)))
+            (fill-paragraph justify)
+            ;; Don't try filling again.
+            t))))))
+
 ;;;###autoload
 (define-derived-mode prog-mode fundamental-mode "Prog"
   "Major mode for editing programming language source code."
   (setq-local require-final-newline mode-require-final-newline)
   (setq-local parse-sexp-ignore-comments t)
+  (setq-local fill-paragraph-function #'prog-fill-paragraph)
   ;; Any programming language is always written left to right.
   (setq bidi-paragraph-direction 'left-to-right))

diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el
index 424cdb7..451688a 100644
--- a/lisp/textmodes/css-mode.el
+++ b/lisp/textmodes/css-mode.el
@@ -393,90 +393,54 @@ pseudo-classes, and at-rules."
             #'css-completion-at-point nil 'local))

 (defvar comment-continue)
+(declare-function prog-fill-paragraph "prog-mode" (&optional justify))

 (defun css-fill-paragraph (&optional justify)
-  (save-excursion
-    ;; Fill succeeding comment when invoked right before a multi-line
-    ;; comment.
-    (when (save-excursion
-            (beginning-of-line)
-            (comment-search-forward (point-at-eol) t))
-      (goto-char (match-end 0)))
-    (let ((ppss (syntax-ppss))
-          (eol (line-end-position)))
-      (cond
-       ((and (nth 4 ppss)
-             (save-excursion
-               (goto-char (nth 8 ppss))
-               (forward-comment 1)
-               (prog1 (not (bolp))
-                 (setq eol (point)))))
-        ;; Filling inside a comment whose comment-end marker is not \n.
-        ;; This code is meant to be generic, so that it works not only 
for
-        ;; css-mode but for all modes.
-        (save-restriction
-          (narrow-to-region (nth 8 ppss) eol)
-          (comment-normalize-vars)      ;Will define comment-continue.
-          (let ((fill-paragraph-function nil)
-                (paragraph-separate
-                 (if (and comment-continue
-                          (string-match "[^ \t]" comment-continue))
-                     (concat "\\(?:[ \t]*\\(?:"
-                             (regexp-quote comment-continue) "\\|"
-                             comment-start-skip "\\|"
-                             comment-end-skip "\\)\\)?"
-                             "\\(?:" paragraph-separate "\\)")
-                   paragraph-separate))
-                (paragraph-start
-                 (if (and comment-continue
-                          (string-match "[^ \t]" comment-continue))
-                     (concat "\\(?:[ \t]*" (regexp-quote 
comment-continue)
-                             "\\)?\\(?:" paragraph-start "\\)")
-                   paragraph-start)))
-            (fill-paragraph justify)
-            ;; Don't try filling again.
-            t)))
-
-       ((and (null (nth 8 ppss))
-             (or (nth 1 ppss)
-                 (and (ignore-errors
-                        (down-list 1)
-                        (when (<= (point) eol)
-                          (setq ppss (syntax-ppss)))))))
-        (goto-char (nth 1 ppss))
-        (let ((end (save-excursion
-                     (ignore-errors (forward-sexp 1) (copy-marker 
(point) t)))))
-          (when end
-            (while (re-search-forward "[{;}]" end t)
-              (cond
-               ;; This is a false positive inside a string or comment.
-               ((nth 8 (syntax-ppss)) nil)
-               ;; This is a false positive when encountering an
-               ;; interpolated variable (bug#19751).
-               ((eq (char-before (- (point) 1)) ?#) nil)
-               ((eq (char-before) ?\})
-                (save-excursion
-                  (forward-char -1)
-                  (skip-chars-backward " \t")
-                  (when (and (not (bolp))
-                             (scss-smie--not-interpolation-p))
-                    (newline))))
-               (t
-                (while
-                    (progn
-                      (setq eol (line-end-position))
-                      (and (forward-comment 1)
-                           (> (point) eol)
-                           ;; A multi-line comment should be on its 
own line.
-                           (save-excursion (forward-comment -1)
-                                           (when (< (point) eol)
-                                             (newline)
-                                             t)))))
-                (if (< (point) eol) (newline)))))
+  (or (prog-fill-paragraph justify)
+      (save-excursion
+        (let ((ppss (syntax-ppss))
+              (eol (line-end-position)))
+          (cond
+           ((and (null (nth 8 ppss))
+                 (or (nth 1 ppss)
+                     (and (ignore-errors
+                            (down-list 1)
+                            (when (<= (point) eol)
+                              (setq ppss (syntax-ppss)))))))
             (goto-char (nth 1 ppss))
-            (indent-region (line-beginning-position 2) end)
-            ;; Don't use the default filling code.
-            t)))))))
+            (let ((end (save-excursion
+                         (ignore-errors (forward-sexp 1) (copy-marker 
(point) t)))))
+              (when end
+                (while (re-search-forward "[{;}]" end t)
+                  (cond
+                   ;; This is a false positive inside a string or 
comment.
+                   ((nth 8 (syntax-ppss)) nil)
+                   ;; This is a false positive when encountering an
+                   ;; interpolated variable (bug#19751).
+                   ((eq (char-before (- (point) 1)) ?#) nil)
+                   ((eq (char-before) ?\})
+                    (save-excursion
+                      (forward-char -1)
+                      (skip-chars-backward " \t")
+                      (when (and (not (bolp))
+                                 (scss-smie--not-interpolation-p))
+                        (newline))))
+                   (t
+                    (while
+                        (progn
+                          (setq eol (line-end-position))
+                          (and (forward-comment 1)
+                               (> (point) eol)
+                               ;; A multi-line comment should be on 
its own line.
+                               (save-excursion (forward-comment -1)
+                                               (when (< (point) eol)
+                                                 (newline)
+                                                 t)))))
+                    (if (< (point) eol) (newline)))))
+                (goto-char (nth 1 ppss))
+                (indent-region (line-beginning-position 2) end)
+                ;; Don't use the default filling code.
+                t))))))))

 (defun css-adaptive-fill ()
   (when (looking-at "[ \t]*/\\*[ \t]*")
-- 
2.1.4