ccmode: Indentation Calculation
10.3 Indentation Calculation
============================
Indentation for a line is calculated from the syntactic context (
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 (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.
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’.