Indentation for a line is calculated from the syntactic context (see Syntactic Analysis).
First, a buffer position is found whose column will be the base for the indentation calculation. It’s the anchor position in the first syntactic element that provides one that is used. If no syntactic element has an anchor position then column zero is used.
Second, the syntactic symbols in each syntactic element are looked up
in the c-offsets-alist
style variable
(see c-offsets-alist), which is an association list of syntactic
symbols and the offsets to apply for those symbols. These offsets are
added together with the base column to produce the new indentation
column.
Let’s use our two code examples above to see how this works. Here is our first example again:
1: void swap( int& a, int& b ) 2: { 3: int tmp = a; 4: a = b; 5: b = tmp; 6: }
Let’s say point is on line 3 and we hit the TAB key to reindent the line. The syntactic context for that line is:
((defun-block-intro 29))
Since buffer position 29 is the first and only anchor position in the list, CC Mode goes there and asks for the current column. This brace is in column zero, so CC Mode uses ‘0’ as the base column.
Next, CC Mode looks up defun-block-intro
in the
c-offsets-alist
style variable. Let’s say it finds the value
‘4’; it adds this to the base column ‘0’, yielding a running
total indentation of 4 spaces.
Since there is only one syntactic element on the list for this line, indentation calculation is complete, and the total indentation for the line is 4 spaces.
Here’s another example:
1: int add( int val, int incr, int doit ) 2: { 3: if( doit ) 4: { 5: return( val + incr ); 6: } 7: return( val ); 8: }
If we were to hit TAB on line 4 in the above example, the same basic process is performed, despite the differences in the syntactic context. The context for this line is:
((substatement-open 46))
Here, CC Mode goes to buffer position 46, which is the ‘i’ in
if
on line 3. This character is in the fourth column on that
line so the base column is ‘4’. Then CC Mode looks up the
substatement-open
symbol in c-offsets-alist
. Let’s say it
finds the value ‘4’. It’s added with the base column and yields an
indentation for the line of 8 spaces.
Simple, huh?
Actually, it’s a bit more complicated than that since the entries on
c-offsets-alist
can be much more than plain offsets.
See c-offsets-alist, for the full story.
Anyway, the mode usually just does The Right Thing without you having to think about it in this much detail. But when customizing indentation, it’s helpful to understand the general indentation model being used.
As you configure CC Mode, you might want to set the variable
c-echo-syntactic-information-p
to non-nil
so that the
syntactic context and calculated offset always is echoed in the
minibuffer when you hit TAB.