One thing I don’t understand is what is useful about electric indentation. This is when entering a special character such as a single or double quote or a semi-colon will automatically cause the current line to be re-indented.
I configure my programming modes to do an automatic indentation when I press the return key. For example, in my cc-config.el file I have this line.
(define-key c-mode-base-map (kbd "RET") 'newline-and-indent)
A Small Criticism of Yegge’s Javascript Mode
Steve Yegge’s javascript mode has a particularly unfortunate interaction with electric indentation. He wrote:
[Automatic indentation] turns out to be, oh, about fifty times harder than incremental parsing. Surprise!
…
I put a few tweaks into Karl’s original indenter code to handle JavaScript 1.7 situations such as array comprehensions, and then wrote a "bounce indenter" that cycles among N precomputed indentation points.
…
This moved the accuracy, at least for my own JavaScript editing, from 90% accurate with Karl’s mode up to 99.x% accurate, assuming you’re willing to hit TAB multiple times for certain syntactic contexts.
So, how does this interact with electric indentation? Pretty badly. Consider if you have the following line and the default indentation isn’t what you want.
if (...) { var x = "some string"; }
When you begin to enter your line, you tab it into your prefered location, then when you enter the quote for the beginning of the string, it resets the position back to the wrong place. No problem, you fix it again but then it breaks once again when you enter the closing quote. Suppressing your rising fury, you make the mistake of retabbing it for a third time then the semicolon at the end of the line causes another reindent and almost guarantees that you throw your PC through the window.
But, is it fixable? Well, Yegge did include a flag called js2-auto-indent-flag
but unfortunately it has to be set before the code is loaded otherwise the definition of the electric keys has already been trashed.
(defvar js2-mode-map
(let ((map (make-sparse-keymap))
keys)
...
(when js2-auto-indent-flag
(mapc (lambda (key)
(define-key map key #'js2-insert-and-indent))
js2-electric-keys))
...
The default definition of js2-insert-and-indent
doesn’t check this flag so I modified my copy to enable me to change the behaviour at runtime.
(defun js2-insert-and-indent (key) "Run command bound to key and indent current line. Runs the command bound to KEY in the global keymap and indents the current line." (interactive (list (this-command-keys))) (let ((cmd (lookup-key (current-global-map) key))) (if (commandp cmd) (call-interactively cmd))) ;; don't do the electric keys inside comments or strings, ;; and don't do bounce-indent with them. (let ((parse-state (parse-partial-sexp (point-min) (point))) (js2-bounce-indent-flag (js2-code-at-bol-p))) (unless (or (not js2-auto-indent-flag) (nth 3 parse-state) (nth 4 parse-state)) (indent-according-to-mode))))
This is the diff:
9901c9901,9902 < (unless (or (not js2-auto-indent-flag) --- > (unless (or (nth 3 parse-state) > (nth 4 parse-state))
So, back to the initial question: Does anyone use/like electric indentation and if so, how do you get around the problem described above (and why is auto-indent on carriage return not sufficient)?
Nope, don’t like it. I think automatic, enforced code formatting has great value for beginning programmers or maintainers-who-are-not-primarily-programmers, because it lets them a) immediately see when their code’s AST does not match their expectation, since that case almost always occurs when they make a mistake (as opposed to when an experienced programmer might intentionally violate an indentation style for a very good reason); and b) it allows them to ignore the maintenance-of indentation (have you seen bad/new/non-programmers’ indentation?? It’s usually incredibly offensive).
I think VB’s electric-indentation is perfectly matched to its user base, and I’ve seen some domain-specific “IDE”s that do this to great effect.
So in this context I think you should decide whether you want non-serious programmers to use your environment for programming; if so, definitely enforce electric-indentation. If not, forget it.
Hi Martin,
I didn’t think about protecting (more experienced programmers from) beginning programmers, that is a good point. However, I still don’t see why adding an indent after a carriage return wouldn’t be sufficient. Or alternatively, if you really want to force a particular indentation on people, why not make every keystroke cause a re-indent?
Thanks
In general I love electric-indentation if it can be assumed to do the right thing without any extra help. But js2-mode’s default indentation is infuriating. It was almost enough to make me ditch the mode entirely. Luckily I found a fix:
http://github.com/technomancy/emacs-starter-kit/blob/fe721654bd21825d36bace0f46a79271c5769cc1/starter-kit-js.el#L36
(I believe this was from a rejected (arg!) patch to js-2 from the tracker.)
Sorry, my reply was confused in the middle…here’s what I meant to say:
1) automatic, immediate code formatting (this is more than electric indentation or perhaps is electric indentation where every character is electric) can be useful in some domain-specific language cases, or some beginning-programming-language cases (this is what I meant by my first paragraph)
2) I suppose the electric indentation you speak of wouldn’t be *too* much more confusing to a beginning programmer than post-return indenting, though I have no emplirical basis for this supposition (this is what I meant by “I think VB’s electric-indentation is perfectly matched to its user base”)
3) I don’t personally like electric indentation except perhaps in some DSLs.
So I think I’m agreeing with your (implied) premise that you can’t see electric indentation’s benefit to you (personally), and answering your explicit question (“what is [as in, can be] useful about electric indentation”).
I can take or leave electric indentation — I find it can be nice in languages like C where often the indentation changes due to a line’s contents, and I don’t really want to add a new line afterwards.
However, I do feel strongly that a language mode should do correct indentation, without stupid workarounds like “oh just keep hitting TAB until it looks right”.
In this case, the thing that is broken is _not_ electric indentation, but the indenter. Maybe it’s a non-trivial problem for some languages (it seems vaguely odd that javascript would be one of them, but who knows…), and maybe yegge’s not up to solving it, but that doesn’t change the fact that it’s broken.
There are obviously languages like python which are incompatible with automatic indendation, but that’s a problem peculiar to such odd languages.
Of course, some people may simply dislike electric indentation — that’s fine, but it’s a personal preference, it doesn’t discount the fact that other people _do_ like it.
@phil – Yes, part of my point was that if you’re electric indenting it better be possible to configure the indent so it is correct first time. Thanks for the pointer to the patch, I’ll take a look. (and why is electric indent better for you than indenting after carriage return?)
@martin – thanks, that clarifies what you were saying, and yes I see why it would be good for a certain set of programmers.
@snogglethorpe – your second and third paragraphs neatly sum up what I meant by electric indent interacting particularly badly with js2.el. And now I think about it, perhaps it could be useful for closing braces/brackets/etc. and I was (am) getting hung up on electric indent on quotes. Thanks for the input.
I really hate this nasty feature of emacs. I write code in Java. After three week of sincere efforts, I found that there is a variable named “c-syntactic-indentation” that I can set to nil. Sigh of relief!