2

I am using emacs -q and editing a text buffer foo.txt.

I have added the following settings:

(setq comment-start ">::")
(setq comment-padding ":::<")

Now if I select a region containing these lines

foo
bar
baz

and press M-;, I get this commented out like this

>:::::<foo
>:::::<bar
>:::::<baz

Looks fine so far. But now I change the settings to like this:

(setq comment-start ">  ")
(setq comment-padding "   <")

Now if I comment the same region as earlier again with M-q I get:

>   <foo
>   <bar
>   <baz

But I was expecting

>     <foo
>     <bar
>     <baz

Why is the commenting prefix string > < instead of > <? The comment start string contributes 2 spaces and the comment padding string contributes 3 spaces. So there should have been 5 spaces. But there are only 3 spaces. Why?

1
  • Why questions are tricky: they can lead to a cascade of opinion-based comments/answers. In my answer I explain through the existing code why the behavior is consistent with how the code is designed, without attempting to explain why it was designed this way (apart from a guess and a suggestion of what it would require to change it).
    – NickD
    Commented Apr 22, 2023 at 14:52

1 Answer 1

2

The function used to construct the initial comment string is comment-padright. Its doc string says:

comment-padright is a byte-compiled Lisp function in ‘newcomment.el’.

(comment-padright STR &optional N)

Construct a string composed of STR plus ‘comment-padding’.
It also adds N copies of the last non-whitespace chars of STR.
If STR already contains padding, the corresponding amount is
ignored from ‘comment-padding’.
N defaults to 0.
If N is ‘re’, a regexp is returned instead, that would match
the string for any N.

Ensure that ‘comment-normalize-vars’ has been called before you use this.

It is used by comment-region (through its subordinate default function comment-region-default-1 as follows:

  ...
  (let ((s (comment-padright comment-start numarg)))
        ...)
    ...

to construct the opening string.

As the doc string states, If STR already contains padding, the corresponding amount is ignored from ‘comment-padding’. That explains why the extra spaces in comment-padding don't do anything. But why do the colons matter in the previous case? A comment in comment-padright itself explains that:

    ...
    (if (not (string-match-p "\\`\\s-" comment-padding))
        ;; If the padding isn't spaces, then don't
        ;; shorten the padding.
        comment-padding
      (substring comment-padding ;additional right padding
                 (min (- (match-end 0) (match-end 1))
                      (length comment-padding)))))))
    ...

It's only spaces as padding that are discarded. See the code in newcomment.el. The line number in this link is correct at the time of writing, but it may change in the future, so you may have to search a bit to find the comment-padright function.

So the behavior is as designed. Why it was designed this way however is another matter: I suspect that a choice was made on which reasonable people might disagree. If someone musters a compelling argument for doing it a different way, then a bug report describing the use case might cause the developers to make appropriate changes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.