1 ;;; cc-align.el --- custom indentation functions for CC Mode
3 ;; Copyright (C) 1985,1987,1992-2000 Free Software Foundation, Inc.
5 ;; Authors: 2000- Martin Stjernholm
6 ;; 1998-1999 Barry A. Warsaw and Martin Stjernholm
7 ;; 1992-1997 Barry A. Warsaw
8 ;; 1987 Dave Detlefs and Stewart Clamen
9 ;; 1985 Richard M. Stallman
10 ;; Maintainer: bug-cc-mode@gnu.org
11 ;; Created: 22-Apr-1997 (split from cc-mode.el)
12 ;; Version: See cc-mode.el
13 ;; Keywords: c languages oop
15 ;; This file is part of GNU Emacs.
17 ;; GNU Emacs is free software; you can redistribute it and/or modify
18 ;; it under the terms of the GNU General Public License as published by
19 ;; the Free Software Foundation; either version 2, or (at your option)
22 ;; GNU Emacs is distributed in the hope that it will be useful,
23 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
24 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 ;; GNU General Public License for more details.
27 ;; You should have received a copy of the GNU General Public License
28 ;; along with GNU Emacs; see the file COPYING. If not, write to the
29 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
30 ;; Boston, MA 02111-1307, USA.
34 (if (and (boundp 'byte-compile-current-file
)
35 (stringp byte-compile-current-file
))
36 (cons (file-name-directory byte-compile-current-file
)
39 (load "cc-defs" nil t
)))
43 ;; Standard indentation line-ups
45 (defun c-lineup-arglist (langelem)
46 "Line up the current argument line under the first argument.
48 Works with: arglist-cont-nonempty."
50 (let* ((containing-sexp
52 ;; arglist-cont-nonempty gives relpos ==
53 ;; to boi of containing-sexp paren. This
54 ;; is good when offset is +, but bad
55 ;; when it is c-lineup-arglist, so we
56 ;; have to special case a kludge here.
57 (if (memq (car langelem
) '(arglist-intro arglist-cont-nonempty
))
61 (skip-chars-forward " \t" (c-point 'eol
)))
62 (goto-char (cdr langelem
)))
64 (langelem-col (c-langelem-col langelem t
)))
67 (looking-at "[ \t]*)"))
68 (progn (goto-char (match-end 0))
71 (c-forward-syntactic-ws)
72 (- (current-column) langelem-col
))
73 (goto-char containing-sexp
)
75 (not (memq (char-after) '(?
{ ?\
( ?\
[)))
76 (let ((eol (c-point 'eol
))
79 (skip-chars-forward " \t")
81 (c-forward-syntactic-ws)
84 (- (current-column) langelem-col
)
87 (defun c-lineup-arglist-intro-after-paren (langelem)
88 "Line up a line just after the open paren of the surrounding paren or
91 Works with: defun-block-intro, brace-list-intro,
92 statement-block-intro, statement-case-intro, arglist-intro."
94 (let ((langelem-col (c-langelem-col langelem t
))
95 (ce-curcol (save-excursion
98 (skip-chars-forward " \t" (c-point 'eol
))
100 (- ce-curcol langelem-col -
1))))
102 (defun c-lineup-arglist-close-under-paren (langelem)
103 "Line up a closing paren line under the corresponding open paren.
105 Works with: defun-close, class-close, inline-close, block-close,
106 brace-list-close, arglist-close, extern-lang-close, namespace-close
107 \(for most of these, a zero offset will normally produce the same
110 (let ((langelem-col (c-langelem-col langelem t
))
111 (ce-curcol (save-excursion
115 (- ce-curcol langelem-col
))))
117 (defun c-lineup-close-paren (langelem)
118 "Line up the closing paren under its corresponding open paren if the
119 open paren is followed by code. If the open paren ends its line, no
120 indentation is added. E.g:
124 ) <-> ) <- c-lineup-close-paren
126 Works with: defun-close, class-close, inline-close, block-close,
127 brace-list-close, arglist-close, extern-lang-close, namespace-close."
133 (setq spec
(c-looking-at-special-brace-list))
134 (if spec
(goto-char (car (car spec
))))
135 (setq opencol
(current-column))
138 (c-forward-syntactic-ws)
140 (c-forward-syntactic-ws (c-point 'eol
))
143 (- opencol
(c-langelem-col langelem t
))))
146 (defun c-lineup-streamop (langelem)
147 "Line up C++ stream operators under each other.
149 Works with: stream-op."
151 (let ((langelem-col (c-langelem-col langelem
)))
152 (re-search-forward "<<\\|>>" (c-point 'eol
) 'move
)
153 (goto-char (match-beginning 0))
154 (- (current-column) langelem-col
))))
156 (defun c-lineup-multi-inher (langelem)
157 "Line up the classes in C++ multiple inheritance clauses and member
158 initializers under each other. E.g:
160 class Foo: Foo::Foo (int a, int b):
161 public Cyphr, Cyphr (a),
162 public Bar <-> Bar (b) <- c-lineup-multi-inher
164 class Foo Foo::Foo (int a, int b)
165 : public Cyphr, : Cyphr (a),
166 public Bar <-> Bar (b) <- c-lineup-multi-inher
168 class Foo Foo::Foo (int a, int b)
169 : public Cyphr : Cyphr (a)
170 , public Bar <-> , Bar (b) <- c-lineup-multi-inher
172 Works with: inher-cont, member-init-cont."
174 (let* ((eol (c-point 'eol
))
176 (char-after-ip (progn
177 (skip-chars-forward " \t")
179 (langelem-col (c-langelem-col langelem
)))
181 ;; This kludge is necessary to support both inher-cont and
182 ;; member-init-cont, since they have different anchor positions.
183 (c-backward-syntactic-ws)
184 (when (eq (char-before) ?
:)
186 (c-backward-syntactic-ws))
188 (skip-chars-forward "^:" eol
)
189 (if (eq char-after-ip ?
,)
190 (skip-chars-forward " \t" eol
)
191 (skip-chars-forward " \t:" eol
))
193 (looking-at c-comment-start-regexp
))
194 (c-forward-syntactic-ws here
))
195 (- (current-column) langelem-col
)
198 (defun c-lineup-java-inher (langelem)
199 "Line up Java implements and extends declarations.
200 If class names follows on the same line as the implements/extends
201 keyword, they are lined up under each other. Otherwise, they are
202 indented by adding `c-basic-offset' to the column of the keyword.
206 extends extends Cyphr,
207 Bar <-> Bar <- c-lineup-java-inher
210 Works with: inher-cont."
212 (let ((langelem-col (c-langelem-col langelem
)))
214 (if (looking-at "[ \t]*$")
216 (c-forward-syntactic-ws)
217 (- (current-column) langelem-col
)))))
219 (defun c-lineup-java-throws (langelem)
220 "Line up Java throws declarations.
221 If exception names follows on the same line as the throws keyword,
222 they are lined up under each other. Otherwise, they are indented by
223 adding `c-basic-offset' to the column of the throws keyword. The
224 throws keyword itself is also indented by `c-basic-offset' from the
225 function declaration start if it doesn't hang. E.g:
227 int foo() int foo() throws Cyphr,
228 throws <-> Bar, <- c-lineup-java-throws
229 Bar <-> Vlod <- c-lineup-java-throws
230 <--><--> c-basic-offset
232 Works with: func-decl-cont."
234 (let* ((lim (1- (c-point 'bol
)))
236 (goto-char (cdr langelem
))
237 (while (zerop (c-forward-token-1 1 t lim
))
238 (if (looking-at "throws\\>[^_]")
241 (if (zerop (c-forward-token-1 1 nil
(c-point 'eol
)))
242 (- (current-column) (c-langelem-col langelem
))
243 (back-to-indentation)
244 (+ (- (current-column) (c-langelem-col langelem
))
248 (defun c-indent-one-line-block (langelem)
249 "Indent a one line block `c-basic-offset' extra.
252 if (n > 0) if (n > 0)
253 {m+=n; n=0;} <-> { <- c-indent-one-line-block
254 <--> c-basic-offset m+=n; n=0;
257 The block may be surrounded by any kind of parenthesis characters.
258 nil is returned if the line doesn't start with a one line block, which
259 makes the function usable in list expressions.
261 Work with: Almost all syntactic symbols, but most useful on *-open."
263 (let ((eol (c-point 'eol
)))
264 (back-to-indentation)
265 (if (and (eq (char-syntax (char-after)) ?\
()
266 (c-safe (progn (c-forward-sexp) t
))
271 (defun c-indent-multi-line-block (langelem)
272 "Indent a multi line block `c-basic-offset' extra.
275 int *foo[] = { int *foo[] = {
277 {17}, <-> { <- c-indent-multi-line-block
282 The block may be surrounded by any kind of parenthesis characters.
283 nil is returned if the line doesn't start with a multi line block,
284 which makes the function usable in list expressions.
286 Work with: Almost all syntactic symbols, but most useful on *-open."
288 (let ((eol (c-point 'eol
)))
289 (back-to-indentation)
290 (if (and (eq (char-syntax (char-after)) ?\
()
291 (or (not (c-safe (progn (c-forward-sexp) t
)))
296 (defun c-lineup-C-comments (langelem)
297 "Line up C block comment continuation lines.
298 Various heuristics are used to handle most of the common comment
299 styles. Some examples:
301 /* /** /* /* text /* /**
302 * text * text text text ** text ** text
305 /*********************************************************************
307 ********************************************************************/
309 /*********************************************************************
310 Free form text comments:
311 In comments with a long delimiter line at the start, the indentation
312 is kept unchanged for lines that start with an empty comment line
313 prefix. The delimiter line is whatever matches the
314 `comment-start-skip' regexp.
315 *********************************************************************/
317 The variable `c-comment-prefix-regexp' is used to recognize the
318 comment line prefix, e.g. the `*' that usually starts every line
321 Works with: The `c' syntactic symbol."
323 (let* ((here (point))
324 (prefixlen (progn (back-to-indentation)
325 (if (looking-at c-comment-prefix-regexp
)
326 (- (match-end 0) (point))
328 (starterlen (save-excursion
329 (goto-char (cdr langelem
))
330 (looking-at comment-start-skip
)
332 (goto-char (match-end 0))
333 (skip-chars-backward " \t")
335 (or (match-end 1) (point))
336 1))) ; Don't count the first '/'.
337 (langelem-col (save-excursion (c-langelem-col langelem
))))
338 (if (and (> starterlen
10) (zerop prefixlen
))
339 ;; The comment has a long starter and the line doesn't have
340 ;; a nonempty comment prefix. Treat it as free form text
341 ;; and don't change the indentation.
342 (- (current-column) langelem-col
)
344 (back-to-indentation)
345 (if (>= (cdr langelem
) (point))
346 ;; On the second line in the comment.
347 (if (zerop prefixlen
)
348 ;; No nonempty comment prefix. Align after comment
351 (goto-char (match-end 0))
352 (if (looking-at "\\([ \t]+\\).+$")
353 ;; Align with the text that hangs after the
355 (goto-char (match-end 1)))
356 (- (current-column) langelem-col
))
357 ;; How long is the comment starter? if greater than the
358 ;; length of the comment prefix, align left. if less
359 ;; than or equal, align right. this should also pick up
360 ;; Javadoc style comments.
361 (if (> starterlen prefixlen
)
363 (goto-char (cdr langelem
))
364 (- (current-column) -
1 langelem-col
))
365 (goto-char (match-end 0))
366 (skip-chars-backward " \t")
367 (- (current-column) prefixlen langelem-col
)))
368 ;; Not on the second line in the comment. If the previous
369 ;; line has a nonempty comment prefix, align with it.
370 ;; Otherwise, align with the previous nonempty line, but
371 ;; align the comment ender with the starter.
372 (when (or (not (looking-at c-comment-prefix-regexp
))
373 (eq (match-beginning 0) (match-end 0)))
375 (back-to-indentation)
376 (if (looking-at (concat "\\(" c-comment-prefix-regexp
"\\)\\*/"))
377 (goto-char (cdr langelem
))
378 (while (and (zerop (forward-line -
1))
379 (looking-at "^[ \t]*$")))
380 (back-to-indentation)
381 (if (< (point) (cdr langelem
))
382 ;; Align with the comment starter rather than
383 ;; with the code before it.
384 (goto-char (cdr langelem
)))))
385 (- (current-column) langelem-col
))))))
387 (defun c-lineup-comment (langelem)
388 "Line up a comment start according to `c-comment-only-line-offset'.
389 If the comment is lined up with a comment starter on the previous
390 line, that alignment is preserved.
392 Works with: comment-intro."
394 (back-to-indentation)
395 ;; this highly kludgiforous flag prevents the mapcar over
396 ;; c-syntactic-context from entering an infinite loop
397 (let ((recurse-prevention-flag (boundp 'recurse-prevention-flag
))
398 (col (current-column)))
400 (recurse-prevention-flag 0)
401 ;; CASE 1: preserve aligned comments
403 (and (c-forward-comment -
1)
404 (= col
(current-column))))
405 ;; we have to subtract out all other indentation
406 (- col
(apply '+ (mapcar 'c-get-offset
407 c-syntactic-context
))))
408 ;; indent as specified by c-comment-only-line-offset
410 (or (car-safe c-comment-only-line-offset
)
411 c-comment-only-line-offset
))
413 (or (cdr-safe c-comment-only-line-offset
)
414 (car-safe c-comment-only-line-offset
)
415 -
1000)) ;jam it against the left side
418 (defun c-lineup-runin-statements (langelem)
419 "Line up statements when the first statement is on the same line as
420 the block opening brace. E.g:
423 { puts (\"Hello world!\");
424 return 0; <- c-lineup-runin-statements
427 If there is no statement after the opening brace to align with, nil is
428 returned. This makes the function usable in list expressions.
430 Works with: The `statement' syntactic symbol."
431 (if (eq (char-after (cdr langelem
)) ?
{)
433 (let ((langelem-col (c-langelem-col langelem
)))
435 (skip-chars-forward " \t")
437 (- (current-column) langelem-col
))))))
439 (defun c-lineup-math (langelem)
440 "Line up the current line after the equal sign on the first line in
441 the statement. If there isn't any, indent with `c-basic-offset'. If
442 the current line contains an equal sign too, try to align it with the
445 Works with: statement-cont."
447 (let ((equalp (save-excursion
448 (goto-char (c-point 'boi
))
449 (skip-chars-forward "^=" (c-point 'eol
))
450 (and (eq (char-after) ?
=)
451 (- (point) (c-point 'boi
)))))
452 (langelem-col (c-langelem-col langelem
))
454 (while (and (not donep
)
455 (< (point) (c-point 'eol
)))
456 (skip-chars-forward "^=" (c-point 'eol
))
457 (if (c-in-literal (cdr langelem
))
460 (if (or (not (eq (char-after) ?
=))
463 (c-forward-syntactic-ws (c-point 'eol
))
465 ;; there's no equal sign on the line
467 ;; calculate indentation column after equals and ws, unless
468 ;; our line contains an equals sign
472 (skip-chars-forward " \t")
474 (- (current-column) equalp langelem-col
))
477 (defun c-lineup-template-args (langelem)
478 "Line up template argument lines under the first argument.
479 To allow this function to be used in a list expression, nil is
480 returned if there's no template argument on the first line.
482 Works with: template-args-cont."
484 (c-with-syntax-table c
++-template-syntax-table
487 (if (and (eq (char-after) ?
<)
488 (zerop (c-forward-token-1 1 nil
(c-point 'eol
))))
489 (- (current-column) (c-langelem-col langelem
))))))
491 (defun c-lineup-ObjC-method-call (langelem)
492 "Line up selector args as elisp-mode does with function args:
493 Go to the position right after the message receiver, and if you are at
494 the end of the line, indent the current line c-basic-offset columns
495 from the opening bracket; otherwise you are looking at the first
496 character of the first method call argument, so lineup the current
499 Works with: objc-method-call-cont."
501 (let* ((extra (save-excursion
502 (back-to-indentation)
503 (c-backward-syntactic-ws (cdr langelem
))
504 (if (eq (char-before) ?
:)
507 (open-bracket-pos (cdr langelem
))
508 (open-bracket-col (progn
509 (goto-char open-bracket-pos
)
514 (skip-chars-forward " \t")
516 (+ open-bracket-col c-basic-offset
)
519 (- target-col open-bracket-col extra
))))
521 (defun c-lineup-ObjC-method-args (langelem)
522 "Line up the colons that separate args.
523 The colon on the current line is aligned with the one on the first
526 Works with: objc-method-args-cont."
528 (let* ((here (c-point 'boi
))
529 (curcol (progn (goto-char here
) (current-column)))
531 (relpos (cdr langelem
))
532 (first-col-column (progn
534 (skip-chars-forward "^:" eol
)
535 (and (eq (char-after) ?
:)
537 (if (not first-col-column
)
540 (skip-chars-forward "^:" eol
)
541 (if (eq (char-after) ?
:)
542 (+ curcol
(- first-col-column
(current-column)))
545 (defun c-lineup-ObjC-method-args-2 (langelem)
546 "Line up the colons that separate args.
547 The colon on the current line is aligned with the one on the previous
550 Works with: objc-method-args-cont."
552 (let* ((here (c-point 'boi
))
553 (curcol (progn (goto-char here
) (current-column)))
555 (relpos (cdr langelem
))
556 (prev-col-column (progn
557 (skip-chars-backward "^:" relpos
)
558 (and (eq (char-before) ?
:)
559 (- (current-column) 1)))))
560 (if (not prev-col-column
)
563 (skip-chars-forward "^:" eol
)
564 (if (eq (char-after) ?
:)
565 (+ curcol
(- prev-col-column
(current-column)))
568 (defun c-lineup-inexpr-block (langelem)
569 "Line up the block for constructs that use a block inside an expression,
570 e.g. anonymous classes in Java and lambda functions in Pike. The body
571 is aligned with the start of the header, e.g. with the \"new\" or
572 \"lambda\" keyword. Returns nil if the block isn't part of such a
575 Works with: inlambda, inexpr-statement, inexpr-class."
577 (back-to-indentation)
578 (let ((res (or (c-looking-at-inexpr-block)
579 (if (c-safe (backward-up-list 1)
580 (eq (char-after) ?
{))
581 (c-looking-at-inexpr-block)))))
583 (goto-char (cdr res
))
586 (back-to-indentation)
587 (current-column)))))))
589 (defun c-lineup-whitesmith-in-block (langelem)
590 "Line up lines inside a block in whitesmith style.
591 It's done in a way that works both when the opening brace hangs and
592 when it doesn't. E.g:
596 foo; <-> foo; <- c-lineup-whitesmith-in-block
600 In the first case the indentation is kept unchanged, in the
601 second `c-basic-offset' is added.
603 Works with: defun-close, defun-block-intro, block-close,
604 brace-list-close, brace-list-intro, statement-block-intro, inclass,
605 inextern-lang, innamespace."
607 (goto-char (cdr langelem
))
608 (back-to-indentation)
609 (if (eq (char-syntax (char-after)) ?\
()
613 (defun c-lineup-dont-change (langelem)
614 "Do not change the indentation of the current line.
616 Works with: Any syntactic symbol."
618 (back-to-indentation)
619 (- (current-column) (c-langelem-col langelem
))))
622 (defun c-snug-do-while (syntax pos
)
623 "Dynamically calculate brace hanginess for do-while statements.
624 Using this function, `while' clauses that end a `do-while' block will
625 remain on the same line as the brace that closes that block.
627 See `c-hanging-braces-alist' for how to utilize this function as an
628 ACTION associated with `block-close' syntax."
631 (if (and (eq syntax
'block-close
)
632 (setq langelem
(assq 'block-close c-syntactic-context
))
633 (progn (goto-char (cdr langelem
))
634 (if (eq (char-after) ?
{)
635 (c-safe (c-forward-sexp -
1)))
636 (looking-at "\\<do\\>[^_]")))
640 (defun c-gnu-impose-minimum ()
641 "Imposes a minimum indentation for lines inside a top-level construct.
642 The variable `c-label-minimum-indentation' specifies the minimum
644 (let ((non-top-levels '(defun-block-intro statement statement-cont
645 statement-block-intro statement-case-intro
646 statement-case-open substatement substatement-open
647 case-label label do-while-closure else-clause
649 (syntax c-syntactic-context
)
652 (setq langelem
(car (car syntax
))
654 ;; don't adjust macro or comment-only lines
655 (cond ((memq langelem
'(cpp-macro comment-intro
))
657 ((memq langelem non-top-levels
)
660 (back-to-indentation)
661 (if (zerop (current-column))
662 (insert (make-string c-label-minimum-indentation
32)))
667 ;; Useful for c-hanging-semi&comma-criteria
669 (defun c-semi&comma-inside-parenlist
()
670 "Controls newline insertion after semicolons in parenthesis lists.
671 If a comma was inserted, no determination is made. If a semicolon was
672 inserted inside a parenthesis list, no newline is added otherwise a
673 newline is added. In either case, checking is stopped. This supports
674 exactly the old newline insertion behavior."
675 ;; newline only after semicolon, but only if that semicolon is not
676 ;; inside a parenthesis list (e.g. a for loop statement)
677 (if (not (eq last-command-char ?\
;))
678 nil
; continue checking
679 (if (condition-case nil
682 (not (eq (char-after) ?\
()))
687 ;; Suppresses newlines before non-blank lines
688 (defun c-semi&comma-no-newlines-before-nonblanks
()
689 "Controls newline insertion after semicolons.
690 If a comma was inserted, no determination is made. If a semicolon was
691 inserted, and the following line is not blank, no newline is inserted.
692 Otherwise, no determination is made."
694 (if (and (= last-command-char ?\
;)
696 ;; (save-excursion (skip-syntax-forward " ") (point))
697 (zerop (forward-line 1))
698 (not (looking-at "^[ \t]*$")))
702 ;; Suppresses new lines after semicolons in one-liners methods
703 (defun c-semi&comma-no-newlines-for-oneline-inliners
()
704 "Controls newline insertion after semicolons for some one-line methods.
705 If a comma was inserted, no determination is made. Newlines are
706 suppressed in one-liners, if the line is an in-class inline function.
707 For other semicolon contexts, no determination is made."
708 (let ((syntax (c-guess-basic-syntax))
710 (if (c-safe (up-list -
1) t
)
713 (if (and (eq last-command-char ?\
;)
714 (eq (car (car syntax
)) 'inclass
)
715 (eq (car (car (cdr syntax
))) 'topmost-intro
)
716 (= (c-point 'bol
) bol
))
722 ;;; cc-align.el ends here