From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Vivien Oddou Newsgroups: gmane.emacs.bugs Subject: bug#5091: indentation in c++-mode Date: Mon, 14 Dec 2009 12:33:44 +0100 Organization: e-on software Message-ID: <1260790424.6151.1.camel@imagina04.e-onsoftware.com> References: <1259678138.22343.7.camel@imagina04.e-onsoftware.com> <20091210143717.GC1504@muc.de> Reply-To: voddou@e-onsoftware.com, 5091@emacsbugs.donarmstrong.com NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain Content-Transfer-Encoding: 7bit X-Trace: ger.gmane.org 1260810316 30006 80.91.229.12 (14 Dec 2009 17:05:16 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Mon, 14 Dec 2009 17:05:16 +0000 (UTC) Cc: 5091@emacsbugs.donarmstrong.com To: Alan Mackenzie Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Mon Dec 14 18:05:08 2009 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1NKELx-0002X4-Lk for geb-bug-gnu-emacs@m.gmane.org; Mon, 14 Dec 2009 18:04:58 +0100 Original-Received: from localhost ([127.0.0.1]:52183 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NKELx-0002yL-9e for geb-bug-gnu-emacs@m.gmane.org; Mon, 14 Dec 2009 12:04:57 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NK9Oy-0005TO-6d for bug-gnu-emacs@gnu.org; Mon, 14 Dec 2009 06:47:44 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NK9Os-0005QO-6C for bug-gnu-emacs@gnu.org; Mon, 14 Dec 2009 06:47:43 -0500 Original-Received: from [199.232.76.173] (port=57098 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NK9Or-0005Q3-On for bug-gnu-emacs@gnu.org; Mon, 14 Dec 2009 06:47:37 -0500 Original-Received: from rzlab.ucr.edu ([138.23.92.77]:51953) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1NK9Op-0006cH-HO for bug-gnu-emacs@gnu.org; Mon, 14 Dec 2009 06:47:36 -0500 Original-Received: from rzlab.ucr.edu (rzlab.ucr.edu [127.0.0.1]) by rzlab.ucr.edu (8.14.3/8.14.3/Debian-5) with ESMTP id nBEBlTUh006297; Mon, 14 Dec 2009 03:47:29 -0800 Original-Received: (from debbugs@localhost) by rzlab.ucr.edu (8.14.3/8.14.3/Submit) id nBEBe7Zx005578; Mon, 14 Dec 2009 03:40:07 -0800 Resent-Date: Mon, 14 Dec 2009 03:40:07 -0800 X-Loop: owner@emacsbugs.donarmstrong.com Resent-From: Vivien Oddou Resent-To: bug-submit-list@donarmstrong.com Resent-CC: Emacs Bugs , owner@emacsbugs.donarmstrong.com 2Resent-Date: Mon, 14 Dec 2009 11:40:06 +0000 Resent-Message-ID: Resent-Sender: owner@emacsbugs.donarmstrong.com X-Emacs-PR-Message: followup 5091 X-Emacs-PR-Package: emacs,cc-mode X-Emacs-PR-Keywords: Original-Received: via spool by 5091-submit@emacsbugs.donarmstrong.com id=B5091.12607904334866 (code B ref 5091); Mon, 14 Dec 2009 11:40:06 +0000 Original-Received: (at 5091) by emacsbugs.donarmstrong.com; 14 Dec 2009 11:33:53 +0000 X-Spam-Bayes: score:0.5 Bayes not run. spammytokens:Tokens not available. hammytokens:Tokens not available. Original-Received: from mail1.e-onsoftware.com (mail1.e-onsoftware.com [75.126.129.87]) by rzlab.ucr.edu (8.14.3/8.14.3/Debian-5) with ESMTP id nBEBXqg0004863 for <5091@emacsbugs.donarmstrong.com>; Mon, 14 Dec 2009 03:33:53 -0800 Original-Received: from [192.168.0.94] (vol75-12-88-162-118-162.fbx.proxad.net [88.162.118.162]) (Authenticated sender: voddou@e-onsoftware.com) by mail1.e-onsoftware.com (Postfix) with ESMTPA id D6E6B170076; Mon, 14 Dec 2009 03:33:45 -0800 (PST) In-Reply-To: <20091210143717.GC1504@muc.de> X-Mailer: Evolution 2.12.3 X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 2) Resent-Date: Mon, 14 Dec 2009 06:47:43 -0500 X-Mailman-Approved-At: Mon, 14 Dec 2009 11:37:28 -0500 X-BeenThere: bug-gnu-emacs@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:33569 Archived-At: Hello :) On Thu, 2009-12-10 at 14:37 +0000, Alan Mackenzie wrote: > Hi, Vivien! > > On Tue, Dec 01, 2009 at 03:35:38PM +0100, Vivien Oddou wrote: > > in this code: > > > namespace n > > { > > int a = func > float>(); // C-c C-s gives ((template-args-cont)) > > } > > > void f() > > { > > int a = func > float>(); // C-C Cs : ((defun-block-intro)) > > > int b = func< > > int, // here too, refering to f() opening brace > > float>(); > > } > > > this is not normal. > > Indeed not. > > I've fixed this, and committed it to the head in Savannah. Here is the > patch. Please try it out and let me know if anything isn't as it should > be. I try to apply it but i get lots of rejected hunks so i suppose i don't have the same version as the one you're working on (cvs latest?) so i'll just wait for the next package release, i just hope it'll not be in two years like we're used to :) > > > > Index: cc-engine.el > =================================================================== > RCS file: /cvsroot/emacs/emacs/lisp/progmodes/cc-engine.el,v > retrieving revision 1.79 > diff -c -r1.79 cc-engine.el > *** cc-engine.el 3 Dec 2009 16:02:10 -0000 1.79 > --- cc-engine.el 10 Dec 2009 14:14:24 -0000 > *************** > *** 3743,3748 **** > --- 3743,3799 ---- > (goto-char bound)) > nil))) > > + (defsubst c-ssb-lit-begin () > + ;; Return the start of the literal point is in, or nil. > + ;; We read and write the variables `safe-pos', `safe-pos-list', `state' > + ;; bound in the caller. > + > + ;; Use `parse-partial-sexp' from a safe position down to the point to check > + ;; if it's outside comments and strings. > + (save-excursion > + (let ((pos (point)) safe-pos state pps-end-pos) > + ;; Pick a safe position as close to the point as possible. > + ;; > + ;; FIXME: Consult `syntax-ppss' here if our cache doesn't give a good > + ;; position. > + > + (while (and safe-pos-list > + (> (car safe-pos-list) (point))) > + (setq safe-pos-list (cdr safe-pos-list))) > + (unless (setq safe-pos (car-safe safe-pos-list)) > + (setq safe-pos (max (or (c-safe-position > + (point) (or c-state-cache > + (c-parse-state))) > + 0) > + (point-min)) > + safe-pos-list (list safe-pos))) > + > + ;; Cache positions along the way to use if we have to back up more. We > + ;; cache every closing paren on the same level. If the paren cache is > + ;; relevant in this region then we're typically already on the same > + ;; level as the target position. Note that we might cache positions > + ;; after opening parens in case safe-pos is in a nested list. That's > + ;; both uncommon and harmless. > + (while (progn > + (setq state (parse-partial-sexp > + safe-pos pos 0)) > + (< (point) pos)) > + (setq safe-pos (point) > + safe-pos-list (cons safe-pos safe-pos-list))) > + > + ;; If the state contains the start of the containing sexp we cache that > + ;; position too, so that parse-partial-sexp in the next run has a bigger > + ;; chance of starting at the same level as the target position and thus > + ;; will get more good safe positions into the list. > + (if (elt state 1) > + (setq safe-pos (1+ (elt state 1)) > + safe-pos-list (cons safe-pos safe-pos-list))) > + > + (if (or (elt state 3) (elt state 4)) > + ;; Inside string or comment. Continue search at the > + ;; beginning of it. > + (elt state 8))))) > + > (defun c-syntactic-skip-backward (skip-chars &optional limit paren-level) > "Like `skip-chars-backward' but only look at syntactically relevant chars, > i.e. don't stop at positions inside syntactic whitespace or string > *************** > *** 3761,3900 **** > comment at the start of cc-engine.el for more info." > > (let ((start (point)) > ! state > ;; A list of syntactically relevant positions in descending > ;; order. It's used to avoid scanning repeatedly over > ;; potentially large regions with `parse-partial-sexp' to verify > ! ;; each position. > safe-pos-list > - ;; The position at the beginning of `safe-pos-list'. > - safe-pos > ;; The result from `c-beginning-of-macro' at the start position or the > ;; start position itself if it isn't within a macro. Evaluated on > ;; demand. > start-macro-beg > ;; The earliest position after the current one with the same paren > ;; level. Used only when `paren-level' is set. > (paren-level-pos (point))) > > ! (while (progn > ! (while (and > ! (< (skip-chars-backward skip-chars limit) 0) > > ! ;; Use `parse-partial-sexp' from a safe position down to > ! ;; the point to check if it's outside comments and > ! ;; strings. > ! (let ((pos (point)) state-2 pps-end-pos) > ! ;; Pick a safe position as close to the point as > ! ;; possible. > ! ;; > ! ;; FIXME: Consult `syntax-ppss' here if our > ! ;; cache doesn't give a good position. > ! (while (and safe-pos-list > ! (> (car safe-pos-list) (point))) > ! (setq safe-pos-list (cdr safe-pos-list))) > ! (unless (setq safe-pos (car-safe safe-pos-list)) > ! (setq safe-pos (max (or (c-safe-position > ! (point) (or c-state-cache > ! (c-parse-state))) > ! 0) > ! (point-min)) > ! safe-pos-list (list safe-pos))) > ! > ! ;; Cache positions along the way to use if we have to > ! ;; back up more. We cache every closing paren on the > ! ;; same level. If the paren cache is relevant in this > ! ;; region then we're typically already on the same > ! ;; level as the target position. Note that we might > ! ;; cache positions after opening parens in case > ! ;; safe-pos is in a nested list. That's both uncommon > ! ;; and harmless. > ! (while (progn > ! (setq state (parse-partial-sexp > ! safe-pos pos 0)) > ! (< (point) pos)) > ! (setq safe-pos (point) > ! safe-pos-list (cons safe-pos safe-pos-list))) > ! > ! (cond > ! ((or (elt state 3) (elt state 4)) > ! ;; Inside string or comment. Continue search at the > ! ;; beginning of it. > ! (goto-char (elt state 8)) > ! t) > > ! ((and paren-level > ! (save-excursion > ! (setq state-2 (parse-partial-sexp > ! pos paren-level-pos -1) > ! pps-end-pos (point)) > ! (/= (car state-2) 0))) > ! ;; Not at the right level. > ! > ! (if (and (< (car state-2) 0) > ! ;; We stop above if we go out of a paren. > ! ;; Now check whether it precedes or is > ! ;; nested in the starting sexp. > ! (save-excursion > ! (setq state-2 > ! (parse-partial-sexp > ! pps-end-pos paren-level-pos > ! nil nil state-2)) > ! (< (car state-2) 0))) > ! > ! ;; We've stopped short of the starting position > ! ;; so the hit was inside a nested list. Go up > ! ;; until we are at the right level. > ! (condition-case nil > (progn > ! (goto-char (scan-lists pos -1 > ! (- (car state-2)))) > ! (setq paren-level-pos (point)) > ! (if (and limit (>= limit paren-level-pos)) > ! (progn > ! (goto-char limit) > ! nil) > ! t)) > ! (error > ! (goto-char (or limit (point-min))) > ! nil)) > ! > ! ;; The hit was outside the list at the start > ! ;; position. Go to the start of the list and exit. > ! (goto-char (1+ (elt state-2 1))) > ! nil)) > ! > ! ((c-beginning-of-macro limit) > ! ;; Inside a macro. > ! (if (< (point) > ! (or start-macro-beg > ! (setq start-macro-beg > ! (save-excursion > ! (goto-char start) > ! (c-beginning-of-macro limit) > ! (point))))) > ! t > ! > ! ;; It's inside the same macro we started in so it's > ! ;; a relevant match. > ! (goto-char pos) > ! nil))))) > ! > ! ;; If the state contains the start of the containing sexp we > ! ;; cache that position too, so that parse-partial-sexp in the > ! ;; next run has a bigger chance of starting at the same level > ! ;; as the target position and thus will get more good safe > ! ;; positions into the list. > ! (if (elt state 1) > ! (setq safe-pos (1+ (elt state 1)) > ! safe-pos-list (cons safe-pos safe-pos-list)))) > > ! (> (point) > ! (progn > ! ;; Skip syntactic ws afterwards so that we don't stop at the > ! ;; end of a comment if `skip-chars' is something like "^/". > ! (c-backward-syntactic-ws) > ! (point))))) > > ;; We might want to extend this with more useful return values in > ;; the future. > --- 3812,3911 ---- > comment at the start of cc-engine.el for more info." > > (let ((start (point)) > ! state-2 > ;; A list of syntactically relevant positions in descending > ;; order. It's used to avoid scanning repeatedly over > ;; potentially large regions with `parse-partial-sexp' to verify > ! ;; each position. Used in `c-ssb-lit-begin' > safe-pos-list > ;; The result from `c-beginning-of-macro' at the start position or the > ;; start position itself if it isn't within a macro. Evaluated on > ;; demand. > start-macro-beg > ;; The earliest position after the current one with the same paren > ;; level. Used only when `paren-level' is set. > + lit-beg > (paren-level-pos (point))) > > ! (while > ! (progn > ! ;; The next loop "tries" to find the end point each time round, > ! ;; loops when it hasn't succeeded. > ! (while > ! (and > ! (< (skip-chars-backward skip-chars limit) 0) > > ! (let ((pos (point)) state-2 pps-end-pos) > > ! (cond > ! ;; Don't stop inside a literal > ! ((setq lit-beg (c-ssb-lit-begin)) > ! (goto-char lit-beg) > ! t) > ! > ! ((and paren-level > ! (save-excursion > ! (setq state-2 (parse-partial-sexp > ! pos paren-level-pos -1) > ! pps-end-pos (point)) > ! (/= (car state-2) 0))) > ! ;; Not at the right level. > ! > ! (if (and (< (car state-2) 0) > ! ;; We stop above if we go out of a paren. > ! ;; Now check whether it precedes or is > ! ;; nested in the starting sexp. > ! (save-excursion > ! (setq state-2 > ! (parse-partial-sexp > ! pps-end-pos paren-level-pos > ! nil nil state-2)) > ! (< (car state-2) 0))) > ! > ! ;; We've stopped short of the starting position > ! ;; so the hit was inside a nested list. Go up > ! ;; until we are at the right level. > ! (condition-case nil > ! (progn > ! (goto-char (scan-lists pos -1 > ! (- (car state-2)))) > ! (setq paren-level-pos (point)) > ! (if (and limit (>= limit paren-level-pos)) > (progn > ! (goto-char limit) > ! nil) > ! t)) > ! (error > ! (goto-char (or limit (point-min))) > ! nil)) > > ! ;; The hit was outside the list at the start > ! ;; position. Go to the start of the list and exit. > ! (goto-char (1+ (elt state-2 1))) > ! nil)) > ! > ! ((c-beginning-of-macro limit) > ! ;; Inside a macro. > ! (if (< (point) > ! (or start-macro-beg > ! (setq start-macro-beg > ! (save-excursion > ! (goto-char start) > ! (c-beginning-of-macro limit) > ! (point))))) > ! t > ! > ! ;; It's inside the same macro we started in so it's > ! ;; a relevant match. > ! (goto-char pos) > ! nil)))))) > ! > ! (> (point) > ! (progn > ! ;; Skip syntactic ws afterwards so that we don't stop at the > ! ;; end of a comment if `skip-chars' is something like "^/". > ! (c-backward-syntactic-ws) > ! (point))))) > > ;; We might want to extend this with more useful return values in > ;; the future. > *************** > *** 8426,8431 **** > --- 8437,8443 ---- > literal char-before-ip before-ws-ip char-after-ip macro-start > in-macro-expr c-syntactic-context placeholder c-in-literal-cache > step-type tmpsymbol keyword injava-inher special-brace-list tmp-pos > + containing-< > ;; The following record some positions for the containing > ;; declaration block if we're directly within one: > ;; `containing-decl-open' is the position of the open > *************** > *** 9040,9046 **** > (back-to-indentation))) > ;; FIXME: Should use c-add-stmt-syntax, but it's not yet > ;; template aware. > ! (c-add-syntax 'template-args-cont (point))) > > ;; CASE 5D.4: perhaps a multiple inheritance line? > ((and (c-major-mode-is 'c++-mode) > --- 9052,9058 ---- > (back-to-indentation))) > ;; FIXME: Should use c-add-stmt-syntax, but it's not yet > ;; template aware. > ! (c-add-syntax 'template-args-cont (point) placeholder)) > > ;; CASE 5D.4: perhaps a multiple inheritance line? > ((and (c-major-mode-is 'c++-mode) > *************** > *** 9252,9261 **** > ;; arglist that begins on the previous line. > ((and c-recognize-<>-arglists > (eq (char-before) ?<) > (not (and c-overloadable-operators-regexp > (c-after-special-operator-id lim)))) > (c-beginning-of-statement-1 (c-safe-position (point) paren-state)) > ! (c-add-syntax 'template-args-cont (c-point 'boi))) > > ;; CASE 5Q: we are at a statement within a macro. > (macro-start > --- 9264,9274 ---- > ;; arglist that begins on the previous line. > ((and c-recognize-<>-arglists > (eq (char-before) ?<) > + (setq placeholder (1- (point))) > (not (and c-overloadable-operators-regexp > (c-after-special-operator-id lim)))) > (c-beginning-of-statement-1 (c-safe-position (point) paren-state)) > ! (c-add-syntax 'template-args-cont (c-point 'boi) placeholder)) > > ;; CASE 5Q: we are at a statement within a macro. > (macro-start > *************** > *** 9277,9290 **** > > ;; (CASE 6 has been removed.) > > ;; CASE 7: line is an expression, not a statement. Most > ;; likely we are either in a function prototype or a function > ! ;; call argument list > ((not (or (and c-special-brace-lists > (save-excursion > (goto-char containing-sexp) > (c-looking-at-special-brace-list))) > ! (eq (char-after containing-sexp) ?{))) > (cond > > ;; CASE 7A: we are looking at the arglist closing paren. > --- 9290,9327 ---- > > ;; (CASE 6 has been removed.) > > + ;; CASE 19: line is an expression, not a statement, and is directly > + ;; contained by a template delimiter. Most likely, we are in a > + ;; template arglist within a statement. This case is based on CASE > + ;; 7. At some point in the future, we may wish to create more > + ;; syntactic symbols such as `template-intro', > + ;; `template-cont-nonempty', etc., and distinguish between them as we > + ;; do for `arglist-intro' etc. (2009-12-07). > + ((and c-recognize-<>-arglists > + (setq containing-< (c-up-list-backward indent-point containing-sexp)) > + (eq (char-after containing-<) ?\<)) > + (setq placeholder (c-point 'boi containing-<)) > + (goto-char containing-sexp) ; Most nested Lbrace/Lparen (but not > + ; '<') before indent-point. > + (if (>= (point) placeholder) > + (progn > + (forward-char) > + (skip-chars-forward " \t")) > + (goto-char placeholder)) > + (c-add-stmt-syntax 'template-args-cont (list containing-<) t > + (c-most-enclosing-brace c-state-cache (point)) > + paren-state)) > + > + > ;; CASE 7: line is an expression, not a statement. Most > ;; likely we are either in a function prototype or a function > ! ;; call argument list, or a template argument list. > ((not (or (and c-special-brace-lists > (save-excursion > (goto-char containing-sexp) > (c-looking-at-special-brace-list))) > ! (eq (char-after containing-sexp) ?{) > ! (eq (char-after containing-sexp) ?<))) > (cond > > ;; CASE 7A: we are looking at the arglist closing paren. > *************** > *** 9381,9387 **** > (c-forward-syntactic-ws) > (point)) > (c-point 'bonl))) > ! (goto-char containing-sexp) > (setq placeholder (c-point 'boi)) > (if (and (c-safe (backward-up-list 1) t) > (>= (point) placeholder)) > --- 9418,9424 ---- > (c-forward-syntactic-ws) > (point)) > (c-point 'bonl))) > ! (goto-char containing-sexp) ; paren opening the arglist > (setq placeholder (c-point 'boi)) > (if (and (c-safe (backward-up-list 1) t) > (>= (point) placeholder)) > Index: cc-mode.el > =================================================================== > RCS file: /cvsroot/emacs/emacs/lisp/progmodes/cc-mode.el,v > retrieving revision 1.88 > diff -c -r1.88 cc-mode.el > *** cc-mode.el 5 Dec 2009 11:16:04 -0000 1.88 > --- cc-mode.el 10 Dec 2009 14:14:24 -0000 > *************** > *** 541,559 **** > (make-local-variable 'lookup-syntax-properties) > (setq lookup-syntax-properties t))) > > ! ;; Use this in Emacs 21 to avoid meddling with the rear-nonsticky > ;; property on each character. > (when (boundp 'text-property-default-nonsticky) > (make-local-variable 'text-property-default-nonsticky) > ! (let ((elem (assq 'syntax-table text-property-default-nonsticky))) > ! (if elem > ! (setcdr elem t) > ! (setq text-property-default-nonsticky > ! (cons '(syntax-table . t) > ! text-property-default-nonsticky)))) > ! (setq text-property-default-nonsticky > ! (cons '(c-type . t) > ! text-property-default-nonsticky))) > > ;; In Emacs 21 and later it's possible to turn off the ad-hoc > ;; heuristic that open parens in column 0 are defun starters. Since > --- 541,555 ---- > (make-local-variable 'lookup-syntax-properties) > (setq lookup-syntax-properties t))) > > ! ;; Use this in Emacs 21+ to avoid meddling with the rear-nonsticky > ;; property on each character. > (when (boundp 'text-property-default-nonsticky) > (make-local-variable 'text-property-default-nonsticky) > ! (mapc (lambda (tprop) > ! (unless (assq tprop text-property-default-nonsticky) > ! (setq text-property-default-nonsticky > ! (cons `(,tprop . t) text-property-default-nonsticky)))) > ! '(syntax-table category c-type))) > > ;; In Emacs 21 and later it's possible to turn off the ad-hoc > ;; heuristic that open parens in column 0 are defun starters. Since > > > emacs 23.1.1 >