2008-12-17

auto-detecting indentation style

When writing some C/C++-code, I usually follow a variant of the Linux coding style. Emacs understands this, if you put something like
(add-hook 'c-mode-common-hook
          (lambda ()
            (c-set-style "linux")))
in your .emacs. In practice, this means that e.g. pressing the Tab-key will do the right thing (there is a lot more to be said about that; but not here, not now).

However, sometimes I also need to edit other people's files, and they may use quite different settings - i.e., maybe they use spaces instead of tabs, or have the indentation set to 2(!). I may not like those settings, but I still want to respect them. If I would edit those files using my normal settings, I will likely screw up the existing code. It'd be nice if emacs would understand the existing settings, and use those instead of my own. Of course that is possible -- there are different ways to do that.

file local variables

First, the original author can explictly set the coding standard, i.e., if he or she puts something like
/* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
in the first line of the file, and Emacs will use those settings. See Specifying File Variables in the Emacs Manual for details. File-local variables can be useful sometimes, but they are not a very complete solution. They require original to actually add them, and changes are they don't; especially if they're not using emacs.

dtrt-indent

What I'd like instead is some way to auto-detect the settings for a file, and use those. And that is exactly what Julian Scheid's dtrt-indent does; add the following to your .emacs (if unclear, see the entries on hooks and external packages):
(add-hook 'c-mode-common-hook 
  (lambda()
    (require 'dtrt-indent)
    (dtrt-indent-mode t)))
With this, emacs will automatically update the indentation settings whenever you open a C/C++/Java/...-file. Some notes:
  • In addition to C-alike languages, dtrt-indent also supports shell, Ruby, and Perl, so you could add a hook to sh-mode, ruby-mode and perl-mode/cperl-mode as well;
  • dtrt-indent wisely lets itself be overridden by abovementioned file local variables, and will not change settings if it cannot determine the settings of the current file with some degree of reliability;
  • dtrt-indent currently only detects the indentation-style, not the coding style, ie. it does not detect if you want to put the '{' on the same line as the 'if', or on the next one. In practice, this turns out not to be a big problem, although it would be nice-to-have.
Anyway, a quite useful package, that I've been happily using for a while.

1 comment:

NorthboundTrain said...

I think it would be better to autoload the function, simplifying the add-hook call:

(autoload 'dtrt-indent-mode "dtrt-indent" "Adapt to foreign indentation offsets" t)
(add-hook 'c-mode-common-hook 'dtrt-indent-mode)

It's a subtle difference, to be sure, but a valid distinction, IMHO.