New Indentation Engine
Indentation Calculation
The first thing CC Mode does when indenting a line of code, is to
analyze the line, determining the syntactic component list of the
construct on that line. A syntactic component consists of a pair
of information (in lisp parlance, a cons cell), where the first
part is a syntactic symbol, and the second part is a relative buffer position. Syntactic symbols describe elements of C code
[1], e.g. statement
,
substatement
, class-open
, class-close
, etc.
See Syntactic Symbols, for a complete list of currently recognized
syntactic symbols and their semantics. The variable
c-offsets-alist
also contains the list of currently supported
syntactic symbols.
Conceptually, a line of C code is always indented relative to the indentation of some line higher up in the buffer. This is represented by the relative buffer position in the syntactic component.
Here is an example. Suppose we had the following code as the only thing
in a c++-mode
buffer [2]:
1: void swap( int& a, int& b ) 2: { 3: int tmp = a; 4: a = b; 5: b = tmp; 6: }
We can use the command C-c C-s
(c-show-syntactic-information
) to simply report what the
syntactic analysis is for the current line. Running this command on
line 4 of this example, we'd see in the echo area[3]:
((statement . 35))
This tells us that the line is a statement and it is indented relative
to buffer position 35, which happens to be the `i
' in int
on
line 3. If you were to move point to line 3 and hit C-c C-s, you
would see:
((defun-block-intro . 29))
This indicates that the `int
' line is the first statement in a top
level function block, and is indented relative to buffer position 29,
which is the brace just after the function header.
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: }
Hitting C-c C-s on line 4 gives us:
((substatement-open . 46))
which tells us that this is a brace that opens a substatement block. [4]
Syntactic component lists can contain more than one component, and individual syntactic components need not have relative buffer positions. The most common example of this is a line that contains a comment only line.
1: void draw_list( List<Drawables>& drawables ) 2: { 3: // call the virtual draw() method on each element in list 4: for( int i=0; i < drawables.count(), ++i ) 5: { 6: drawables[i].draw(); 7: } 8: }
Hitting C-c C-s on line 3 of this example gives:
((comment-intro) (defun-block-intro . 46))
and you can see that the syntactic component list contains two syntactic
components. Also notice that the first component,
`(comment-intro)
' has no relative buffer position.
[1] or C++, Objective-C, Java or IDL code. In general, for the rest of this manual I'll use the term ``C code'' to refer to all the C-like dialects, unless otherwise noted.
[2] The line numbers in this and future examples don't actually appear in the buffer, of course!
[3] With a universal argument (i.e. C-u C-c C-s) the analysis is inserted into the buffer as a comment on the current line.
[4] A substatement is the line after a conditional statement, such as if
, else
, while
, do
, switch
, etc. A substatement block is a brace block following one of these conditional statements.