dot-emacs: smarter indentation with tabs and spaces
In XMMS2, the coding guidelines require you to use a mix of tabs and spaces to indent code: tabs indent blocks, while spaces are used to align multi-line statements. It’s all very natural really:
[tab][tab][tab]foo_function (arg1, [tab][tab][tab] arg2, [tab][tab][tab] arg3)
Unfortunately, if you use the default C indentation mode in emacs, what you get (when breaking like with C-j or RET TAB) is the following:
[tab][tab][tab]foo_function (arg1, [tab][tab][tab][tab][tab] arg2, [tab][tab][tab][tab][tab] arg3)
So you mean to tweak the code yourself to fix the tabs. Tedious, annoying. We know better!
I wrote a hook to fix this. The idea is to fix tabs when we’re in an argument list context. It can probably be further improved (please send patches!), but it’s quite useful already.
Just add the following to your .emacs file.
"C mode with adjusted defaults for use with the xmms2."
(interactive)
(c-mode)
(c-set-style "K&R")
(setq tab-width 4)
(setq indent-tabs-mode t)
(setq c-basic-offset 4)
; Align closing paren with opening paren
(c-set-offset ‘arglist-close ‘c-lineup-arglist-intro-after-paren)
(add-hook ‘c-special-indent-hook ’smart-tab-indent-hook))
(defun get-nonempty-context ()
(let ((curr-context (car (c-guess-basic-syntax))))
(if (or (eq (car curr-context) ‘arglist-intro)
(eq (car curr-context) ‘arglist-cont)
(eq (car curr-context) ‘arglist-cont-nonempty)
(eq (car curr-context) ‘arglist-close))
curr-context
nil)))
(defun smart-tab-indent-hook ()
"Fixes indentation to pad with spaces in arglists."
(let ((nonempty-ctx (get-nonempty-context)))
(if nonempty-ctx
(let ((tabbed-columns (+ (point-at-bol)
(/ (c-langelem-col nonempty-ctx t)
tab-width)))
(orig-column (current-column)))
(tabify (point-at-bol) tabbed-columns)
(untabify tabbed-columns (point-at-eol))
; editing tabs screws the pointer position
(move-to-column orig-column)))))
Note: don’t forget the
bit, else it won’t work properly for the last argument before the closing parenthesis. And avoid using
to break lines, it can fail with this hook; use
instead, it’s smarter anyway!