1 ;;; cc-align.el --- custom indentation functions for CC Mode
3 ;; Copyright (C) 1985,1987,1992-2001 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 this program; see the file COPYING. If not, write to
29 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
30 ;; Boston, MA 02111-1307, USA.
34 (if (and (boundp 'byte-compile-dest-file)
35 (stringp byte-compile-dest-file))
36 (cons (file-name-directory byte-compile-dest-file) load-path)
38 (require 'cc-bytecomp)))
42 (cc-require 'cc-langs)
43 (cc-require 'cc-engine)
46 ;; Standard indentation line-ups
48 (defun c-lineup-arglist (langelem)
49 "Line up the current argument line under the first argument.
51 Works with: arglist-cont-nonempty."
53 (let* ((containing-sexp
55 ;; arglist-cont-nonempty gives relpos ==
56 ;; to boi of containing-sexp paren. This
57 ;; is good when offset is +, but bad
58 ;; when it is c-lineup-arglist, so we
59 ;; have to special case a kludge here.
60 (if (memq (car langelem) '(arglist-intro arglist-cont-nonempty))
64 (skip-chars-forward " \t" (c-point 'eol)))
65 (goto-char (cdr langelem)))
67 (langelem-col (c-langelem-col langelem t)))
70 (looking-at "[ \t]*)"))
71 (progn (goto-char (match-end 0))
74 (c-forward-syntactic-ws)
75 (- (current-column) langelem-col))
76 (goto-char containing-sexp)
78 (not (memq (char-after) '(?{ ?\( ?\[)))
79 (let ((eol (c-point 'eol))
82 (skip-chars-forward " \t")
84 (c-forward-syntactic-ws)
87 (- (current-column) langelem-col)
90 (defun c-lineup-arglist-intro-after-paren (langelem)
91 "Line up a line just after the open paren of the surrounding paren or
94 Works with: defun-block-intro, brace-list-intro,
95 statement-block-intro, statement-case-intro, arglist-intro."
97 (let ((langelem-col (c-langelem-col langelem t))
98 (ce-curcol (save-excursion
101 (skip-chars-forward " \t" (c-point 'eol))
103 (- ce-curcol langelem-col -1))))
105 (defun c-lineup-arglist-close-under-paren (langelem)
106 "Line up a closing paren line under the corresponding open paren.
108 Works with: defun-close, class-close, inline-close, block-close,
109 brace-list-close, arglist-close, extern-lang-close, namespace-close
110 \(for most of these, a zero offset will normally produce the same
113 (let ((langelem-col (c-langelem-col langelem t))
114 (ce-curcol (save-excursion
118 (- ce-curcol langelem-col))))
120 (defun c-lineup-close-paren (langelem)
121 "Line up the closing paren under its corresponding open paren if the
122 open paren is followed by code. If the open paren ends its line, no
123 indentation is added. E.g:
127 ) <-> ) <- c-lineup-close-paren
129 Works with: defun-close, class-close, inline-close, block-close,
130 brace-list-close, arglist-close, extern-lang-close, namespace-close."
136 (setq spec (c-looking-at-special-brace-list))
137 (if spec (goto-char (car (car spec))))
138 (setq opencol (current-column))
141 (c-forward-syntactic-ws)
143 (c-forward-syntactic-ws (c-point 'eol))
146 (- opencol (c-langelem-col langelem t))))
149 (defun c-lineup-streamop (langelem)
150 "Line up C++ stream operators under each other.
152 Works with: stream-op."
154 (let ((langelem-col (c-langelem-col langelem)))
155 (re-search-forward "<<\\|>>" (c-point 'eol) 'move)
156 (goto-char (match-beginning 0))
157 (- (current-column) langelem-col))))
159 (defun c-lineup-multi-inher (langelem)
160 "Line up the classes in C++ multiple inheritance clauses and member
161 initializers under each other. E.g:
163 class Foo: Foo::Foo (int a, int b):
164 public Cyphr, Cyphr (a),
165 public Bar <-> Bar (b) <- c-lineup-multi-inher
167 class Foo Foo::Foo (int a, int b)
168 : public Cyphr, : Cyphr (a),
169 public Bar <-> Bar (b) <- c-lineup-multi-inher
171 class Foo Foo::Foo (int a, int b)
172 : public Cyphr : Cyphr (a)
173 , public Bar <-> , Bar (b) <- c-lineup-multi-inher
175 Works with: inher-cont, member-init-cont."
177 (let* ((eol (c-point 'eol))
179 (char-after-ip (progn
180 (skip-chars-forward " \t")
182 (langelem-col (c-langelem-col langelem)))
184 ;; This kludge is necessary to support both inher-cont and
185 ;; member-init-cont, since they have different anchor positions.
186 (c-backward-syntactic-ws)
187 (when (eq (char-before) ?:)
189 (c-backward-syntactic-ws))
191 (skip-chars-forward "^:" eol)
192 (if (eq char-after-ip ?,)
193 (skip-chars-forward " \t" eol)
194 (skip-chars-forward " \t:" eol))
196 (looking-at c-comment-start-regexp))
197 (c-forward-syntactic-ws here))
198 (- (current-column) langelem-col)
201 (defun c-lineup-java-inher (langelem)
202 "Line up Java implements and extends declarations.
203 If class names follows on the same line as the implements/extends
204 keyword, they are lined up under each other. Otherwise, they are
205 indented by adding `c-basic-offset' to the column of the keyword.
209 extends extends Cyphr,
210 Bar <-> Bar <- c-lineup-java-inher
213 Works with: inher-cont."
215 (let ((langelem-col (c-langelem-col langelem)))
217 (if (looking-at "[ \t]*$")
219 (c-forward-syntactic-ws)
220 (- (current-column) langelem-col)))))
222 (defun c-lineup-java-throws (langelem)
223 "Line up Java throws declarations.
224 If exception names follows on the same line as the throws keyword,
225 they are lined up under each other. Otherwise, they are indented by
226 adding `c-basic-offset' to the column of the throws keyword. The
227 throws keyword itself is also indented by `c-basic-offset' from the
228 function declaration start if it doesn't hang. E.g:
230 int foo() int foo() throws Cyphr,
231 throws <-> Bar, <- c-lineup-java-throws
232 Bar <-> Vlod <- c-lineup-java-throws
233 <--><--> c-basic-offset
235 Works with: func-decl-cont."
237 (let* ((lim (1- (c-point 'bol)))
239 (goto-char (cdr langelem))
240 (while (zerop (c-forward-token-1 1 t lim))
241 (if (looking-at "throws\\>[^_]")
244 (if (zerop (c-forward-token-1 1 nil (c-point 'eol)))
245 (- (current-column) (c-langelem-col langelem))
246 (back-to-indentation)
247 (+ (- (current-column) (c-langelem-col langelem))
251 (defun c-indent-one-line-block (langelem)
252 "Indent a one line block `c-basic-offset' extra.
255 if (n > 0) if (n > 0)
256 {m+=n; n=0;} <-> { <- c-indent-one-line-block
257 <--> c-basic-offset m+=n; n=0;
260 The block may use any kind of parenthesis character. nil is returned
261 if the line doesn't start with a one line block, which makes the
262 function usable in list expressions.
264 Work with: Almost all syntactic symbols, but most useful on *-open."
266 (let ((eol (c-point 'eol)))
267 (back-to-indentation)
268 (if (and (eq (char-syntax (char-after)) ?\()
269 (c-safe (progn (c-forward-sexp) t))
274 (defun c-indent-multi-line-block (langelem)
275 "Indent a multi line block `c-basic-offset' extra.
278 int *foo[] = { int *foo[] = {
280 {17}, <-> { <- c-indent-multi-line-block
285 The block may use any kind of parenthesis character. nil is returned
286 if the line doesn't start with a multi line block, which makes the
287 function usable in list expressions.
289 Work with: Almost all syntactic symbols, but most useful on *-open."
291 (let ((eol (c-point 'eol)))
292 (back-to-indentation)
293 (if (and (eq (char-syntax (char-after)) ?\()
294 (or (not (c-safe (progn (c-forward-sexp) t)))
299 (defun c-lineup-C-comments (langelem)
300 "Line up C block comment continuation lines.
301 Various heuristics are used to handle many of the common comment
302 styles. Some examples:
304 /* /** /* /* text /* /**
305 * text * text text text ** text ** text
308 /*********************************************************************
310 ********************************************************************/
312 /*********************************************************************
313 Free form text comments:
314 In comments with a long delimiter line at the start, the indentation
315 is kept unchanged for lines that start with an empty comment line
316 prefix. The delimiter line is whatever matches the
317 `comment-start-skip' regexp.
318 *********************************************************************/
320 The variable `c-comment-prefix-regexp' is used to recognize the
321 comment line prefix, e.g. the `*' that usually starts every line
324 Works with: The `c' syntactic symbol."
326 (let* ((here (point))
327 (prefixlen (progn (back-to-indentation)
328 (if (looking-at c-current-comment-prefix)
329 (- (match-end 0) (point))
331 (starterlen (save-excursion
332 (goto-char (cdr langelem))
333 (looking-at comment-start-skip)
335 (goto-char (match-end 0))
336 (skip-chars-backward " \t")
338 (or (match-end 1) (point))
339 1))) ; Don't count the first '/'.
340 (langelem-col (save-excursion (c-langelem-col langelem))))
341 (if (and (> starterlen 10) (zerop prefixlen))
342 ;; The comment has a long starter and the line doesn't have
343 ;; a nonempty comment prefix. Treat it as free form text
344 ;; and don't change the indentation.
345 (- (current-column) langelem-col)
347 (back-to-indentation)
348 (if (>= (cdr langelem) (point))
349 ;; On the second line in the comment.
350 (if (zerop prefixlen)
351 ;; No nonempty comment prefix. Align after comment
354 (goto-char (match-end 0))
355 (if (looking-at "\\([ \t]+\\).+$")
356 ;; Align with the text that hangs after the
358 (goto-char (match-end 1)))
359 (- (current-column) langelem-col))
360 ;; How long is the comment starter? if greater than the
361 ;; length of the comment prefix, align left. if less
362 ;; than or equal, align right. this should also pick up
363 ;; Javadoc style comments.
364 (if (> starterlen prefixlen)
366 (goto-char (cdr langelem))
367 (- (current-column) -1 langelem-col))
368 (goto-char (match-end 0))
369 (skip-chars-backward " \t")
370 (- (current-column) prefixlen langelem-col)))
371 ;; Not on the second line in the comment. If the previous
372 ;; line has a nonempty comment prefix, align with it.
373 ;; Otherwise, align with the previous nonempty line, but
374 ;; align the comment ender with the starter.
375 (when (or (not (looking-at c-current-comment-prefix))
376 (eq (match-beginning 0) (match-end 0)))
378 (back-to-indentation)
379 (if (looking-at (concat "\\(" c-current-comment-prefix "\\)\\*/"))
380 (goto-char (cdr langelem))
381 (while (and (zerop (forward-line -1))
382 (looking-at "^[ \t]*$")))
383 (back-to-indentation)
384 (if (< (point) (cdr langelem))
385 ;; Align with the comment starter rather than
386 ;; with the code before it.
387 (goto-char (cdr langelem)))))
388 (- (current-column) langelem-col))))))
390 (defun c-lineup-comment (langelem)
391 "Line up a comment start according to `c-comment-only-line-offset'.
392 If the comment is lined up with a comment starter on the previous
393 line, that alignment is preserved.
395 Works with: comment-intro."
397 (back-to-indentation)
398 (let ((col (current-column)))
400 ;; CASE 1: preserve aligned comments
402 (and (c-forward-comment -1)
403 (= col (current-column))))
404 (vector col)) ; Return an absolute column.
405 ;; indent as specified by c-comment-only-line-offset
407 (or (car-safe c-comment-only-line-offset)
408 c-comment-only-line-offset))
410 (or (cdr-safe c-comment-only-line-offset)
411 (car-safe c-comment-only-line-offset)
412 -1000)) ;jam it against the left side
415 (defun c-lineup-runin-statements (langelem)
416 "Line up statements when the first statement is on the same line as
417 the block opening brace. E.g:
420 { puts (\"Hello world!\");
421 return 0; <- c-lineup-runin-statements
424 If there is no statement after the opening brace to align with, nil is
425 returned. This makes the function usable in list expressions.
427 Works with: The `statement' syntactic symbol."
428 (if (eq (char-after (cdr langelem)) ?{)
430 (let ((langelem-col (c-langelem-col langelem)))
432 (skip-chars-forward " \t")
434 (- (current-column) langelem-col))))))
436 (defun c-lineup-math (langelem)
437 "Line up the current line after the equal sign on the first line in
438 the statement. If there isn't any, indent with `c-basic-offset'. If
439 the current line contains an equal sign too, try to align it with the
442 Works with: statement-cont."
444 (let ((equalp (save-excursion
445 (goto-char (c-point 'boi))
446 (let ((eol (c-point 'eol)))
447 (c-forward-token-1 0 t eol)
448 (while (and (not (eq (char-after) ?=))
449 (= (c-forward-token-1 1 t eol) 0))))
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 (vector (current-column))))
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))
721 (cc-provide 'cc-align)
722 ;;; cc-align.el ends here