I'm getting started with some JS code in Spacemacs, and trying to get a good indentation level on my method chaining. The trouble is, once I've got an indentation to the place I want it, something (I'm assuming a function of js2-mode) re-indents the code to a different spot once I type an open paren.

Typing, good so far:

function renderChart(data) {
var x = d3.scaleLinear()

Then I try to add an open paren and get re-indented elsewhere:

function renderChart(data) {
var x = d3.scaleLinear()

Here's a gif so you can see it in action:

strange indentation behavior in js2-mode

Any clue what I can do to stop this from happening? Obviously auto-indentation is a useful feature when I'm starting a new line, but I'd rather it not happen mid-line when I've already got things to the place I want them. Thanks in advance!

  • If you toggle off electric-indent-local-mode in that buffer, does that stop the problem from occurring?
    – phils
    Mar 31, 2020 at 20:08
  • @phils It sort of trades one issue for another. I don't get lines jumping around now. But when I start a new line, instead of retaining the indentation level of the previous line, the new line is indented up to the level of its containing scope. Comments don't like newlines, so I'll try my best to convey here, with underscores for indentation. I get: thing.foo()\n_______.bar()\n.i-d-love-if-this-lined-up-with-bar-instead-of-thing()
    – Patrick
    Mar 31, 2020 at 20:39
  • To clarify, those underscores represent an indentation level that I tabbed/spaced over to manually that, delightfully, isn't being overridden, but which I would like to be held over to the next line
    – Patrick
    Mar 31, 2020 at 20:48
  • Ok, so we've confirmed that electric-indent is controlling this, so next have a look at C-h v electric-indent-chars and see whether it includes 40 which is the value of the ( character which I checked with M-: ?(. If so, I suggest testing with electric-indent enabled, but electric-indent-chars not containing that character. I'm guessing it would be a buffer-local value if it's set, so you might use M-: (setq-local electric-indent-chars '(x y z)) to set it to only chars x,y,z. By default that list is just (10) which is a newline.
    – phils
    Mar 31, 2020 at 21:05
  • Ah!!! Yes, this was set to a bunch of closure characters—()[]{} etc.—in addition to newline. I don't really want reindenting to happen on newlines either in JS though; I just get the jump when I hit enter instead of the paren. BUT you did point me in the right direction, where I discovered electric-indent-inhibit. I enabled this in js2-mode by adding to js2-mode-hook. Now if I can just figure out how to carry over the same indent level to the new line, rather than falling back to the indent level of the scope, but that might be another question entirely...
    – Patrick
    Apr 1, 2020 at 0:49

1 Answer 1


It turns out this feature—re-indenting a line while you're typing it—is called "electric indentation." Many modes will disable it when this type of strict indentation isn't useful, or the correct level can't be easily inferred, by setting the electric-indent-inhibit variable to t.

js2-mode doesn't do this automatically, but you can make it do so by adding to your init file. In the case of spacemacs, this means adding a new hook to your dotspacemacs/user-config:

(defun dotspacemacs/user-config ()
  ;; Maybe you have some other stuff in here already, then add:
  (add-hook 'js2-mode-hook #'(lambda () (setq-local electric-indent-inhibit t)))

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.