www.delorie.com/gnu/docs/emacs/cc-mode_28.html   search  
 
Buy the book!


CC Mode Manual

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.5.1 Custom Indentation Functions

The most flexible way to customize CC Mode is by writing custom indentation functions, and associating them with specific syntactic symbols (see section 8. Syntactic Symbols). CC Mode itself uses 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))))

Indentation functions take a single argument, which is a syntactic component cons cell (see section 3.1 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.

The function should return nil if it's used in a situation where it doesn't want to do any decision. If the function is used in a list expression (see section 7. Customizing Indentation), that will cause CC Mode to go on and check the next entry in the list.

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(29):
 
(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 an extensive set of predefined indentation functions, not all of which are used by the default styles. So there's a good chance the function you want already exists. See section 9. Indentation Functions, for a list of them. If you have written an indentation function that you think is generally useful, you're very welcome to contribute it; please contact bug-cc-mode@gnu.org.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

  webmaster     delorie software   privacy  
  Copyright 2003   by The Free Software Foundation     Updated Jun 2003