* bug#5091: indentation in c++-mode
@ 2009-12-01 14:35 ` Vivien Oddou
2009-12-05 11:33 ` Alan Mackenzie
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Vivien Oddou @ 2009-12-01 14:35 UTC (permalink / raw
To: bug-gnu-emacs
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.
emacs 23.1.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* bug#5091: indentation in c++-mode
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-10 14:45 ` bug#5091: marked as done (indentation in c++-mode) Emacs bug Tracking System
2 siblings, 0 replies; 5+ messages in thread
From: Alan Mackenzie @ 2009-12-05 11:33 UTC (permalink / raw
To: voddou, 5091; +Cc: bug-gnu-emacs
[Reply-To: set]
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.
> emacs 23.1.1
Thanks for reporting this bug, and thanks for making it crisp and easy to
follow.
The two scenarios above aren't quite identical - the first one, in the
namespace, is treated as being at "top level". The second one is inside
a function, and hasn't been handled up to now.
Give me a few days, and I should be able to fix it.
--
Alan Mackenzie (Nuremberg, Germany).
^ permalink raw reply [flat|nested] 5+ messages in thread
* bug#5091: indentation in c++-mode
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
2009-12-10 14:45 ` bug#5091: marked as done (indentation in c++-mode) Emacs bug Tracking System
2 siblings, 1 reply; 5+ messages in thread
From: Alan Mackenzie @ 2009-12-10 14:37 UTC (permalink / raw
To: voddou, 5091
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.
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
--
Alan Mackenzie (Nuremberg, Germany).
^ permalink raw reply [flat|nested] 5+ messages in thread
* bug#5091: marked as done (indentation in c++-mode)
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-10 14:45 ` Emacs bug Tracking System
2 siblings, 0 replies; 5+ messages in thread
From: Emacs bug Tracking System @ 2009-12-10 14:45 UTC (permalink / raw
To: Alan Mackenzie
[-- Attachment #1: Type: text/plain, Size: 842 bytes --]
Your message dated Thu, 10 Dec 2009 14:47:38 +0000
with message-id <20091210144738.GD1504@muc.de>
and subject line Re: bug#5091: indentation in c++-mode
has caused the Emacs bug report #5091,
regarding indentation in c++-mode
to be marked as done.
This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
bug report if necessary, and/or fix the problem forthwith.
(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@emacsbugs.donarmstrong.com
immediately.)
--
5091: http://emacsbugs.donarmstrong.com/cgi-bin/bugreport.cgi?bug=5091
Emacs Bug Tracking System
Contact owner@emacsbugs.donarmstrong.com with problems
[-- Attachment #2: Type: message/rfc822, Size: 2417 bytes --]
From: Vivien Oddou <voddou@e-onsoftware.com>
To: bug-gnu-emacs@gnu.org
Subject: indentation in c++-mode
Date: Tue, 01 Dec 2009 15:35:38 +0100
Message-ID: <1259678138.22343.7.camel@imagina04.e-onsoftware.com>
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.
emacs 23.1.1
[-- Attachment #3: Type: message/rfc822, Size: 1975 bytes --]
From: Alan Mackenzie <acm@muc.de>
To: 5091-done@emacsbugs.donarmstrong.com
Subject: Re: bug#5091: indentation in c++-mode
Date: Thu, 10 Dec 2009 14:47:38 +0000
Message-ID: <20091210144738.GD1504@muc.de>
Solved by fixing c-guess-basic-syntax in cc-engine.el.
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.
>
> emacs 23.1.1
>
>
>
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* bug#5091: indentation in c++-mode
2009-12-10 14:37 ` Alan Mackenzie
@ 2009-12-14 11:33 ` Vivien Oddou
0 siblings, 0 replies; 5+ messages in thread
From: Vivien Oddou @ 2009-12-14 11:33 UTC (permalink / raw
To: Alan Mackenzie; +Cc: 5091
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
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2009-12-14 11:33 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[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
2009-12-10 14:45 ` bug#5091: marked as done (indentation in c++-mode) Emacs bug Tracking System
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.