Syntactic symbols aren’t the only place where you can customize
CC Mode with the lisp equivalent of callback functions. Remember
that actions are usually a list containing some combination of
the symbols before
and after
(see Hanging Braces).
For more flexibility, you can instead specify brace “hanginess” by
giving a syntactic symbol an action function in
c-hanging-braces-alist
; this function determines the
“hanginess” of a brace, usually by looking at the code near it.
An action function is called with two arguments: the syntactic symbol
for the brace (e.g. substatement-open
), and the buffer position
where the brace has been inserted. Point is undefined on entry to an
action function, but the function must preserve it (e.g. by using
save-excursion
). The return value should be a list containing
some combination of before
and after
, including neither
of them (i.e. nil
).
During the call to the indentation or brace hanging action
function, this variable is bound to the full syntactic analysis list.
This might be, for example, ‘((block-close 73))’. Don’t ever
give c-syntactic-context
a value yourself—this would disrupt
the proper functioning of CC Mode.
This variable is also bound in three other circumstances: (i) when calling a c-hanging-semi&comma-criteria function (see Hanging Semicolons and Commas); (ii) when calling a line-up function (see Custom Line-Up Functions); (iii) when calling a c-special-indent-hook function (see Other Special Indentations).
As an example, CC Mode itself uses this feature to dynamically determine the hanginess of braces which close “do-while” constructs:
void do_list( int count, char** atleast_one_string ) { int i=0; do { handle_string( atleast_one_string[i] ); i++; } while( i < count ); }
CC Mode assigns the block-close
syntactic symbol to the
brace that closes the do
construct, and normally we’d like the
line that follows a block-close
brace to begin on a separate
line. However, with “do-while” constructs, we want the
while
clause to follow the closing brace. To do this, we
associate the block-close
symbol with the action function
c-snug-do-while
:
(defun c-snug-do-while (syntax pos) "Dynamically calculate brace hanginess for do-while statements." (save-excursion (let (langelem) (if (and (eq syntax 'block-close) (setq langelem (assq 'block-close c-syntactic-context)) (progn (goto-char (cdr langelem)) (if (= (following-char) ?{) (forward-sexp -1)) (looking-at "\\<do\\>[^_]"))) '(before) '(before after)))))
This function simply looks to see if the brace closes a “do-while” clause and if so, returns the list ‘(before)’ indicating that a newline should be inserted before the brace, but not after it. In all other cases, it returns the list ‘(before after)’ so that the brace appears on a line by itself.