[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#5091: indentation in c++-mode
From: |
Vivien Oddou |
Subject: |
bug#5091: indentation in c++-mode |
Date: |
Mon, 14 Dec 2009 12:33:44 +0100 |
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
>