ccmode: Custom Braces
8.1.1 Custom Brace Hanging
--------------------------
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’ (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’).
-- Variable: c-syntactic-context
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
Semicolons and Commas::); (ii) when calling a line-up function
(Custom Line-Up); (iii) when calling a
c-special-indent-hook function (Other Indentation).
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.