all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Vivien Oddou <voddou@e-onsoftware.com>
To: Alan Mackenzie <acm@muc.de>
Cc: 5091@emacsbugs.donarmstrong.com
Subject: bug#5091: indentation in c++-mode
Date: Mon, 14 Dec 2009 12:33:44 +0100	[thread overview]
Message-ID: <1260790424.6151.1.camel@imagina04.e-onsoftware.com> (raw)
In-Reply-To: <20091210143717.GC1504@muc.de>

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<int,
> >                  float>();  // C-c C-s gives ((template-args-cont))
> > }
> 
> > void f()
> > {
> >     int a = func<int,
> >         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
> 






  reply	other threads:[~2009-12-14 11:33 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20091210144738.GD1504@muc.de>
2009-12-01 14:35 ` bug#5091: indentation in c++-mode Vivien Oddou
2009-12-05 11:33   ` Alan Mackenzie
2009-12-10 14:37   ` Alan Mackenzie
2009-12-14 11:33     ` Vivien Oddou [this message]
2009-12-10 14:45   ` bug#5091: marked as done (indentation in c++-mode) Emacs bug Tracking System

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1260790424.6151.1.camel@imagina04.e-onsoftware.com \
    --to=voddou@e-onsoftware.com \
    --cc=5091@emacsbugs.donarmstrong.com \
    --cc=acm@muc.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.