Posts Tagged ‘electric indentation’

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))
    (when js2-auto-indent-flag
      (mapc (lambda (key)
              (define-key map key #'js2-insert-and-indent))

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))

This is the diff:

<    (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)?


Read Full Post »