Advanced Customizations
Custom Brace and Colon Hanging
The most flexible way to customize CC Mode is by writing custom indentation functions and associating them with specific syntactic symbols (see Syntactic Symbols). CC Mode itself uses custom indentation functions to provide more sophisticated indentation, for example when lining up C++ stream operator blocks:
1: void main(int argc, char**) 2: { 3: cout << "There were " 4: << argc 5: << "arguments passed to the program" 6: << endl; 7: }
In this example, lines 4 through 6 are assigned the stream-op
syntactic symbol. Here, stream-op
has an offset of +
, and
with a c-basic-offset
of 2, you can see that lines 4 through 6
are simply indented two spaces to the right of line 3. But perhaps we'd
like CC Mode to be a little more intelligent so that it aligns
all the `<<
' symbols in lines 3 through 6. To do this, we have
to write a custom indentation function which finds the column of first
stream operator on the first line of the statement. Here is sample
lisp code implementing this:
(defun c-lineup-streamop (langelem) ;; lineup stream operators (save-excursion (let* ((relpos (cdr langelem)) (curcol (progn (goto-char relpos) (current-column)))) (re-search-forward "<<\\|>>" (c-point 'eol) 'move) (goto-char (match-beginning 0)) (- (current-column) curcol))))
Custom indent functions take a single argument, which is a syntactic component cons cell (see Syntactic Analysis). The function returns an integer offset value that will be added to the running total indentation for the line. Note that what actually gets returned is the difference between the column that the first stream operator is on, and the column of the buffer relative position passed in the function's argument. Remember that CC Mode automatically adds in the column of the component's relative buffer position and we don't the column offset added in twice.
Now, to associate the function c-lineup-streamop
with the
stream-op
syntactic symbol, we can add something like the
following to our c++-mode-hook
[1]:
(c-set-offset 'stream-op 'c-lineup-streamop)
Now the function looks like this after re-indenting (using C-c C-q):
1: void main(int argc, char**) 2: { 3: cout << "There were " 4: << argc 5: << "arguments passed to the program" 6: << endl; 7: }
Custom indentation functions can be as simple or as complex as you like,
and any syntactic symbol that appears in c-offsets-alist
can have
a custom indentation function associated with it. CC Mode comes
with several standard custom indentation functions, not all of which are
used by the default styles.
c-lineup-arglist
--- lines up function argument lines under the
argument on the previous line.
c-lineup-arglist-intro-after-paren
--- similar to
c-lineup-arglist
, but works for argument lists that begin with an
open parenthesis followed by a newline.
c-lineup-arglist-close-under-paren
--- set your
arglist-close
syntactic symbol to this line-up function so that
parentheses that close argument lists will line up under the parenthesis
that opened the argument list.
c-lineup-close-paren
--- lines up the closing parenthesis under
its corresponding open parenthesis if that one is followed by code.
Otherwise, if the open parenthesis ends its line, no indentation is
added. Works with any ...-close
symbol.
c-lineup-streamop
--- lines up C++ stream operators
(e.g. `<<
' and `>>
').
c-lineup-multi-inher
--- lines up multiple inheritance lines.
c-indent-one-line-block
--- adds c-basic-offset
to the
indentation if the line is a one line block, otherwise 0. Intended to
be used with any opening brace symbol, e.g. substatement-open
.
c-lineup-C-comments
--- lines up C block comment continuation
lines.
c-lineup-comment
--- lines up comment only lines according to
the variable c-comment-only-line-offset
.
c-lineup-runin-statements
--- lines up statement
s for coding
standards which place the first statement in a block on the same line as
the block opening brace[2].
c-lineup-math
--- lines up math statement-cont
lines under
the previous line after the equals sign.
c-lineup-ObjC-method-call
--- for Objective-C code, lines up
selector arguments just after the message receiver.
c-lineup-ObjC-method-args
--- for Objective-C code, lines up the
colons that separate arguments by aligning colons vertically.
c-lineup-ObjC-method-args-2
--- similar to
c-lineup-ObjC-method-args
but lines up the colon on the current
line with the colon on the previous line.
c-lineup-dont-change
--- this lineup function returns the
indentation of the current line. Think of it as an identity function
for lineups; it is used for cpp-macro-cont
lines.
[1] It probably makes more sense to add this to c++-mode-hook
than c-mode-common-hook
since stream operators are only relevent for C++.
[2] Run-in style doesn't really work too well. You might need to write your own custom indentation functions to better support this style.