;;; cc-align.el --- custom indentation functions for CC Mode;; Copyright (C) 1985,1987,1992-2001 Free Software Foundation, Inc.;; Authors: 2000- Martin Stjernholm;; 1998-1999 Barry A. Warsaw and Martin Stjernholm;; 1992-1997 Barry A. Warsaw;; 1987 Dave Detlefs and Stewart Clamen;; 1985 Richard M. Stallman;; Maintainer: bug-cc-mode@gnu.org;; Created: 22-Apr-1997 (split from cc-mode.el);; Version: See cc-mode.el;; Keywords: c languages oop;; This file is part of GNU Emacs.;; GNU Emacs is free software; you can redistribute it and/or modify;; it under the terms of the GNU General Public License as published by;; the Free Software Foundation; either version 2, or (at your option);; any later version.;; GNU Emacs is distributed in the hope that it will be useful,;; but WITHOUT ANY WARRANTY; without even the implied warranty of;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the;; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License;; along with this program; see the file COPYING. If not, write to;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,;; Boston, MA 02111-1307, USA.(eval-when-compile(let((load-path(if(and(boundp'byte-compile-dest-file)(stringpbyte-compile-dest-file))(cons(file-name-directorybyte-compile-dest-file)load-path)load-path)))(require'cc-bytecomp)))(cc-require'cc-defs)(cc-require'cc-vars)(cc-require'cc-langs)(cc-require'cc-engine);; Standard indentation line-ups(defunc-lineup-arglist(langelem)"Line up the current argument line under the first argument.Works with: arglist-cont-nonempty."(save-excursion(let*((containing-sexp(save-excursion;; arglist-cont-nonempty gives relpos ==;; to boi of containing-sexp paren. This;; is good when offset is +, but bad;; when it is c-lineup-arglist, so we;; have to special case a kludge here.(if(memq(carlangelem)'(arglist-introarglist-cont-nonempty))(progn(beginning-of-line)(backward-up-list1)(skip-chars-forward" \t"(c-point'eol)))(goto-char(cdrlangelem)))(point)))(langelem-col(c-langelem-collangelemt)))(if(save-excursion(beginning-of-line)(looking-at"[ \t]*)"))(progn(goto-char(match-end0))(c-forward-sexp-1)(forward-char1)(c-forward-syntactic-ws)(-(current-column)langelem-col))(goto-charcontaining-sexp)(or(eolp)(not(memq(char-after)'(?{?\(?\[)))(let((eol(c-point'eol))(here(progn(forward-char1)(skip-chars-forward" \t")(point))))(c-forward-syntactic-ws)(if(<(point)eol)(goto-charhere))))(-(current-column)langelem-col)))))(defunc-lineup-arglist-intro-after-paren(langelem)"Line up a line just after the open paren of the surrounding paren orbrace block.Works with: defun-block-intro, brace-list-intro,statement-block-intro, statement-case-intro, arglist-intro."(save-excursion(let((langelem-col(c-langelem-collangelemt))(ce-curcol(save-excursion(beginning-of-line)(backward-up-list1)(skip-chars-forward" \t"(c-point'eol))(current-column))))(-ce-curcollangelem-col-1))))(defunc-lineup-arglist-close-under-paren(langelem)"Line up a closing paren line under the corresponding open paren.Works with: defun-close, class-close, inline-close, block-close,brace-list-close, arglist-close, extern-lang-close, namespace-close\(for most of these, a zero offset will normally produce the sameresult, though)."(save-excursion(let((langelem-col(c-langelem-collangelemt))(ce-curcol(save-excursion(beginning-of-line)(backward-up-list1)(current-column))))(-ce-curcollangelem-col))))(defunc-lineup-close-paren(langelem)"Line up the closing paren under its corresponding open paren if theopen paren is followed by code. If the open paren ends its line, noindentation is added. E.g:main (int, main ( char ** int, char ** ) <-> ) <- c-lineup-close-parenWorks with: defun-close, class-close, inline-close, block-close,brace-list-close, arglist-close, extern-lang-close, namespace-close."(save-excursion(condition-casenil(let(opencolspec)(beginning-of-line)(backward-up-list1)(setqspec(c-looking-at-special-brace-list))(ifspec(goto-char(car(carspec))))(setqopencol(current-column))(forward-char1)(ifspec(progn(c-forward-syntactic-ws)(forward-char1)))(c-forward-syntactic-ws(c-point'eol))(if(eolp)0(-opencol(c-langelem-collangelemt))))(errornil))))(defunc-lineup-streamop(langelem)"Line up C++ stream operators under each other.Works with: stream-op."(save-excursion(let((langelem-col(c-langelem-collangelem)))(re-search-forward"<<\\|>>"(c-point'eol)'move)(goto-char(match-beginning0))(-(current-column)langelem-col))))(defunc-lineup-multi-inher(langelem)"Line up the classes in C++ multiple inheritance clauses and memberinitializers under each other. E.g:class Foo: Foo::Foo (int a, int b): public Cyphr, Cyphr (a), public Bar <-> Bar (b) <- c-lineup-multi-inherclass Foo Foo::Foo (int a, int b) : public Cyphr, : Cyphr (a), public Bar <-> Bar (b) <- c-lineup-multi-inherclass Foo Foo::Foo (int a, int b) : public Cyphr : Cyphr (a) , public Bar <-> , Bar (b) <- c-lineup-multi-inherWorks with: inher-cont, member-init-cont."(save-excursion(let*((eol(c-point'eol))(here(point))(char-after-ip(progn(skip-chars-forward" \t")(char-after)))(langelem-col(c-langelem-collangelem)));; This kludge is necessary to support both inher-cont and;; member-init-cont, since they have different anchor positions.(c-backward-syntactic-ws)(when(eq(char-before)?:)(backward-char)(c-backward-syntactic-ws))(skip-chars-forward"^:"eol)(if(eqchar-after-ip?,)(skip-chars-forward" \t"eol)(skip-chars-forward" \t:"eol))(if(or(eolp)(looking-atc-comment-start-regexp))(c-forward-syntactic-wshere))(-(current-column)langelem-col))))(defunc-lineup-java-inher(langelem)"Line up Java implements and extends declarations.If class names follows on the same line as the implements/extendskeyword, they are lined up under each other. Otherwise, they areindented by adding `c-basic-offset' to the column of the keyword.E.g:class Foo class Foo extends extends Cyphr, Bar <-> Bar <- c-lineup-java-inher <--> c-basic-offsetWorks with: inher-cont."(save-excursion(let((langelem-col(c-langelem-collangelem)))(forward-word1)(if(looking-at"[ \t]*$")c-basic-offset(c-forward-syntactic-ws)(-(current-column)langelem-col)))))(defunc-lineup-java-throws(langelem)"Line up Java throws declarations.If exception names follows on the same line as the throws keyword,they are lined up under each other. Otherwise, they are indented byadding `c-basic-offset' to the column of the throws keyword. Thethrows keyword itself is also indented by `c-basic-offset' from thefunction declaration start if it doesn't hang. E.g:int foo() int foo() throws Cyphr, throws <-> Bar, <- c-lineup-java-throws Bar <-> Vlod <- c-lineup-java-throws<--><--> c-basic-offsetWorks with: func-decl-cont."(save-excursion(let*((lim(1-(c-point'bol)))(throws(catch'done(goto-char(cdrlangelem))(while(zerop(c-forward-token-11tlim))(if(looking-at"throws\\>[^_]")(throw'donet))))))(ifthrows(if(zerop(c-forward-token-11nil(c-point'eol)))(-(current-column)(c-langelem-collangelem))(back-to-indentation)(+(-(current-column)(c-langelem-collangelem))c-basic-offset))c-basic-offset))))(defunc-indent-one-line-block(langelem)"Indent a one line block `c-basic-offset' extra.E.g:if (n > 0) if (n > 0) {m+=n; n=0;} <-> { <- c-indent-one-line-block<--> c-basic-offset m+=n; n=0; }The block may use any kind of parenthesis character. nil is returnedif the line doesn't start with a one line block, which makes thefunction usable in list expressions.Work with: Almost all syntactic symbols, but most useful on *-open."(save-excursion(let((eol(c-point'eol)))(back-to-indentation)(if(and(eq(char-syntax(char-after))?\()(c-safe(progn(c-forward-sexp)t))(<=(point)eol))c-basic-offsetnil))))(defunc-indent-multi-line-block(langelem)"Indent a multi line block `c-basic-offset' extra.E.g:int *foo[] = { int *foo[] = { NULL, NULL, {17}, <-> { <- c-indent-multi-line-block 17 } <--> c-basic-offsetThe block may use any kind of parenthesis character. nil is returnedif the line doesn't start with a multi line block, which makes thefunction usable in list expressions.Work with: Almost all syntactic symbols, but most useful on *-open."(save-excursion(let((eol(c-point'eol)))(back-to-indentation)(if(and(eq(char-syntax(char-after))?\()(or(not(c-safe(progn(c-forward-sexp)t)))(>(point)eol)))c-basic-offsetnil))))(defunc-lineup-C-comments(langelem)"Line up C block comment continuation lines.Various heuristics are used to handle many of the common commentstyles. Some examples:/* /** /* /* text /* /** * text * text text text ** text ** text */ */ */ */ */ *//********************************************************************* * text ********************************************************************//********************************************************************* Free form text comments: In comments with a long delimiter line at the start, the indentation is kept unchanged for lines that start with an empty comment line prefix. The delimiter line is whatever matches the `comment-start-skip' regexp.*********************************************************************/The variable `c-comment-prefix-regexp' is used to recognize thecomment line prefix, e.g. the `*' that usually starts every lineinside a comment.Works with: The `c' syntactic symbol."(save-excursion(let*((here(point))(prefixlen(progn(back-to-indentation)(if(looking-atc-current-comment-prefix)(-(match-end0)(point))0)))(starterlen(save-excursion(goto-char(cdrlangelem))(looking-atcomment-start-skip)(-(save-excursion(goto-char(match-end0))(skip-chars-backward" \t")(point))(or(match-end1)(point))1))); Don't count the first '/'.(langelem-col(save-excursion(c-langelem-collangelem))))(if(and(>starterlen10)(zeropprefixlen));; The comment has a long starter and the line doesn't have;; a nonempty comment prefix. Treat it as free form text;; and don't change the indentation.(-(current-column)langelem-col)(forward-line-1)(back-to-indentation)(if(>=(cdrlangelem)(point));; On the second line in the comment.(if(zeropprefixlen);; No nonempty comment prefix. Align after comment;; starter.(progn(goto-char(match-end0))(if(looking-at"\\([ \t]+\\).+$");; Align with the text that hangs after the;; comment starter.(goto-char(match-end1)))(-(current-column)langelem-col));; How long is the comment starter? if greater than the;; length of the comment prefix, align left. if less;; than or equal, align right. this should also pick up;; Javadoc style comments.(if(>starterlenprefixlen)(progn(goto-char(cdrlangelem))(-(current-column)-1langelem-col))(goto-char(match-end0))(skip-chars-backward" \t")(-(current-column)prefixlenlangelem-col)));; Not on the second line in the comment. If the previous;; line has a nonempty comment prefix, align with it.;; Otherwise, align with the previous nonempty line, but;; align the comment ender with the starter.(when(or(not(looking-atc-current-comment-prefix))(eq(match-beginning0)(match-end0)))(goto-charhere)(back-to-indentation)(if(looking-at(concat"\\("c-current-comment-prefix"\\)\\*/"))(goto-char(cdrlangelem))(while(and(zerop(forward-line-1))(looking-at"^[ \t]*$")))(back-to-indentation)(if(<(point)(cdrlangelem));; Align with the comment starter rather than;; with the code before it.(goto-char(cdrlangelem)))))(-(current-column)langelem-col))))))(defunc-lineup-comment(langelem)"Line up a comment start according to `c-comment-only-line-offset'.If the comment is lined up with a comment starter on the previousline, that alignment is preserved.Works with: comment-intro."(save-excursion(back-to-indentation)(let((col(current-column)))(cond;; CASE 1: preserve aligned comments((save-excursion(and(c-forward-comment-1)(=col(current-column))))(vectorcol)); Return an absolute column.;; indent as specified by c-comment-only-line-offset((not(bolp))(or(car-safec-comment-only-line-offset)c-comment-only-line-offset))(t(or(cdr-safec-comment-only-line-offset)(car-safec-comment-only-line-offset)-1000));jam it against the left side))))(defunc-lineup-runin-statements(langelem)"Line up statements when the first statement is on the same line asthe block opening brace. E.g:int main(){ puts (\"Hello world!\"); return 0; <- c-lineup-runin-statements}If there is no statement after the opening brace to align with, nil isreturned. This makes the function usable in list expressions.Works with: The `statement' syntactic symbol."(if(eq(char-after(cdrlangelem))?{)(save-excursion(let((langelem-col(c-langelem-collangelem)))(forward-char1)(skip-chars-forward" \t")(unless(eolp)(-(current-column)langelem-col))))))(defunc-lineup-math(langelem)"Line up the current line after the equal sign on the first line inthe statement. If there isn't any, indent with `c-basic-offset'. Ifthe current line contains an equal sign too, try to align it with thefirst one.Works with: statement-cont."(save-excursion(let((equalp(save-excursion(goto-char(c-point'boi))(let((eol(c-point'eol)))(c-forward-token-10teol)(while(and(not(eq(char-after)?=))(=(c-forward-token-11teol)0))))(and(eq(char-after)?=)(-(point)(c-point'boi)))))(langelem-col(c-langelem-collangelem))donep)(while(and(notdonep)(<(point)(c-point'eol)))(skip-chars-forward"^="(c-point'eol))(if(c-in-literal(cdrlangelem))(forward-char1)(setqdonept)))(if(or(not(eq(char-after)?=))(save-excursion(forward-char1)(c-forward-syntactic-ws(c-point'eol))(eolp)));; there's no equal sign on the linec-basic-offset;; calculate indentation column after equals and ws, unless;; our line contains an equals sign(if(notequalp)(progn(forward-char1)(skip-chars-forward" \t")(setqequalp0)))(-(current-column)equalplangelem-col)))))(defunc-lineup-template-args(langelem)"Line up template argument lines under the first argument.To allow this function to be used in a list expression, nil isreturned if there's no template argument on the first line.Works with: template-args-cont."(save-excursion(c-with-syntax-tablec++-template-syntax-table(beginning-of-line)(backward-up-list1)(if(and(eq(char-after)?<)(zerop(c-forward-token-11nil(c-point'eol))))(-(current-column)(c-langelem-collangelem))))))(defunc-lineup-ObjC-method-call(langelem)"Line up selector args as elisp-mode does with function args:Go to the position right after the message receiver, and if you are atthe end of the line, indent the current line c-basic-offset columnsfrom the opening bracket; otherwise you are looking at the firstcharacter of the first method call argument, so lineup the currentline with it.Works with: objc-method-call-cont."(save-excursion(let*((extra(save-excursion(back-to-indentation)(c-backward-syntactic-ws(cdrlangelem))(if(eq(char-before)?:)(-c-basic-offset)0)))(open-bracket-pos(cdrlangelem))(open-bracket-col(progn(goto-charopen-bracket-pos)(current-column)))(target-col(progn(forward-char)(c-forward-sexp)(skip-chars-forward" \t")(if(eolp)(+open-bracket-colc-basic-offset)(current-column)))))(-target-colopen-bracket-colextra))))(defunc-lineup-ObjC-method-args(langelem)"Line up the colons that separate args.The colon on the current line is aligned with the one on the firstline.Works with: objc-method-args-cont."(save-excursion(let*((here(c-point'boi))(curcol(progn(goto-charhere)(current-column)))(eol(c-point'eol))(relpos(cdrlangelem))(first-col-column(progn(goto-charrelpos)(skip-chars-forward"^:"eol)(and(eq(char-after)?:)(current-column)))))(if(notfirst-col-column)c-basic-offset(goto-charhere)(skip-chars-forward"^:"eol)(if(eq(char-after)?:)(+curcol(-first-col-column(current-column)))c-basic-offset)))))(defunc-lineup-ObjC-method-args-2(langelem)"Line up the colons that separate args.The colon on the current line is aligned with the one on the previousline.Works with: objc-method-args-cont."(save-excursion(let*((here(c-point'boi))(curcol(progn(goto-charhere)(current-column)))(eol(c-point'eol))(relpos(cdrlangelem))(prev-col-column(progn(skip-chars-backward"^:"relpos)(and(eq(char-before)?:)(-(current-column)1)))))(if(notprev-col-column)c-basic-offset(goto-charhere)(skip-chars-forward"^:"eol)(if(eq(char-after)?:)(+curcol(-prev-col-column(current-column)))c-basic-offset)))))(defunc-lineup-inexpr-block(langelem)"Line up the block for constructs that use a block inside an expression,e.g. anonymous classes in Java and lambda functions in Pike. The bodyis aligned with the start of the header, e.g. with the \"new\" or\"lambda\" keyword. Returns nil if the block isn't part of such aconstruct.Works with: inlambda, inexpr-statement, inexpr-class."(save-excursion(back-to-indentation)(let((res(or(c-looking-at-inexpr-block)(if(c-safe(backward-up-list1)(eq(char-after)?{))(c-looking-at-inexpr-block)))))(whenres(goto-char(cdrres))(-(current-column)(progn(back-to-indentation)(current-column)))))))(defunc-lineup-whitesmith-in-block(langelem)"Line up lines inside a block in whitesmith style.It's done in a way that works both when the opening brace hangs andwhen it doesn't. E.g:something { something { foo; <-> foo; <- c-lineup-whitesmith-in-block } } <--> c-basic-offsetIn the first case the indentation is kept unchanged, in thesecond `c-basic-offset' is added.Works with: defun-close, defun-block-intro, block-close,brace-list-close, brace-list-intro, statement-block-intro, inclass,inextern-lang, innamespace."(save-excursion(goto-char(cdrlangelem))(back-to-indentation)(if(eq(char-syntax(char-after))?\()0c-basic-offset)))(defunc-lineup-dont-change(langelem)"Do not change the indentation of the current line.Works with: Any syntactic symbol."(save-excursion(back-to-indentation)(vector(current-column))))(defunc-snug-do-while(syntaxpos)"Dynamically calculate brace hanginess for do-while statements.Using this function, `while' clauses that end a `do-while' block willremain on the same line as the brace that closes that block.See `c-hanging-braces-alist' for how to utilize this function as anACTION associated with `block-close' syntax."(save-excursion(let(langelem)(if(and(eqsyntax'block-close)(setqlangelem(assq'block-closec-syntactic-context))(progn(goto-char(cdrlangelem))(if(eq(char-after)?{)(c-safe(c-forward-sexp-1)))(looking-at"\\<do\\>[^_]")))'(before)'(beforeafter)))))(defunc-gnu-impose-minimum()"Imposes a minimum indentation for lines inside a top-level construct.The variable `c-label-minimum-indentation' specifies the minimumindentation amount."(let((non-top-levels'(defun-block-introstatementstatement-contstatement-block-introstatement-case-introstatement-case-opensubstatementsubstatement-opencase-labellabeldo-while-closureelse-clause))(syntaxc-syntactic-context)langelem)(whilesyntax(setqlangelem(car(carsyntax))syntax(cdrsyntax));; don't adjust macro or comment-only lines(cond((memqlangelem'(cpp-macrocomment-intro))(setqsyntaxnil))((memqlangelemnon-top-levels)(save-excursion(setqsyntaxnil)(back-to-indentation)(if(zerop(current-column))(insert(make-stringc-label-minimum-indentation32)))))))));; Useful for c-hanging-semi&comma-criteria(defunc-semi&comma-inside-parenlist()"Controls newline insertion after semicolons in parenthesis lists.If a comma was inserted, no determination is made. If a semicolon wasinserted inside a parenthesis list, no newline is added otherwise anewline is added. In either case, checking is stopped. This supportsexactly the old newline insertion behavior.";; newline only after semicolon, but only if that semicolon is not;; inside a parenthesis list (e.g. a for loop statement)(if(not(eqlast-command-char?\;))nil; continue checking(if(condition-casenil(save-excursion(up-list-1)(not(eq(char-after)?\()))(errort))t'stop)));; Suppresses newlines before non-blank lines(defunc-semi&comma-no-newlines-before-nonblanks()"Controls newline insertion after semicolons.If a comma was inserted, no determination is made. If a semicolon wasinserted, and the following line is not blank, no newline is inserted.Otherwise, no determination is made."(save-excursion(if(and(=last-command-char?\;);;(/= (point-max);; (save-excursion (skip-syntax-forward " ") (point))(zerop(forward-line1))(not(looking-at"^[ \t]*$")))'stopnil)));; Suppresses new lines after semicolons in one-liners methods(defunc-semi&comma-no-newlines-for-oneline-inliners()"Controls newline insertion after semicolons for some one-line methods.If a comma was inserted, no determination is made. Newlines aresuppressed in one-liners, if the line is an in-class inline function.For other semicolon contexts, no determination is made."(let((syntax(c-guess-basic-syntax))(bol(save-excursion(if(c-safe(up-list-1)t)(c-point'bol)-1))))(if(and(eqlast-command-char?\;)(eq(car(carsyntax))'inclass)(eq(car(car(cdrsyntax)))'topmost-intro)(=(c-point'bol)bol))'stopnil)))(cc-provide'cc-align);;; cc-align.el ends here