Emacs indentation difficulty

The EmacsWiki has a nice article on IndentingC.

In fact, EmacsWiki has nice articles on everything. I wouldn't want to have learned Emacs before it existed.


Indenting in emacs cc-mode is governed by a set of offsets, each of which can be set, according to a name attached to the offset.

The open-curly after an if statement has an offset, with a name. If you change the offset value, the open-curly will be indented differently. Likewise, the open-curly after a function declaration, has a named offset. Line continuations in a macro have a named offset. Case labels in a switch statement, do while loops. They all have offsets. There are a zillion of 'em, all stored in a variable called c-offsets-alist.

The styles mentioned in other places provide a "basic offset", which is normally 2, 4, or 8 spaces, and then a value for c-offsets-alist. Each style also has a name, and you can derive custom styles from other styles. Like this:

(c-add-style "myCStyle"
  '("bsd"  ; this must be defined elsewhere - it is in cc-modes.el
  (c-basic-offset . 4)
  (c-echo-syntactic-information-p . t)
  (c-comment-only-line-offset . (0 . 0))
  (c-offsets-alist . (
    (c                     . c-lineup-C-comments)
    (statement-case-open   . 0)
    (case-label            . +)
    (substatement-open     . 0)
    ))
  ))

The value for each named offset in c-offsets-alist is one of:

  • 0 implying, keep the indent the same as the previous line
  • + implying, increase the indent, one additional level
  • - implying, decrease the indent, one additional level

You can also use ++, --, and so on. Put something like that, to define a style, in your .emacs file. Then, to automatically employ that style when editing C files, use c-set=style in a c-mode hook, like this:

(defun doug-c-mode-hook-fn ()
  (cond (window-system
     ;; use my defined style for all C modules
     (c-set-style "myCStyle")
     ;; never convert leading spaces to tabs
     (setq indent-tabs-mode nil)
       ....
  )))

(add-hook 'c-mode-hook 'doug-c-mode-hook-fn)

The next question is, how does one determine which of the named c-offsets you need to set for any particular situation? There's an app for that. ok, not an app, but a elisp function.

M-x c-set-offset
Displays where emacs thinks it is, syntactically, in a cc-mode source file. To use it, place the cursor at the position where you'd like to learn the offset name, or change the offset. Then invoke this function. It will tell you the name of the offset for the current syntactical element.
If you change the value of that named element in your c-offsets-alist for your chosen style, something that is typically done in .emacs or your equivalent, then the indent setting will be true for all source modules.

alt text


Your defaults are possibly being overridden by cc-mode's style feature.

Try initialising the default style like this:

(setq c-default-style '((java-mode . "java") (awk-mode . "awk") (other . "user")))

You should be able to paste the preceding line into your .emacs file, or customize the c-default-style variable. The default has (other "gnu") as the last element of the list, which means that all non-Java and non-awk files get the gnu style instead of what you set with setq. The special user style gets initialised from your manually-set style variables.

Another option is to pick one of the built-in styles instead of defining it yourself, or to create your own style using the c-add-style function. To do this, change "user" in the above command to the name of the style (as a string). Try the the stroustrup or python built-in styles to format if-statements how you want.