Previous: Hanging Braces, Up: Hanging Braces [Contents][Index]

#### 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` (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`).

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 calling a c-hanging-semi&comma-criteria function (see Hanging Semicolons and Commas); (ii) when calling a line-up function (see Custom Line-Up); (iii) when calling a c-special-indent-hook function (see 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.

Previous: Hanging Braces, Up: Hanging Braces [Contents][Index]