11.1 c-offsets-alist

This section explains the structure and semantics of the style variable c-offsets-alist, the principal variable for configuring indentation. Details of how to set it up, and its relationship to CC Mode’s style system are given in Style Variables.

User Option: c-offsets-alist

This is an alist which associates an offset with each syntactic symbol. This offset is a rule specifying how to indent a line whose syntactic context matches the symbol. See Syntactic Analysis.

Note that the buffer-local binding of this alist in a CC Mode buffer contains an entry for every syntactic symbol. Its global binding and its settings within style specifications usually contain only a few entries. See Style Variables.

The offset specification associated with any particular syntactic symbol can be an integer, a variable name, a vector, a function or lambda expression, a list, or one of the following special symbols: +, -, ++, --, *, or /. The meanings of these values are described in detail below.

Here is an example fragment of a c-offsets-alist, showing some of these kinds of offsets:

((statement . 0)
 (substatement . +)
 (cpp-macro . [0])
 (topmost-intro-cont . c-lineup-topmost-intro-cont)
 (statement-block-intro . (add c-lineup-whitesmith-in-block
                               c-indent-multi-line-block))
 …

)
Command: c-set-offset (C-c C-o)

This command changes the entry for a syntactic symbol in the current binding of c-offsets-alist, or it inserts a new entry if there isn’t already one for that syntactic symbol.

You can use c-set-offset interactively within a CC Mode buffer to make experimental changes to your indentation settings. C-c C-o prompts you for the syntactic symbol to change (defaulting to that of the current line) and the new offset (defaulting to the current offset).

c-set-offset takes two arguments when used programmatically: symbol, the syntactic element symbol to change and offset, the new offset for that syntactic element. You can call the command in your .emacs to change the global binding of c-offsets-alist (see Style Variables); you can use it in a hook function to make changes from the current style. CC Mode itself uses this function when initializing styles.

The “offset specifications” in c-offsets-alist can be any of the following:

An integer

The integer specifies a relative offset. All relative offsets44 will be added together and used to calculate the indentation relative to an anchor position earlier in the buffer. See Indentation Calculation, for details. Most of the time, it’s probably better to use one of the special symbols like + than an integer (apart from zero).

One of the symbols +, -, ++, --, *, or /

These special symbols describe a relative offset in multiples of c-basic-offset:

By defining a style’s indentation in terms of c-basic-offset, you can change the amount of whitespace given to an indentation level while maintaining the same basic shape of your code. Here are the values that the special symbols correspond to:

+

c-basic-offset times 1

-

c-basic-offset times -1

++

c-basic-offset times 2

--

c-basic-offset times -2

*

c-basic-offset times 0.5

/

c-basic-offset times -0.5

A vector

The first element of the vector, an integer, sets the absolute indentation column. This will override any previously calculated indentation, but won’t override relative indentation calculated from syntactic elements later on in the syntactic context of the line being indented. See Indentation Calculation. Any elements in the vector beyond the first will be ignored.

A function or lambda expression

The function will be called and its return value will in turn be evaluated as an offset specification. Functions are useful when more context than just the syntactic symbol is needed to get the desired indentation. See Line-Up Functions, and Custom Line-Up Functions, for details about them.

A symbol with a variable binding

If the symbol also has a function binding, the function takes precedence over the variable. Otherwise the value of the variable is used. It must be an integer (which is used as relative offset) or a vector (an absolute offset).

A list

The offset can also be a list containing several offset specifications; these are evaluated recursively and combined. A list is typically only useful when some of the offsets are line-up functions. A common strategy is calling a sequence of functions in turn until one of them recognizes that it is appropriate for the source line and returns a non-nil value.

nil values are always ignored when the offsets are combined. The first element of the list specifies the method of combining the non-nil offsets from the remaining elements:

first

Use the first offset that doesn’t evaluate to nil. Subsequent elements of the list don’t get evaluated.

min

Use the minimum of all the offsets. All must be either relative or absolute - they can’t be mixed.

max

Use the maximum of all the offsets. All must be either relative or absolute - they can’t be mixed.

add

Add all the evaluated offsets together. Exactly one of them may be absolute, in which case the result is absolute. Any relative offsets that preceded the absolute one in the list will be ignored in that case.

As a compatibility measure, if the first element is none of the above then it too will be taken as an offset specification and the whole list will be combined according to the method first.

If an offset specification evaluates to nil, then a relative offset of 0 (zero) is used45.


Footnotes

(44)

The syntactic context ((defun-block-intro 2724) (comment-intro)) would likely have two relative offsets.

(45)

There is however a variable c-strict-syntax-p that when set to non-nil will cause an error to be signaled in that case. It’s now considered obsolete since it doesn’t work well with some of the alignment functions that return nil instead of zero. You should therefore leave c-strict-syntax-p set to nil.