1 ;;; cc-align.el --- custom indentation functions for CC Mode
3 ;; Copyright (C) 1985,1987,1992-1999 Free Software Foundation, Inc.
5 ;; Authors: 1998-1999 Barry A. Warsaw and Martin Stjernholm
6 ;; 1992-1997 Barry A. Warsaw
7 ;; 1987 Dave Detlefs and Stewart Clamen
8 ;; 1985 Richard M. Stallman
9 ;; Maintainer: bug-cc-mode@gnu.org
10 ;; Created: 22-Apr-1997 (split from cc-mode.el)
11 ;; Version: See cc-mode.el
12 ;; Keywords: c languages oop
14 ;; This file is part of GNU Emacs.
16 ;; GNU Emacs is free software; you can redistribute it and/or modify
17 ;; it under the terms of the GNU General Public License as published by
18 ;; the Free Software Foundation; either version 2, or (at your option)
21 ;; GNU Emacs is distributed in the hope that it will be useful,
22 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
23 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 ;; GNU General Public License for more details.
26 ;; You should have received a copy of the GNU General Public License
27 ;; along with GNU Emacs; see the file COPYING. If not, write to the
28 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
29 ;; Boston, MA 02111-1307, USA.
33 (if (and (boundp 'byte-compile-current-file)
34 (stringp byte-compile-current-file))
35 (cons (file-name-directory byte-compile-current-file)
38 (load "cc-defs" nil t)))
42 ;; Standard indentation line-ups
44 (defun c-lineup-arglist (langelem)
45 "Line up the current argument line under the first argument.
47 Works with: arglist-cont-nonempty."
49 (let* ((containing-sexp
51 ;; arglist-cont-nonempty gives relpos ==
52 ;; to boi of containing-sexp paren. This
53 ;; is good when offset is +, but bad
54 ;; when it is c-lineup-arglist, so we
55 ;; have to special case a kludge here.
56 (if (memq (car langelem) '(arglist-intro arglist-cont-nonempty))
60 (skip-chars-forward " \t" (c-point 'eol)))
61 (goto-char (cdr langelem)))
63 (langelem-col (c-langelem-col langelem t)))
66 (looking-at "[ \t]*)"))
67 (progn (goto-char (match-end 0))
70 (c-forward-syntactic-ws)
71 (- (current-column) langelem-col))
72 (goto-char containing-sexp)
74 (not (memq (char-after) '(?{ ?\( ?\[)))
75 (let ((eol (c-point 'eol))
78 (skip-chars-forward " \t")
80 (c-forward-syntactic-ws)
83 (- (current-column) langelem-col)
86 (defun c-lineup-arglist-intro-after-paren (langelem)
87 "Line up a line just after the open paren of the surrounding paren or
90 Works with: defun-block-intro, brace-list-intro,
91 statement-block-intro, statement-case-intro, arglist-intro."
93 (let ((langelem-col (c-langelem-col langelem t))
94 (ce-curcol (save-excursion
97 (skip-chars-forward " \t" (c-point 'eol))
99 (- ce-curcol langelem-col -1))))
101 (defun c-lineup-arglist-close-under-paren (langelem)
102 "Line up a closing paren line under the corresponding open paren.
104 Works with: defun-close, class-close, inline-close, block-close,
105 brace-list-close, arglist-close, extern-lang-close, namespace-close
106 \(for most of these, a zero offset will normally produce the same
109 (let ((langelem-col (c-langelem-col langelem t))
110 (ce-curcol (save-excursion
114 (- ce-curcol langelem-col))))
116 (defun c-lineup-close-paren (langelem)
117 "Line up the closing paren under its corresponding open paren if the
118 open paren is followed by code. If the open paren ends its line, no
119 indentation is added. E.g:
123 ) <-> ) <- c-lineup-close-paren
125 Works with: defun-close, class-close, inline-close, block-close,
126 brace-list-close, arglist-close, extern-lang-close, namespace-close."
132 (setq spec (c-looking-at-special-brace-list))
133 (if spec (goto-char (car (car spec))))
134 (setq opencol (current-column))
137 (c-forward-syntactic-ws)
139 (c-forward-syntactic-ws (c-point 'eol))
142 (- opencol (c-langelem-col langelem t))))
145 (defun c-lineup-streamop (langelem)
146 "Line up C++ stream operators under each other.
148 Works with: stream-op."
150 (let ((langelem-col (c-langelem-col langelem)))
151 (re-search-forward "<<\\|>>" (c-point 'eol) 'move)
152 (goto-char (match-beginning 0))
153 (- (current-column) langelem-col))))
155 (defun c-lineup-multi-inher (langelem)
156 "Line up the classes in C++ multiple inheritance clauses under each other.
158 Works with: inher-cont."
160 (let ((eol (c-point 'eol))
162 (langelem-col (c-langelem-col langelem)))
163 (skip-chars-forward "^:" eol)
164 (skip-chars-forward " \t:" eol)
166 (looking-at c-comment-start-regexp))
167 (c-forward-syntactic-ws here))
168 (- (current-column) langelem-col)
171 (defun c-lineup-java-inher (langelem)
172 "Line up Java implements and extends declarations.
173 If class names follows on the same line as the implements/extends
174 keyword, they are lined up under each other. Otherwise, they are
175 indented by adding `c-basic-offset' to the column of the keyword.
179 extends extends Cyphr,
180 Bar <-> Bar <- c-lineup-java-inher
183 Works with: inher-cont."
185 (let ((langelem-col (c-langelem-col langelem)))
187 (if (looking-at "[ \t]*$")
189 (c-forward-syntactic-ws)
190 (- (current-column) langelem-col)))))
192 (defun c-lineup-java-throws (langelem)
193 "Line up Java throws declarations.
194 If exception names follows on the same line as the throws keyword,
195 they are lined up under each other. Otherwise, they are indented by
196 adding `c-basic-offset' to the column of the throws keyword. The
197 throws keyword itself is also indented by `c-basic-offset' from the
198 function declaration start if it doesn't hang. E.g:
200 int foo() int foo() throws Cyphr,
201 throws <-> Bar, <- c-lineup-java-throws
202 Bar <-> Vlod <- c-lineup-java-throws
203 <--><--> c-basic-offset
205 Works with: func-decl-cont."
207 (let* ((lim (1- (c-point 'bol)))
209 (goto-char (cdr langelem))
210 (while (zerop (c-forward-token-1 1 t lim))
211 (if (looking-at "throws\\>[^_]")
214 (if (zerop (c-forward-token-1 1 nil (c-point 'eol)))
215 (- (current-column) (c-langelem-col langelem))
216 (back-to-indentation)
217 (+ (- (current-column) (c-langelem-col langelem))
221 (defun c-indent-one-line-block (langelem)
222 "Indent a one line block `c-basic-offset' extra.
225 if (n > 0) if (n > 0)
226 {m+=n; n=0;} <-> { <- c-indent-one-line-block
227 <--> c-basic-offset m+=n; n=0;
230 The block may be surrounded by any kind of parenthesis characters.
231 nil is returned if the line doesn't start with a one line block, which
232 makes the function usable in list expressions.
234 Work with: Almost all syntactic symbols, but most useful on *-open."
236 (let ((eol (c-point 'eol)))
237 (back-to-indentation)
238 (if (and (eq (char-syntax (char-after)) ?\()
239 (c-safe (progn (c-forward-sexp) t))
244 (defun c-indent-multi-line-block (langelem)
245 "Indent a multi line block `c-basic-offset' extra.
248 int *foo[] = { int *foo[] = {
250 {17}, <-> { <- c-indent-multi-line-block
255 The block may be surrounded by any kind of parenthesis characters.
256 nil is returned if the line doesn't start with a multi line block,
257 which makes the function usable in list expressions.
259 Work with: Almost all syntactic symbols, but most useful on *-open."
261 (let ((eol (c-point 'eol)))
262 (back-to-indentation)
263 (if (and (eq (char-syntax (char-after)) ?\()
264 (or (not (c-safe (progn (c-forward-sexp) t)))
269 (defun c-lineup-C-comments (langelem)
270 "Line up C block comment continuation lines.
271 Various heuristics are used to handle most of the common comment
272 styles. Some examples:
274 /* /** /* /* text /* /**
275 * text * text text text ** text ** text
278 /*********************************************************************
280 ********************************************************************/
282 /*********************************************************************
283 Free form text comments:
284 In comments with a long delimiter line at the start, the indentation
285 is kept unchanged for lines that start with an empty comment line
286 prefix. The delimiter line is whatever matches the
287 `comment-start-skip' regexp.
288 *********************************************************************/
290 The variable `c-comment-prefix-regexp' is used to recognize the
291 comment line prefix, e.g. the `*' that usually starts every line
294 Works with: The `c' syntactic symbol."
296 (let* ((here (point))
297 (prefixlen (progn (back-to-indentation)
298 (if (looking-at c-comment-prefix-regexp)
299 (- (match-end 0) (point))
301 (starterlen (save-excursion
302 (goto-char (cdr langelem))
303 (looking-at comment-start-skip)
305 (goto-char (match-end 0))
306 (skip-chars-backward " \t")
308 (or (match-end 1) (point))
309 1))) ; Don't count the first '/'.
310 (langelem-col (save-excursion (c-langelem-col langelem))))
311 (if (and (> starterlen 10) (zerop prefixlen))
312 ;; The comment has a long starter and the line doesn't have
313 ;; a nonempty comment prefix. Treat it as free form text
314 ;; and don't change the indentation.
315 (- (current-column) langelem-col)
317 (back-to-indentation)
318 (if (>= (cdr langelem) (point))
319 ;; On the second line in the comment.
320 (if (zerop prefixlen)
321 ;; No nonempty comment prefix. Align after comment
324 (goto-char (match-end 0))
325 (if (looking-at "\\([ \t]+\\).+$")
326 ;; Align with the text that hangs after the
328 (goto-char (match-end 1)))
329 (- (current-column) langelem-col))
330 ;; How long is the comment starter? if greater than the
331 ;; length of the comment prefix, align left. if less
332 ;; than or equal, align right. this should also pick up
333 ;; Javadoc style comments.
334 (if (> starterlen prefixlen)
336 (goto-char (cdr langelem))
337 (- (current-column) -1 langelem-col))
338 (goto-char (match-end 0))
339 (skip-chars-backward " \t")
340 (- (current-column) prefixlen langelem-col)))
341 ;; Not on the second line in the comment. If the previous
342 ;; line has a nonempty comment prefix, align with it.
343 ;; Otherwise, align with the previous nonempty line, but
344 ;; align the comment ender with the starter.
345 (when (or (not (looking-at c-comment-prefix-regexp))
346 (eq (match-beginning 0) (match-end 0)))
348 (back-to-indentation)
349 (if (looking-at (concat "\\(" c-comment-prefix-regexp "\\)\\*/"))
350 (goto-char (cdr langelem))
351 (while (and (zerop (forward-line -1))
352 (looking-at "^[ \t]*$")))
353 (back-to-indentation)
354 (if (< (point) (cdr langelem))
355 ;; Align with the comment starter rather than
356 ;; with the code before it.
357 (goto-char (cdr langelem)))))
358 (- (current-column) langelem-col))))))
360 (defun c-lineup-comment (langelem)
361 "Line up a comment start according to `c-comment-only-line-offset'.
362 If the comment is lined up with a comment starter on the previous
363 line, that alignment is preserved.
365 Works with: comment-intro."
367 (back-to-indentation)
368 ;; this highly kludgiforous flag prevents the mapcar over
369 ;; c-syntactic-context from entering an infinite loop
370 (let ((recurse-prevention-flag (boundp 'recurse-prevention-flag))
371 (col (current-column)))
373 (recurse-prevention-flag 0)
374 ;; CASE 1: preserve aligned comments
376 (and (c-forward-comment -1)
377 (= col (current-column))))
378 ;; we have to subtract out all other indentation
379 (- col (apply '+ (mapcar 'c-get-offset
380 c-syntactic-context))))
381 ;; indent as specified by c-comment-only-line-offset
383 (or (car-safe c-comment-only-line-offset)
384 c-comment-only-line-offset))
386 (or (cdr-safe c-comment-only-line-offset)
387 (car-safe c-comment-only-line-offset)
388 -1000)) ;jam it against the left side
391 (defun c-lineup-runin-statements (langelem)
392 "Line up statements when the first statement is on the same line as
393 the block opening brace. E.g:
396 { puts (\"Hello world!\");
397 return 0; <- c-lineup-runin-statements
400 If there is no statement after the opening brace to align with, nil is
401 returned. This makes the function usable in list expressions.
403 Works with: The `statement' syntactic symbol."
404 (if (eq (char-after (cdr langelem)) ?{)
406 (let ((langelem-col (c-langelem-col langelem)))
408 (skip-chars-forward " \t")
410 (- (current-column) langelem-col))))))
412 (defun c-lineup-math (langelem)
413 "Line up the current line after the equal sign on the first line in
414 the statement. If there isn't any, indent with `c-basic-offset'. If
415 the current line contains an equal sign too, try to align it with the
418 Works with: statement-cont."
420 (let ((equalp (save-excursion
421 (goto-char (c-point 'boi))
422 (skip-chars-forward "^=" (c-point 'eol))
423 (and (eq (char-after) ?=)
424 (- (point) (c-point 'boi)))))
425 (langelem-col (c-langelem-col langelem))
427 (while (and (not donep)
428 (< (point) (c-point 'eol)))
429 (skip-chars-forward "^=" (c-point 'eol))
430 (if (c-in-literal (cdr langelem))
433 (if (or (not (eq (char-after) ?=))
436 (c-forward-syntactic-ws (c-point 'eol))
438 ;; there's no equal sign on the line
440 ;; calculate indentation column after equals and ws, unless
441 ;; our line contains an equals sign
445 (skip-chars-forward " \t")
447 (- (current-column) equalp langelem-col))
450 (defun c-lineup-template-args (langelem)
451 "Line up template argument lines under the first argument.
452 To allow this function to be used in a list expression, nil is
453 returned if there's no template argument on the first line.
455 Works with: template-args-cont."
457 (c-with-syntax-table c++-template-syntax-table
460 (if (and (eq (char-after) ?<)
461 (zerop (c-forward-token-1 1 nil (c-point 'eol))))
462 (- (current-column) (c-langelem-col langelem))))))
464 (defun c-lineup-ObjC-method-call (langelem)
465 "Line up selector args as elisp-mode does with function args:
466 Go to the position right after the message receiver, and if you are at
467 the end of the line, indent the current line c-basic-offset columns
468 from the opening bracket; otherwise you are looking at the first
469 character of the first method call argument, so lineup the current
472 Works with: objc-method-call-cont."
474 (let* ((extra (save-excursion
475 (back-to-indentation)
476 (c-backward-syntactic-ws (cdr langelem))
477 (if (eq (char-before) ?:)
480 (open-bracket-pos (cdr langelem))
481 (open-bracket-col (progn
482 (goto-char open-bracket-pos)
487 (skip-chars-forward " \t")
489 (+ open-bracket-col c-basic-offset)
492 (- target-col open-bracket-col extra))))
494 (defun c-lineup-ObjC-method-args (langelem)
495 "Line up the colons that separate args.
496 The colon on the current line is aligned with the one on the first
499 Works with: objc-method-args-cont."
501 (let* ((here (c-point 'boi))
502 (curcol (progn (goto-char here) (current-column)))
504 (relpos (cdr langelem))
505 (first-col-column (progn
507 (skip-chars-forward "^:" eol)
508 (and (eq (char-after) ?:)
510 (if (not first-col-column)
513 (skip-chars-forward "^:" eol)
514 (if (eq (char-after) ?:)
515 (+ curcol (- first-col-column (current-column)))
518 (defun c-lineup-ObjC-method-args-2 (langelem)
519 "Line up the colons that separate args.
520 The colon on the current line is aligned with the one on the previous
523 Works with: objc-method-args-cont."
525 (let* ((here (c-point 'boi))
526 (curcol (progn (goto-char here) (current-column)))
528 (relpos (cdr langelem))
529 (prev-col-column (progn
530 (skip-chars-backward "^:" relpos)
531 (and (eq (char-before) ?:)
532 (- (current-column) 1)))))
533 (if (not prev-col-column)
536 (skip-chars-forward "^:" eol)
537 (if (eq (char-after) ?:)
538 (+ curcol (- prev-col-column (current-column)))
541 (defun c-lineup-inexpr-block (langelem)
542 "Line up the block for constructs that use a block inside an expression,
543 e.g. anonymous classes in Java and lambda functions in Pike. The body
544 is aligned with the start of the header, e.g. with the \"new\" or
545 \"lambda\" keyword. Returns nil if the block isn't part of such a
548 Works with: inlambda, inexpr-statement, inexpr-class."
550 (back-to-indentation)
551 (let ((res (or (c-looking-at-inexpr-block)
552 (if (c-safe (backward-up-list 1)
553 (eq (char-after) ?{))
554 (c-looking-at-inexpr-block)))))
556 (goto-char (cdr res))
559 (back-to-indentation)
560 (current-column)))))))
562 (defun c-lineup-whitesmith-in-block (langelem)
563 "Line up lines inside a block in whitesmith style.
564 It's done in a way that works both when the opening brace hangs and
565 when it doesn't. E.g:
569 foo; <-> foo; <- c-lineup-whitesmith-in-block
573 In the first case the indentation is kept unchanged, in the
574 second `c-basic-offset' is added.
576 Works with: defun-close, defun-block-intro, block-close,
577 brace-list-close, brace-list-intro, statement-block-intro, inclass,
578 inextern-lang, innamespace."
580 (goto-char (cdr langelem))
581 (back-to-indentation)
582 (if (eq (char-syntax (char-after)) ?\()
586 (defun c-lineup-dont-change (langelem)
587 "Do not change the indentation of the current line.
589 Works with: Any syntactic symbol."
591 (back-to-indentation)
592 (- (current-column) (c-langelem-col langelem))))
595 (defun c-snug-do-while (syntax pos)
596 "Dynamically calculate brace hanginess for do-while statements.
597 Using this function, `while' clauses that end a `do-while' block will
598 remain on the same line as the brace that closes that block.
600 See `c-hanging-braces-alist' for how to utilize this function as an
601 ACTION associated with `block-close' syntax."
604 (if (and (eq syntax 'block-close)
605 (setq langelem (assq 'block-close c-syntactic-context))
606 (progn (goto-char (cdr langelem))
607 (if (eq (char-after) ?{)
608 (c-safe (c-forward-sexp -1)))
609 (looking-at "\\<do\\>[^_]")))
613 (defun c-gnu-impose-minimum ()
614 "Imposes a minimum indentation for lines inside a top-level construct.
615 The variable `c-label-minimum-indentation' specifies the minimum
617 (let ((non-top-levels '(defun-block-intro statement statement-cont
618 statement-block-intro statement-case-intro
619 statement-case-open substatement substatement-open
620 case-label label do-while-closure else-clause
622 (syntax c-syntactic-context)
625 (setq langelem (car (car syntax))
627 ;; don't adjust comment-only lines
628 (cond ((eq langelem 'comment-intro)
630 ((memq langelem non-top-levels)
633 (back-to-indentation)
634 (if (zerop (current-column))
635 (insert (make-string c-label-minimum-indentation 32)))
640 ;; Useful for c-hanging-semi&comma-criteria
642 (defun c-semi&comma-inside-parenlist ()
643 "Controls newline insertion after semicolons in parenthesis lists.
644 If a comma was inserted, no determination is made. If a semicolon was
645 inserted inside a parenthesis list, no newline is added otherwise a
646 newline is added. In either case, checking is stopped. This supports
647 exactly the old newline insertion behavior."
648 ;; newline only after semicolon, but only if that semicolon is not
649 ;; inside a parenthesis list (e.g. a for loop statement)
650 (if (not (eq last-command-char ?\;))
651 nil ; continue checking
652 (if (condition-case nil
655 (not (eq (char-after) ?\()))
660 ;; Suppresses newlines before non-blank lines
661 (defun c-semi&comma-no-newlines-before-nonblanks ()
662 "Controls newline insertion after semicolons.
663 If a comma was inserted, no determination is made. If a semicolon was
664 inserted, and the following line is not blank, no newline is inserted.
665 Otherwise, no determination is made."
667 (if (and (= last-command-char ?\;)
669 ;; (save-excursion (skip-syntax-forward " ") (point))
670 (zerop (forward-line 1))
671 (not (looking-at "^[ \t]*$")))
675 ;; Suppresses new lines after semicolons in one-liners methods
676 (defun c-semi&comma-no-newlines-for-oneline-inliners ()
677 "Controls newline insertion after semicolons for some one-line methods.
678 If a comma was inserted, no determination is made. Newlines are
679 suppressed in one-liners, if the line is an in-class inline function.
680 For other semicolon contexts, no determination is made."
681 (let ((syntax (c-guess-basic-syntax))
683 (if (c-safe (up-list -1) t)
686 (if (and (eq last-command-char ?\;)
687 (eq (car (car syntax)) 'inclass)
688 (eq (car (car (cdr syntax))) 'topmost-intro)
689 (= (c-point 'bol) bol))
695 ;;; cc-align.el ends here