2016-03-06 Javascript Comments

I like to write the doc strings for functions using the following style, when writing Javascript (using `js-mode`).

/**
 * Erase floor tile, if any.
 */
function removeFloor (x, y) {
  var old   = Map.data.get(x, y).floor;
  if (old)
    replaceFloor(x, y, old, null);
}

By default, hitting `RET` inside a comment or writing long comment lines does nothing special. Here’s what I prefer:

(add-hook 'js-mode-hook
	  (lambda ()
	    (setq indent-tabs-mode nil
		  js-indent-level 2)
	    (idle-highlight-mode 1)
            ;; writing longer comments
            (setq-local comment-auto-fill-only-comments t)
            (auto-fill-mode 1)
            (setq-local comment-multi-line t)
            (local-set-key (kbd "RET") 'c-indent-new-comment-line)))

Writing long comment lines will fill them automatically, and when I hit `RET`, comments are continued using the prefix “ _ “ instead of just “ ”._

​#Emacs

Comments

(Please contact me if you want to remove your comment.)

Thanks for this, Alex. I don’t write Javascript often, and had never been sufficiently motivated to figure out why `(local-set-key (kbd "RET") (key-binding (kbd "M-j")))` was so broken for Javascript block comments. Presumably js-mode should actually be binding `M-j` to `c-indent-new-comment-line`

– Anonymous 2016-03-07 03:41 UTC

---

...in fact I see that it’s the *combination* of `(setq-local comment-multi-line t)` and `(local-set-key (kbd "RET") 'c-indent-new-comment-line)` which fixes this, rather than the command alone. (So that `comment-multi-line` setting is important for both the indent-new-comment-line behaviour and the auto-fill behaviour).

My `(local-set-key (kbd "RET") (key-binding (kbd "M-j")))` happens in `prog-mode-hook` so I’ve added the following at `js-mode-hook`:

`(setq-local comment-multi-line t)`

`(local-set-key [remap indent-new-comment-line] 'c-indent-new-comment-line))`

– Phil 2016-03-07 04:30 UTC

---

I did not consider using *remap*. Interesting.

My setup has the strange effect that `//` are also continued on the next line. That’s unexpected:

/**
 * test
 */
function () {
  foo; // bar
       // █

Actually, now that I’ve gone back, it seems to me that `comment-multi-line` can still be `nil`. I use `M-q` on long comments with `comment-multi-line` set to `nil` and got the following:

/**
 * test test test test test test test test test test test test test
 * test test test test test test test
 */
function () {
  foo; // bar test test test test test test test test test test test
       // test test test test test test test test
  quux;

Good enough for `M-q`? Yes.

But now I remember: `comment-multi-line` has an effect on `auto-fill-mode`. Here’s what you get as you type a long comment line with `comment-multi-line` set to `t`:

/**
 * test test test test test test test test test test test test test
 test █
 */
function () {
  foo; // bar
       //

Here’s what you get as you type a long comment line with `comment-multi-line` set to `nil`:

/**
 * test test test test test test test test test test test test test */
 /**test █
 */
function () {
  foo; // bar
       //

OK, so that explains `comment-multi-line`. I still thought I had a good solution for `auto-fill-mode` and now it seems that I don’t. Looking at `do-auto-fill` it seems that `fill-context-prefix` finds no prefix. It determines `first-line-prefix` to be the empty string and `second-line-prefix` to be “ _ “. So why isn’t it used?_

There’s this test: `(string-match re first-line-prefix)` with `re` being `\`.**”`. So where's the problem? Should`first-line-prefix`be`***`such that this test succeeds and`second-line-prefix` is picked? Because now we’re getting to “the longest common substring of both prefixes” resulting in the empty string.***

It seems to me that `fill-match-adaptive-prefix` ought to return `/**` and it does not. There, we find `(looking-at adaptive-fill-regexp)` which matches and `(match-string 0)` which returns the empty string.

Sooo... `(setq adaptive-fill-regexp "[ ]*\\(//+\\|/?\\**\\)[ ]*\\([ ]*\\([-–!|#%;>*·•‣⁃◦]+[ ]*\\)*\\)")` fixes this by inserting `/?`. The segment in question is from `c-comment-prefix-regexp` which is set to `//+\\|\\**`. Now what? It’s doc string says: “it does not need to match a block comment starter” Does it?

So, I propose:

(setq c-comment-prefix-regexp "//+\\|/?\\**")
(let ((c-buffer-is-cc-mode t))
  (c-setup-paragraph-variables))

Either way, it’s not too bad in `//` comments:

/**
 * test
 */
function () {
  foo; // bar test test test test test test test test test test test
  // test █

– Alex Schroeder 2016-03-07 11:28 UTC