Customizing Indentation
Top
Performance Issues
Here is a complete list of the recognized syntactic symbols as described
in the c-offsets-alist
variable, along with a brief description.
More detailed descriptions follow below.
string
--- inside multi-line string
c
--- inside a multi-line C style block comment
defun-open
--- brace that opens a function definition
defun-close
--- brace that closes a function definition
defun-block-intro
--- the first line in a top-level defun
class-open
--- brace that opens a class definition
class-close
--- brace that closes a class definition
inline-open
--- brace that opens an in-class inline method
inline-close
--- brace that closes an in-class inline method
func-decl-cont
--- the region between a function definition's
argument list and the function opening brace (excluding K&R argument
declarations). In C, you cannot put anything but whitespace and comments
between them; in C++ and Java, throws
declarations and other
things can appear in this context.
knr-argdecl-intro
--- first line of a K&R C argument declaration
knr-argdecl
--- subsequent lines in a K&R C argument declaration
topmost-intro
--- the first line in a topmost definition
topmost-intro-cont
--- topmost definition continuation lines
member-init-intro
--- first line in a member initialization list
member-init-cont
--- subsequent member initialization list lines
inher-intro
--- first line of a multiple inheritance list
inher-cont
--- subsequent multiple inheritance lines
block-open
--- statement block open brace
block-close
--- statement block close brace
brace-list-open
--- open brace of an enum or static array list
brace-list-close
--- close brace of an enum or static array list
brace-list-intro
--- first line in an enum or static array list
brace-list-entry
--- subsequent lines in an enum or static array list
statement
--- a C statement
statement-cont
--- a continuation of a C statement
statement-block-intro
--- the first line in a new statement block
statement-case-intro
--- the first line in a case `block'
statement-case-open
--- the first line in a case block starting
with brace
substatement
--- the first line after a conditional
substatement-open
--- the brace that opens a substatement block
case-label
--- a case or default label
access-label
--- C++ access control label
label
--- any non-special C label
do-while-closure
--- the `while' that ends a
do
-while
construct
else-clause
--- the `else' of an if
-else
construct
comment-intro
--- a line containing only a comment introduction
arglist-intro
--- the first line in an argument list
arglist-cont
--- subsequent argument list lines when no arguments
follow on the same line as the the arglist opening paren
arglist-cont-nonempty
--- subsequent argument list lines when at
least one argument follows on the same line as the arglist opening paren
arglist-close
--- the solo close paren of an argument list
stream-op
--- lines continuing a stream operator
inclass
--- the line is nested inside a class definition
cpp-macro
--- the start of a C preprocessor macro definition
cpp-macro-cont
--- subsequent lines of a multi-line C
preprocessor macro definition
friend
--- a C++ friend declaration
objc-method-intro
--- the first line of an Objective-C method definition
objc-method-args-cont
--- lines continuing an Objective-C method
definition
objc-method-call-cont
--- lines continuing an Objective-C method call
extern-lang-open
--- brace that opens an external language block
extern-lang-close
--- brace that closes an external language block
inextern-lang
--- analogous to `inclass' syntactic symbol, but
used inside external language blocks (e.g. extern "C" {
).
namespace-open
--- brace that opens a C++ namespace block.
namespace-close
--- brace that closes a C++ namespace block.
innamespace
--- analogous to `inextern-lang' syntactic symbol,
but used inside C++ namespace blocks.
template-args-cont
--- C++ template argument list continuations
Most syntactic symbol names follow a general naming convention. When a
line begins with an open or close brace, the syntactic symbol will
contain the suffix -open
or -close
respectively.
Usually, a distinction is made between the first line that introduces a
construct and lines that continue a construct, and the syntactic symbols
that represent these lines will contain the suffix -intro
or
-cont
respectively. As a sub-classification of this scheme, a
line which is the first of a particular brace block construct will
contain the suffix -block-intro
.
Let's look at some examples to understand how this works. Remember that you can check the syntax of any line by using C-c C-s.
1: void 2: swap( int& a, int& b ) 3: { 4: int tmp = a; 5: a = b; 6: b = tmp; 7: int ignored = 8: a + b; 9: }
Line 1 shows a topmost-intro
since it is the first line that
introduces a top-level construct. Line 2 is a continuation of the
top-level construct introduction so it has the syntax
topmost-intro-cont
. Line 3 shows a defun-open
since it is
the brace that opens a top-level function definition. Line 9 is a
defun-close
since it contains the brace that closes the top-level
function definition. Line 4 is a defun-block-intro
, i.e. it is
the first line of a brace-block, enclosed in a
top-level function definition.
Lines 5, 6, and 7 are all given statement
syntax since there
isn't much special about them. Note however that line 8 is given
statement-cont
syntax since it continues the statement begun
on the previous line.
Here's another example, which illustrates some C++ class syntactic symbols:
1: class Bass 2: : public Guitar, 3: public Amplifiable 4: { 5: public: 6: Bass() 7: : eString( new BassString( 0.105 )), 8: aString( new BassString( 0.085 )), 9: dString( new BassString( 0.065 )), 10: gString( new BassString( 0.045 )) 11: { 12: eString.tune( 'E' ); 13: aString.tune( 'A' ); 14: dString.tune( 'D' ); 15: gString.tune( 'G' ); 16: } 17: friend class Luthier; 18: }
As in the previous example, line 1 has the topmost-intro
syntax.
Here however, the brace that opens a C++ class definition on line 4 is
assigned the class-open
syntax. Note that in C++, classes,
structs, and unions are essentially equivalent syntactically (and are
very similar semantically), so replacing the class
keyword in the
example above with struct
or union
would still result in a
syntax of class-open
for line 4 [1].
Similarly, line 18 is assigned class-close
syntax.
Line 2 introduces the inheritance list for the class so it is assigned
the inher-intro
syntax, and line 3, which continues the
inheritance list is given inher-cont
syntax.
Hitting C-c C-s on line 5 shows the following analysis:
((inclass . 1) (access-label . 67))
The primary syntactic symbol for this line is access-label
as
this a label keyword that specifies access protection in C++. However,
because this line is also a top-level construct inside a class
definition, the analysis actually shows two syntactic symbols. The
other syntactic symbol assigned to this line is inclass
.
Similarly, line 6 is given both inclass
and topmost-intro
syntax:
((inclass . 58) (topmost-intro . 60))
Line 7 introduces a C++ member initialization list and as such is given
member-init-intro
syntax. Note that in this case it is
not assigned inclass
since this is not considered a
top-level construct. Lines 8 through 10 are all assigned
member-init-cont
since they continue the member initialization
list started on line 7.
Line 11's analysis is a bit more complicated:
((inclass . 1) (inline-open))
This line is assigned a syntax of both inline-open
and
inclass
because it opens an in-class C++ inline method
definition. This is distinct from, but related to, the C++ notion of an
inline function in that its definition occurs inside an enclosing class
definition, which in C++ implies that the function should be inlined.
If though, the definition of the Bass
constructor appeared
outside the class definition, the construct would be given the
defun-open
syntax, even if the keyword inline
appeared
before the method name, as in:
class Bass : public Guitar, public Amplifiable { public: Bass(); } inline Bass::Bass() : eString( new BassString( 0.105 )), aString( new BassString( 0.085 )), dString( new BassString( 0.065 )), gString( new BassString( 0.045 )) { eString.tune( 'E' ); aString.tune( 'A' ); dString.tune( 'D' ); gString.tune( 'G' ); }
Returning to the previous example, line 16 is given inline-close
syntax, while line 12 is given defun-block-open
syntax, and lines
13 through 15 are all given statement
syntax. Line 17 is
interesting in that its syntactic analysis list contains three
elements:
((friend) (inclass . 58) (topmost-intro . 380))
The friend
syntactic symbol is a modifier that typically does not
have a relative buffer position.
Template definitions introduce yet another syntactic symbol:
1: ThingManager <int, 2: Framework::Callback *, 3: Mutex> framework_callbacks;
Here, line 1 is analyzed as a topmost-intro
, but lines 2 and 3
are both analyzed as template-args-cont
lines.
Here is another (totally contrived) example which illustrates how syntax is assigned to various conditional constructs:
1: void spam( int index ) 2: { 3: for( int i=0; i<index; i++ ) 4: { 5: if( i == 10 ) 6: { 7: do_something_special(); 8: } 9: else 10: do_something( i ); 11: } 12: do { 13: another_thing( i-- ); 14: } 15: while( i > 0 ); 16: }
Only the lines that illustrate new syntactic symbols will be discussed.
Line 4 has a brace which opens a conditional's substatement block. It
is thus assigned substatement-open
syntax, and since line 5 is
the first line in the substatement block, it is assigned
substatement-block-intro
syntax. Lines 6 and 7 are assigned
similar syntax. Line 8 contains the brace that closes the inner
substatement block. It is given the syntax block-close
,
as are lines 11 and 14.
Line 9 is a little different --- since it contains the keyword
else
matching the if
statement introduced on line 5, it is
given the else-clause
syntax. Note also that line 10 is slightly
different too. Because else
is considered a conditional
introducing keyword [2], and because
the following substatement is not a brace block, line 10 is assigned the
substatement
syntax.
One other difference is seen on line 15. The while
construct
that closes a do
conditional is given the special syntax
do-while-closure
if it appears on a line by itself. Note that if
the while
appeared on the same line as the preceding close brace,
that line would have been assigned block-close
syntax instead.
Switch statements have their own set of syntactic symbols. Here's an example:
1: void spam( enum Ingredient i ) 2: { 3: switch( i ) { 4: case Ham: 5: be_a_pig(); 6: break; 7: case Salt: 8: drink_some_water(); 9: break; 10: default: 11: { 12: what_is_it(); 13: break; 14: } 15: } 14: }
Here, lines 4, 7, and 10 are all assigned case-label
syntax,
while lines 5 and 8 are assigned statement-case-intro
. Line 11
is treated slightly differently since it contains a brace that opens a
block --- it is given statement-case-open
syntax.
There are a set of syntactic symbols that are used to recognize
constructs inside of brace lists. A brace list is defined as an
enum
or aggregate initializer list, such as might statically
initialize an array of structs. For example:
1: static char* ingredients[] = 2: { 3: "Ham", 4: "Salt", 5: NULL 6: }
Following convention, line 2 in this example is assigned
brace-list-open
syntax, and line 3 is assigned
brace-list-intro
syntax. Likewise, line 6 is assigned
brace-list-close
syntax. Lines 4 and 5 however, are assigned
brace-list-entry
syntax, as would all subsequent lines in this
initializer list.
External language definition blocks also have their own syntactic symbols. In this example:
1: extern "C" 2: { 3: int thing_one( int ); 4: int thing_two( double ); 5: }
line 2 is given the extern-lang-open
syntax, while line 5 is given
the extern-lang-close
syntax. The analysis for line 3 yields:
((inextern-lang) (topmost-intro . 14))
, where
inextern-lang
is a modifier similar in purpose to inclass
.
Similarly, C++ namespace constructs have their own associated syntactic symbols. In this example:
1: namespace foo 2: { 3: void xxx() {} 4: }
line 2 is given the namespace-open
syntax, while line 4 is given
the namespace-close
syntax. The analysis for line 3 yields:
((innamespace) (topmost-intro . 17))
, where innamespace
is
a modifier similar in purpose to inextern-lang
and inclass
.
A number of syntactic symbols are associated with parenthesis lists, a.k.a argument lists, as found in function declarations and function calls. This example illustrates these:
1: void a_function( int line1, 2: int line2 ); 3: 4: void a_longer_function( 5: int line1, 6: int line2 7: ); 8: 9: void call_them( int line1, int line2 ) 10: { 11: a_function( 12: line1, 13: line2 14: ); 15: 16: a_longer_function( line1, 17: line2 ); 18: }
Lines 5 and 12 are assigned arglist-intro
syntax since they are
the first line following the open parenthesis, and lines 7 and 14 are
assigned arglist-close
syntax since they contain the parenthesis
that closes the argument list.
Lines that continue argument lists can be assigned one of two syntactic
symbols. For example, Lines 2 and 17
are assigned arglist-cont-nonempty
syntax. What this means
is that they continue an argument list, but that the line containing the
parenthesis that opens the list is not empty following the open
parenthesis. Contrast this against lines 6 and 13 which are assigned
arglist-cont
syntax. This is because the parenthesis that opens
their argument lists is the last character on that line.
Note that there is no arglist-open
syntax. This is because any
parenthesis that opens an argument list, appearing on a separate line,
is assigned the statement-cont
syntax instead.
A few miscellaneous syntactic symbols that haven't been previously covered are illustrated by this C++ example:
1: void Bass::play( int volume ) 2: const 3: { 4: /* this line starts a multi-line 5: * comment. This line should get `c' syntax */ 6: 7: char* a_multiline_string = "This line starts a multi-line \ 8: string. This line should get `string' syntax."; 9: 10: note: 11: { 12: #ifdef LOCK 13: Lock acquire(); 14: #endif // LOCK 15: slap_pop(); 16: cout << "I played " 17: << "a note\n"; 18: } 19: }
The lines to note in this example include:
func-decl-cont
syntax;
defun-block-intro
and
comment-intro
syntax;
c
syntax;
defun-block-intro
. Note that the appearance of the
comment on lines 4 and 5 do not cause line 6 to be assigned
statement
syntax because comments are considered to be
syntactic whitespace, which are ignored when analyzing
code;
string
syntax;
label
syntax;
block-open
syntax;
cpp-macro
syntax.
stream-op
syntax.
Multi-line C preprocessor macros are now (somewhat) supported. At least CC Mode now recognizes the fact that it is inside a multi-line macro, and it properly skips such macros as syntactic whitespace. In this example:
1: #define LIST_LOOP(cons, listp) \ 2: for (cons = listp; !NILP (cons); cons = XCDR (cons)) \ 3: if (!CONSP (cons)) \ 4: signal_error ("Invalid list format", listp); \ 5: else
line 1 is given the syntactic symbol cpp-macro
. This first line
of a macro is always given this symbol. The second and subsequent lines
(e.g. lines 2 through 5) are given the cpp-macro-cont
syntactic
symbol, with a relative buffer position pointing to the #
which
starts the macro definition.
In Objective-C buffers, there are three additional syntactic symbols assigned to various message calling constructs. Here's an example illustrating these:
1: - (void)setDelegate:anObject 2: withStuff:stuff 3: { 4: [delegate masterWillRebind:self 5: toDelegate:anObject 6: withExtraStuff:stuff]; 7: }
Here, line 1 is assigned objc-method-intro
syntax, and line 2 is
assigned objc-method-args-cont
syntax. Lines 5 and 6 are both
assigned objc-method-call-cont
syntax.
Two other syntactic symbols can appear in old style, non-prototyped C code [3]:
1: int add_three_integers(a, b, c) 2: int a; 3: int b; 4: int c; 5: { 6: return a + b + c; 7: }
Here, line 2 is the first line in an argument declaration list and so is
given the knr-argdecl-intro
syntactic symbol. Subsequent lines
(i.e. lines 3 and 4 in this example), are given knr-argdecl
syntax.
[1] This is the case even for C and Objective-C. For consistency, structs in all supported languages are syntactically equivalent to classes. Note however that the keyword class
is meaningless in C and Objective-C.
[2] The list of conditional keywords are (in C, C++, Objective-C, and Java): for
, if
, do
, else
, while
, and switch
. C++ and Java have two additional conditional keywords: try
and catch
. Java also has the finally
and synchronized
keywords.
[3] a.k.a. K&R C, or Kernighan & Ritchie C