Subject: bug#385: [PATCH] comment-indent doesn't respect comment-indent-function

From: [email-masked]
Date: Wed, 14 Jun 2017 00:33:06 -0400

tags 19740 + patch
block 19740 by 385
quit

Stefan Monnier <[email-masked]> writes:

> If you need more control over the placement, rather than a variable
> comment-indent-fixed, maybe we should just say that if
> comment-indent-function returns a list of a single integer, it should be
> taken as the indentation position and not second-guessed.  Or it could
> return a cons cell (MIN . MAX) to say "anywhere between MIN and MAX".

Here's a patch.  This seems to be a prerequisite to fix #19740.

Regarding incompatibility of new comment-indent-functions for old Emacs,
some simple advice on comment-choose-indent should easily do the trick.

>From cc9db0dbb5590ee909386078128e55c5ee24f319 Mon Sep 17 00:00:00 2001
From: Noam Postavsky <[email-masked]>
Date: Wed, 14 Jun 2017 00:08:15 -0400
Subject: [PATCH v1] Allow comment-indent-functions to specify exact
 indentation (Bug#385)

* lisp/newcomment.el (comment-choose-indent): Interpret a cons of two
integers as indicating a range of acceptable indentation.
(comment-indent): Don't apply `comment-inline-offset',
`comment-choose-indent' already does that.
(comment-indent-function):
* doc/emacs/programs.texi (Options for Comments): Document new
acceptable return values.
* etc/NEWS: Announce it.
---
 doc/emacs/programs.texi |  9 ++++++---
 etc/NEWS                |  4 ++++
 lisp/newcomment.el      | 35 ++++++++++++++++++-----------------
 3 files changed, 28 insertions(+), 20 deletions(-)

diff --git a/doc/emacs/programs.texi b/doc/emacs/programs.texi
index 222d1c2a4d..27ac0eb640 100644
--- a/doc/emacs/programs.texi
+++ b/doc/emacs/programs.texi
@@ -1146,9 +1146,12 @@ Options for Comments
 various major modes.  The function is called with no arguments, but with
 point at the beginning of the comment, or at the end of a line if a new
 comment is to be inserted.  It should return the column in which the
-comment ought to start.  For example, in Lisp mode, the indent hook
-function bases its decision on how many semicolons begin an existing
-comment, and on the code in the preceding lines.
+comment ought to start.  For example, the default hook function bases
+its decision on how many comment characters begin an existing comment.
+
+Emacs also tries to align comments on adjacent lines.  To override
+this, the function may return a cons of two (possibly equal) integers
+to indicate an acceptable range of indentation.
 
 @node Documentation
 @section Documentation Lookup
diff --git a/etc/NEWS b/etc/NEWS
index 7e955ad26d..2467e81fe3 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -377,6 +377,10 @@ display of raw bytes from octal to hex.
 ** You can now provide explicit field numbers in format specifiers.
 For example, '(format "%2$s %1$s" "X" "Y")' produces "Y X".
 
++++
+** 'comment-indent-function' values may now return a cons to specify a
+range of indentation.
+
 
 * Editing Changes in Emacs 26.1
 
diff --git a/lisp/newcomment.el b/lisp/newcomment.el
index 118549f421..8772b52376 100644
--- a/lisp/newcomment.el
+++ b/lisp/newcomment.el
@@ -142,9 +142,10 @@ (put 'comment-end 'safe-local-variable 'stringp)
 ;;;###autoload
 (defvar comment-indent-function 'comment-indent-default
   "Function to compute desired indentation for a comment.
-This function is called with no args with point at the beginning of
-the comment's starting delimiter and should return either the desired
-column indentation or nil.
+This function is called with no args with point at the beginning
+of the comment's starting delimiter and should return either the
+desired column indentation, a range of acceptable
+indentation (MIN . MAX), or nil.
 If nil is returned, indentation is delegated to `indent-according-to-mode'.")
 
 ;;;###autoload
@@ -649,13 +650,20 @@ (defun comment-choose-indent (&optional indent)
 - prefer INDENT (or `comment-column' if nil).
 Point is expected to be at the start of the comment."
   (unless indent (setq indent comment-column))
-  ;; Avoid moving comments past the fill-column.
-  (let ((max (+ (current-column)
-                (- (or comment-fill-column fill-column)
-                   (save-excursion (end-of-line) (current-column)))))
-        (other nil)
-        (min (save-excursion (skip-chars-backward " \t")
-                             (if (bolp) 0 (+ comment-inline-offset (current-column))))))
+  (let ((other nil)
+        min max)
+    (pcase indent
+      (`(,lo . ,hi) (setq min lo) (setq max hi)
+       (setq indent comment-column))
+      (_ ;; Avoid moving comments past the fill-column.
+       (setq max (+ (current-column)
+                    (- (or comment-fill-column fill-column)
+                       (save-excursion (end-of-line) (current-column)))))
+       (setq min (save-excursion
+                   (skip-chars-backward " \t")
+                   ;; Leave at least `comment-inline-offset' space after
+                   ;; other nonwhite text on the line.
+                   (if (bolp) 0 (+ comment-inline-offset (current-column)))))))
     ;; Fix up the range.
     (if (< max min) (setq max min))
     ;; Don't move past the fill column.
@@ -750,13 +758,6 @@ (defun comment-indent (&optional continue)
 	  ;; If the comment is at the right of code, adjust the indentation.
 	  (unless (save-excursion (skip-chars-backward " \t") (bolp))
 	    (setq indent (comment-choose-indent indent)))
-	  ;; Update INDENT to leave at least one space
-	  ;; after other nonwhite text on the line.
-	  (save-excursion
-	    (skip-chars-backward " \t")
-	    (unless (bolp)
-	      (setq indent (max indent
-                                (+ (current-column) comment-inline-offset)))))
 	  ;; If that's different from comment's current position, change it.
 	  (unless (= (current-column) indent)
 	    (delete-region (point) (progn (skip-chars-backward " \t") (point)))
-- 
2.11.1