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.
38 (if (and (boundp 'byte-compile-dest-file
)
39 (stringp byte-compile-dest-file
))
40 (cons (file-name-directory byte-compile-dest-file
) load-path
)
42 (require 'cc-bytecomp
)))
46 (cc-require 'cc-langs
)
47 (cc-require 'cc-engine
)
50 ;; Standard indentation line-ups
52 (defun c-lineup-arglist (langelem)
53 "Line up the current argument line under the first argument.
55 Works with: arglist-cont-nonempty."
57 (let* ((containing-sexp
59 ;; arglist-cont-nonempty gives relpos ==
60 ;; to boi of containing-sexp paren. This
61 ;; is good when offset is +, but bad
62 ;; when it is c-lineup-arglist, so we
63 ;; have to special case a kludge here.
64 (if (memq (car langelem
) '(arglist-intro arglist-cont-nonempty
))
68 (skip-chars-forward " \t" (c-point 'eol
)))
69 (goto-char (cdr langelem
)))
71 (langelem-col (c-langelem-col langelem t
)))
74 (looking-at "[ \t]*)"))
75 (progn (goto-char (match-end 0))
78 (c-forward-syntactic-ws)
79 (- (current-column) langelem-col
))
80 (goto-char containing-sexp
)
82 (not (memq (char-after) '(?
{ ?\
( ?\
[)))
83 (let ((eol (c-point 'eol
))
86 (skip-chars-forward " \t")
88 (c-forward-syntactic-ws)
91 (- (current-column) langelem-col
)
94 (defun c-lineup-arglist-intro-after-paren (langelem)
95 "Line up a line just after the open paren of the surrounding paren or
98 Works with: defun-block-intro, brace-list-intro,
99 statement-block-intro, statement-case-intro, arglist-intro."
101 (let ((langelem-col (c-langelem-col langelem t
))
102 (ce-curcol (save-excursion
105 (skip-chars-forward " \t" (c-point 'eol
))
107 (- ce-curcol langelem-col -
1))))
109 (defun c-lineup-arglist-close-under-paren (langelem)
110 "Line up a closing paren line under the corresponding open paren.
112 Works with: defun-close, class-close, inline-close, block-close,
113 brace-list-close, arglist-close, extern-lang-close, namespace-close
114 \(for most of these, a zero offset will normally produce the same
117 (let ((langelem-col (c-langelem-col langelem t
))
118 (ce-curcol (save-excursion
122 (- ce-curcol langelem-col
))))
124 (defun c-lineup-close-paren (langelem)
125 "Line up the closing paren under its corresponding open paren if the
126 open paren is followed by code. If the open paren ends its line, no
127 indentation is added. E.g:
131 ) <-> ) <- c-lineup-close-paren
133 Works with: defun-close, class-close, inline-close, block-close,
134 brace-list-close, arglist-close, extern-lang-close, namespace-close."
140 (setq spec
(c-looking-at-special-brace-list))
141 (if spec
(goto-char (car (car spec
))))
142 (setq opencol
(current-column))
145 (c-forward-syntactic-ws)
147 (c-forward-syntactic-ws (c-point 'eol
))
150 (- opencol
(c-langelem-col langelem t
))))
153 (defun c-lineup-streamop (langelem)
154 "Line up C++ stream operators under each other.
156 Works with: stream-op."
158 (let ((langelem-col (c-langelem-col langelem
)))
159 (re-search-forward "<<\\|>>" (c-point 'eol
) 'move
)
160 (goto-char (match-beginning 0))
161 (- (current-column) langelem-col
))))
163 (defun c-lineup-multi-inher (langelem)
164 "Line up the classes in C++ multiple inheritance clauses and member
165 initializers under each other. E.g:
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 class Foo Foo::Foo (int a, int b)
176 : public Cyphr : Cyphr (a)
177 , public Bar <-> , Bar (b) <- c-lineup-multi-inher
179 Works with: inher-cont, member-init-cont."
181 (let* ((eol (c-point 'eol
))
183 (char-after-ip (progn
184 (skip-chars-forward " \t")
186 (langelem-col (c-langelem-col langelem
)))
188 ;; This kludge is necessary to support both inher-cont and
189 ;; member-init-cont, since they have different anchor positions.
190 (c-backward-syntactic-ws)
191 (when (eq (char-before) ?
:)
193 (c-backward-syntactic-ws))
195 (skip-chars-forward "^:" eol
)
196 (if (eq char-after-ip ?
,)
197 (skip-chars-forward " \t" eol
)
198 (skip-chars-forward " \t:" eol
))
200 (looking-at c-comment-start-regexp
))
201 (c-forward-syntactic-ws here
))
202 (- (current-column) langelem-col
)
205 (defun c-lineup-java-inher (langelem)
206 "Line up Java implements and extends declarations.
207 If class names follows on the same line as the implements/extends
208 keyword, they are lined up under each other. Otherwise, they are
209 indented by adding `c-basic-offset' to the column of the keyword.
213 extends extends Cyphr,
214 Bar <-> Bar <- c-lineup-java-inher
217 Works with: inher-cont."
219 (let ((langelem-col (c-langelem-col langelem
)))
221 (if (looking-at "[ \t]*$")
223 (c-forward-syntactic-ws)
224 (- (current-column) langelem-col
)))))
226 (defun c-lineup-java-throws (langelem)
227 "Line up Java throws declarations.
228 If exception names follows on the same line as the throws keyword,
229 they are lined up under each other. Otherwise, they are indented by
230 adding `c-basic-offset' to the column of the throws keyword. The
231 throws keyword itself is also indented by `c-basic-offset' from the
232 function declaration start if it doesn't hang. E.g:
234 int foo() int foo() throws Cyphr,
235 throws <-> Bar, <- c-lineup-java-throws
236 Bar <-> Vlod <- c-lineup-java-throws
237 <--><--> c-basic-offset
239 Works with: func-decl-cont."
241 (let* ((lim (1- (c-point 'bol
)))
243 (goto-char (cdr langelem
))
244 (while (zerop (c-forward-token-1 1 t lim
))
245 (if (looking-at "throws\\>[^_]")
248 (if (zerop (c-forward-token-1 1 nil
(c-point 'eol
)))
249 (- (current-column) (c-langelem-col langelem
))
250 (back-to-indentation)
251 (+ (- (current-column) (c-langelem-col langelem
))
255 (defun c-indent-one-line-block (langelem)
256 "Indent a one line block `c-basic-offset' extra.
259 if (n > 0) if (n > 0)
260 {m+=n; n=0;} <-> { <- c-indent-one-line-block
261 <--> c-basic-offset m+=n; n=0;
264 The block may use any kind of parenthesis character. nil is returned
265 if the line doesn't start with a one line block, which makes the
266 function usable in list expressions.
268 Work with: Almost all syntactic symbols, but most useful on *-open."
270 (let ((eol (c-point 'eol
)))
271 (back-to-indentation)
272 (if (and (eq (char-syntax (char-after)) ?\
()
273 (c-safe (progn (c-forward-sexp) t
))
278 (defun c-indent-multi-line-block (langelem)
279 "Indent a multi line block `c-basic-offset' extra.
282 int *foo[] = { int *foo[] = {
284 {17}, <-> { <- c-indent-multi-line-block
289 The block may use any kind of parenthesis character. nil is returned
290 if the line doesn't start with a multi line block, which makes the
291 function usable in list expressions.
293 Work with: Almost all syntactic symbols, but most useful on *-open."
295 (let ((eol (c-point 'eol
)))
296 (back-to-indentation)
297 (if (and (eq (char-syntax (char-after)) ?\
()
298 (or (not (c-safe (progn (c-forward-sexp) t
)))
303 (defun c-lineup-C-comments (langelem)
304 "Line up C block comment continuation lines.
305 Various heuristics are used to handle many of the common comment
306 styles. Some examples:
308 /* /** /* /* text /* /**
309 * text * text text text ** text ** text
312 /*********************************************************************
314 ********************************************************************/
316 /*********************************************************************
317 Free form text comments:
318 In comments with a long delimiter line at the start, the indentation
319 is kept unchanged for lines that start with an empty comment line
320 prefix. The delimiter line is whatever matches the
321 `comment-start-skip' regexp.
322 *********************************************************************/
324 The variable `c-comment-prefix-regexp' is used to recognize the
325 comment line prefix, e.g. the `*' that usually starts every line
328 Works with: The `c' syntactic symbol."
330 (let* ((here (point))
331 (prefixlen (progn (back-to-indentation)
332 (if (looking-at c-current-comment-prefix
)
333 (- (match-end 0) (point))
335 (starterlen (save-excursion
336 (goto-char (cdr langelem
))
337 (looking-at comment-start-skip
)
339 (goto-char (match-end 0))
340 (skip-chars-backward " \t")
342 (or (match-end 1) (point))
343 1))) ; Don't count the first '/'.
344 (langelem-col (save-excursion (c-langelem-col langelem
))))
345 (if (and (> starterlen
10) (zerop prefixlen
))
346 ;; The comment has a long starter and the line doesn't have
347 ;; a nonempty comment prefix. Treat it as free form text
348 ;; and don't change the indentation.
349 (- (current-column) langelem-col
)
351 (back-to-indentation)
352 (if (>= (cdr langelem
) (point))
353 ;; On the second line in the comment.
354 (if (zerop prefixlen
)
355 ;; No nonempty comment prefix. Align after comment
358 (goto-char (match-end 0))
359 (if (looking-at "\\([ \t]+\\).+$")
360 ;; Align with the text that hangs after the
362 (goto-char (match-end 1)))
363 (- (current-column) langelem-col
))
364 ;; How long is the comment starter? if greater than the
365 ;; length of the comment prefix, align left. if less
366 ;; than or equal, align right. this should also pick up
367 ;; Javadoc style comments.
368 (if (> starterlen prefixlen
)
370 (goto-char (cdr langelem
))
371 (- (current-column) -
1 langelem-col
))
372 (goto-char (match-end 0))
373 (skip-chars-backward " \t")
374 (- (current-column) prefixlen langelem-col
)))
375 ;; Not on the second line in the comment. If the previous
376 ;; line has a nonempty comment prefix, align with it.
377 ;; Otherwise, align with the previous nonempty line, but
378 ;; align the comment ender with the starter.
379 (when (or (not (looking-at c-current-comment-prefix
))
380 (eq (match-beginning 0) (match-end 0)))
382 (back-to-indentation)
383 (if (looking-at (concat "\\(" c-current-comment-prefix
"\\)\\*/"))
384 (goto-char (cdr langelem
))
385 (while (and (zerop (forward-line -
1))
386 (looking-at "^[ \t]*$")))
387 (back-to-indentation)
388 (if (< (point) (cdr langelem
))
389 ;; Align with the comment starter rather than
390 ;; with the code before it.
391 (goto-char (cdr langelem
)))))
392 (- (current-column) langelem-col
))))))
394 (defun c-lineup-comment (langelem)
395 "Line up a comment start according to `c-comment-only-line-offset'.
396 If the comment is lined up with a comment starter on the previous
397 line, that alignment is preserved.
399 Works with: comment-intro."
401 (back-to-indentation)
402 (let ((col (current-column)))
404 ;; CASE 1: preserve aligned comments
406 (and (c-forward-comment -
1)
407 (= col
(current-column))))
408 (vector col
)) ; Return an absolute column.
409 ;; indent as specified by c-comment-only-line-offset
411 (or (car-safe c-comment-only-line-offset
)
412 c-comment-only-line-offset
))
414 (or (cdr-safe c-comment-only-line-offset
)
415 (car-safe c-comment-only-line-offset
)
416 -
1000)) ;jam it against the left side
419 (defun c-lineup-runin-statements (langelem)
420 "Line up statements when the first statement is on the same line as
421 the block opening brace. E.g:
424 { puts (\"Hello world!\");
425 return 0; <- c-lineup-runin-statements
428 If there is no statement after the opening brace to align with, nil is
429 returned. This makes the function usable in list expressions.
431 Works with: The `statement' syntactic symbol."
432 (if (eq (char-after (cdr langelem
)) ?
{)
434 (let ((langelem-col (c-langelem-col langelem
)))
436 (skip-chars-forward " \t")
438 (- (current-column) langelem-col
))))))
440 (defun c-lineup-math (langelem)
441 "Line up the current line after the equal sign on the first line in
442 the statement. If there isn't any, indent with `c-basic-offset'. If
443 the current line contains an equal sign too, try to align it with the
446 Works with: statement-cont."
448 (let ((equalp (save-excursion
449 (goto-char (c-point 'boi
))
450 (let ((eol (c-point 'eol
)))
451 (c-forward-token-1 0 t eol
)
452 (while (and (not (eq (char-after) ?
=))
453 (= (c-forward-token-1 1 t eol
) 0))))
454 (and (eq (char-after) ?
=)
455 (- (point) (c-point 'boi
)))))
456 (langelem-col (c-langelem-col langelem
))
458 (while (and (not donep
)
459 (< (point) (c-point 'eol
)))
460 (skip-chars-forward "^=" (c-point 'eol
))
461 (if (c-in-literal (cdr langelem
))
464 (if (or (not (eq (char-after) ?
=))
467 (c-forward-syntactic-ws (c-point 'eol
))
469 ;; there's no equal sign on the line
471 ;; calculate indentation column after equals and ws, unless
472 ;; our line contains an equals sign
476 (skip-chars-forward " \t")
478 (- (current-column) equalp langelem-col
))
481 (defun c-lineup-template-args (langelem)
482 "Line up template argument lines under the first argument.
483 To allow this function to be used in a list expression, nil is
484 returned if there's no template argument on the first line.
486 Works with: template-args-cont."
488 (c-with-syntax-table c
++-template-syntax-table
491 (if (and (eq (char-after) ?
<)
492 (zerop (c-forward-token-1 1 nil
(c-point 'eol
))))
493 (- (current-column) (c-langelem-col langelem
))))))
495 (defun c-lineup-ObjC-method-call (langelem)
496 "Line up selector args as elisp-mode does with function args:
497 Go to the position right after the message receiver, and if you are at
498 the end of the line, indent the current line c-basic-offset columns
499 from the opening bracket; otherwise you are looking at the first
500 character of the first method call argument, so lineup the current
503 Works with: objc-method-call-cont."
505 (let* ((extra (save-excursion
506 (back-to-indentation)
507 (c-backward-syntactic-ws (cdr langelem
))
508 (if (eq (char-before) ?
:)
511 (open-bracket-pos (cdr langelem
))
512 (open-bracket-col (progn
513 (goto-char open-bracket-pos
)
518 (skip-chars-forward " \t")
520 (+ open-bracket-col c-basic-offset
)
523 (- target-col open-bracket-col extra
))))
525 (defun c-lineup-ObjC-method-args (langelem)
526 "Line up the colons that separate args.
527 The colon on the current line is aligned with the one on the first
530 Works with: objc-method-args-cont."
532 (let* ((here (c-point 'boi
))
533 (curcol (progn (goto-char here
) (current-column)))
535 (relpos (cdr langelem
))
536 (first-col-column (progn
538 (skip-chars-forward "^:" eol
)
539 (and (eq (char-after) ?
:)
541 (if (not first-col-column
)
544 (skip-chars-forward "^:" eol
)
545 (if (eq (char-after) ?
:)
546 (+ curcol
(- first-col-column
(current-column)))
549 (defun c-lineup-ObjC-method-args-2 (langelem)
550 "Line up the colons that separate args.
551 The colon on the current line is aligned with the one on the previous
554 Works with: objc-method-args-cont."
556 (let* ((here (c-point 'boi
))
557 (curcol (progn (goto-char here
) (current-column)))
559 (relpos (cdr langelem
))
560 (prev-col-column (progn
561 (skip-chars-backward "^:" relpos
)
562 (and (eq (char-before) ?
:)
563 (- (current-column) 1)))))
564 (if (not prev-col-column
)
567 (skip-chars-forward "^:" eol
)
568 (if (eq (char-after) ?
:)
569 (+ curcol
(- prev-col-column
(current-column)))
572 (defun c-lineup-inexpr-block (langelem)
573 "Line up the block for constructs that use a block inside an expression,
574 e.g. anonymous classes in Java and lambda functions in Pike. The body
575 is aligned with the start of the header, e.g. with the \"new\" or
576 \"lambda\" keyword. Returns nil if the block isn't part of such a
579 Works with: inlambda, inexpr-statement, inexpr-class."
581 (back-to-indentation)
582 (let ((res (or (c-looking-at-inexpr-block)
583 (if (c-safe (backward-up-list 1)
584 (eq (char-after) ?
{))
585 (c-looking-at-inexpr-block)))))
587 (goto-char (cdr res
))
590 (back-to-indentation)
591 (current-column)))))))
593 (defun c-lineup-whitesmith-in-block (langelem)
594 "Line up lines inside a block in whitesmith style.
595 It's done in a way that works both when the opening brace hangs and
596 when it doesn't. E.g:
600 foo; <-> foo; <- c-lineup-whitesmith-in-block
604 In the first case the indentation is kept unchanged, in the
605 second `c-basic-offset' is added.
607 Works with: defun-close, defun-block-intro, block-close,
608 brace-list-close, brace-list-intro, statement-block-intro, inclass,
609 inextern-lang, innamespace."
611 (goto-char (cdr langelem
))
612 (back-to-indentation)
613 (if (eq (char-syntax (char-after)) ?\
()
617 (defun c-lineup-dont-change (langelem)
618 "Do not change the indentation of the current line.
620 Works with: Any syntactic symbol."
622 (back-to-indentation)
623 (vector (current-column))))
626 (defun c-snug-do-while (syntax pos
)
627 "Dynamically calculate brace hanginess for do-while statements.
628 Using this function, `while' clauses that end a `do-while' block will
629 remain on the same line as the brace that closes that block.
631 See `c-hanging-braces-alist' for how to utilize this function as an
632 ACTION associated with `block-close' syntax."
635 (if (and (eq syntax
'block-close
)
636 (setq langelem
(assq 'block-close c-syntactic-context
))
637 (progn (goto-char (cdr langelem
))
638 (if (eq (char-after) ?
{)
639 (c-safe (c-forward-sexp -
1)))
640 (looking-at "\\<do\\>[^_]")))
644 (defun c-gnu-impose-minimum ()
645 "Imposes a minimum indentation for lines inside a top-level construct.
646 The variable `c-label-minimum-indentation' specifies the minimum
648 (let ((non-top-levels '(defun-block-intro statement statement-cont
649 statement-block-intro statement-case-intro
650 statement-case-open substatement substatement-open
651 case-label label do-while-closure else-clause
653 (syntax c-syntactic-context
)
656 (setq langelem
(car (car syntax
))
658 ;; don't adjust macro or comment-only lines
659 (cond ((memq langelem
'(cpp-macro comment-intro
))
661 ((memq langelem non-top-levels
)
664 (back-to-indentation)
665 (if (zerop (current-column))
666 (insert (make-string c-label-minimum-indentation
32)))
671 ;; Useful for c-hanging-semi&comma-criteria
673 (defun c-semi&comma-inside-parenlist
()
674 "Controls newline insertion after semicolons in parenthesis lists.
675 If a comma was inserted, no determination is made. If a semicolon was
676 inserted inside a parenthesis list, no newline is added otherwise a
677 newline is added. In either case, checking is stopped. This supports
678 exactly the old newline insertion behavior."
679 ;; newline only after semicolon, but only if that semicolon is not
680 ;; inside a parenthesis list (e.g. a for loop statement)
681 (if (not (eq last-command-char ?\
;))
682 nil
; continue checking
683 (if (condition-case nil
686 (not (eq (char-after) ?\
()))
691 ;; Suppresses newlines before non-blank lines
692 (defun c-semi&comma-no-newlines-before-nonblanks
()
693 "Controls newline insertion after semicolons.
694 If a comma was inserted, no determination is made. If a semicolon was
695 inserted, and the following line is not blank, no newline is inserted.
696 Otherwise, no determination is made."
698 (if (and (= last-command-char ?\
;)
700 ;; (save-excursion (skip-syntax-forward " ") (point))
701 (zerop (forward-line 1))
702 (not (looking-at "^[ \t]*$")))
706 ;; Suppresses new lines after semicolons in one-liners methods
707 (defun c-semi&comma-no-newlines-for-oneline-inliners
()
708 "Controls newline insertion after semicolons for some one-line methods.
709 If a comma was inserted, no determination is made. Newlines are
710 suppressed in one-liners, if the line is an in-class inline function.
711 For other semicolon contexts, no determination is made."
712 (let ((syntax (c-guess-basic-syntax))
714 (if (c-safe (up-list -
1) t
)
717 (if (and (eq last-command-char ?\
;)
718 (eq (car (car syntax
)) 'inclass
)
719 (eq (car (car (cdr syntax
))) 'topmost-intro
)
720 (= (c-point 'bol
) bol
))
725 (cc-provide 'cc-align
)
727 ;;; cc-align.el ends here