Since some people asked for it, I turned this answer
into a package.
If you have Melpa configured, you can install it with
M-x package-install RET aggressive-indent
See the Readme for all the options, but the
simplest way to turn it on is:
(add-hook 'emacs-lisp-mode-hook #'aggressive-indent-mode)
The Old Answer
The following does auto-indentation only on elisp buffers. It has advantage of also working when you erase or yank stuff (instead of just typing). It's easy to add to other modes as well.
This function will indent whatever s-expression the point is currently inside.
You can bind it to a key if you'd like, but see below first.
(require 'cl-lib)
(defun endless/indent-defun ()
"Indent current defun.
Do nothing if mark is active (to avoid deactivating it), or if
buffer is not modified (to avoid creating accidental
modifications)."
(interactive)
(ignore-errors
(unless (or (region-active-p)
buffer-read-only
(null (buffer-modified-p)))
(let ((l (save-excursion (beginning-of-defun 1) (point)))
(r (save-excursion (end-of-defun 1) (point))))
(cl-letf (((symbol-function 'message) #'ignore))
(indent-region l r))))))
This hook will make it so that this function will be run after you
type anything, but only in elisp buffers. This should keep everything
always indented.
(add-hook
'emacs-lisp-mode-hook
(lambda ()
(add-hook 'post-command-hook
#'endless/indent-defun nil 'local)))
Try it! It works remarkably well.
Also, following @holocronweaver’s suggestion in the comments, you can use
something like the following for c-like languages:
(define-key c++-mode-map ";"
(lambda () (interactive)
(insert ";")
(endless/indent-defun)))
electric-indent-mode
is much better than mapping<return>
tonewline-and-indent