[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] /srv/bzr/emacs/trunk r106221: DTRT for c-beginning/end-of-
From: |
Alan Mackenzie |
Subject: |
[Emacs-diffs] /srv/bzr/emacs/trunk r106221: DTRT for c-beginning/end-of-defun in nested declaration scopes. |
Date: |
Fri, 28 Oct 2011 15:37:28 +0000 |
User-agent: |
Bazaar (2.3.1) |
------------------------------------------------------------
revno: 106221 [merge]
committer: Alan Mackenzie <address@hidden>
branch nick: trunk
timestamp: Fri 2011-10-28 15:37:28 +0000
message:
DTRT for c-beginning/end-of-defun in nested declaration scopes.
modified:
doc/misc/cc-mode.texi
lisp/ChangeLog
lisp/progmodes/cc-cmds.el
lisp/progmodes/cc-engine.el
lisp/progmodes/cc-vars.el
=== modified file 'doc/misc/cc-mode.texi'
--- a/doc/misc/cc-mode.texi 2011-10-27 20:34:23 +0000
+++ b/doc/misc/cc-mode.texi 2011-10-28 14:35:39 +0000
@@ -891,6 +891,8 @@
@itemx @kbd{C-M-e} (@code{c-end-of-defun})
@findex c-beginning-of-defun
@findex c-end-of-defun
address@hidden c-defun-tactic
address@hidden defun-tactic (c-)
Move to the beginning or end of the current or next function. Other
constructs (such as a structs or classes) which have a brace block
@@ -904,6 +906,15 @@
start or end of the function. This occasionally causes point not to
move at all.
+By default, these commands will recognize functions contained within a
address@hidden scope} such as a C++ @code{class} or @code{namespace}
+construct, should the point start inside it. If @ccmode fails to find
+function beginnings or ends inside the current declaration scope, it
+will search the enclosing scopes. If you want @ccmode to recognize
+functions only at the top address@hidden was @ccmode{}'s
+behaviour prior to version 5.32.}, set @code{c-defun-tatic} to
address@hidden
+
These functions are analogous to the Emacs built-in commands
@code{beginning-of-defun} and @code{end-of-defun}, except they
eliminate the constraint that the top-level opening brace of the defun
=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog 2011-10-28 14:47:50 +0000
+++ b/lisp/ChangeLog 2011-10-28 15:24:05 +0000
@@ -1,3 +1,30 @@
+2011-10-28 Alan Mackenzie <address@hidden>
+
+ Amend the handling of c-beginning/end-of-defun in nested declaration
+ scopes.
+
+ * cc-vars.el (c-defun-tactic): Move here from cc-langs.el. Change it
to a
+ defcustom.
+
+ * cc-mode.texi (Movement Commands): Document `c-defun-tactic'. Document
+ the new handling of nested scopes for movement by defuns.
+
+ * cc-langs.el (c-defun-tactic): Move this variable to cc-vars.el.
+ (c-nonlabel-token-2-key): New variable for change in cc-engine.el.
+
+ * cc-engine.el (c-beginning-of-statement-1): Prevent "class foo : bar"
+ being spuriously recognized as a label.
+
+ * cc-cmds.el (c-narrow-to-most-enclosing-decl-block): Add parameter
+ `inclusive' (to include enclosing braces in the region).
+ (c-widen-to-enclosing-decl-scope): New function.
+ (c-while-widening-to-decl-block): New macro.
+ (c-beginning-of-defun, c-end-of-defun): Change algorithm to keep going
+ outward for defun boundaries, and correspondingly change symbol
+ `respect-enclosure' to `go-outward'.
+ (c-declaration-limits): Change algorithm to report only the "innermost"
+ defun's boundaries.
+
2011-10-28 Deniz Dogan <address@hidden>
* net/rcirc.el (rcirc-mode): Use hard newlines.
=== modified file 'lisp/progmodes/cc-cmds.el'
--- a/lisp/progmodes/cc-cmds.el 2011-03-12 19:19:47 +0000
+++ b/lisp/progmodes/cc-cmds.el 2011-10-28 14:34:39 +0000
@@ -1485,6 +1485,78 @@
(setq n (1- n))))
n)
+(defun c-narrow-to-most-enclosing-decl-block (&optional inclusive)
+ ;; If we are inside a decl-block (in the sense of c-looking-at-decl-block),
+ ;; i.e. something like namespace{} or extern{}, narrow to the insides of
+ ;; that block (NOT including the enclosing braces) if INCLUSIVE is nil,
+ ;; otherwise include the braces. If the closing brace is missing,
+ ;; (point-max) is used instead.
+ (let ((paren-state (c-parse-state))
+ encl-decl)
+ (setq encl-decl (and paren-state (c-most-enclosing-decl-block
paren-state)))
+ (if encl-decl
+ (save-excursion
+ (narrow-to-region
+ (if inclusive
+ (progn (goto-char encl-decl)
+ (c-beginning-of-decl-1)
+ (point))
+ (1+ encl-decl))
+ (progn
+ (goto-char encl-decl)
+ (or (c-safe (forward-list)
+ (if inclusive
+ (point)
+ (1- (point))))
+ (point-max))))))))
+
+(defun c-widen-to-enclosing-decl-scope (paren-state orig-point-min
orig-point-max)
+ ;; Narrow the buffer to the innermost declaration scope (e.g. a class, a
+ ;; namespace or the "whole buffer") recorded in PAREN-STATE, the bounding
+ ;; braces NOT being included in the resulting region. On no account may the
+ ;; final region exceed that bounded by ORIG-POINT-MIN, ORIG-POINT-MAX.
+ ;; PAREN-STATE is a list of buffer positions in the style of
+ ;; (c-parse-state), one of which will be that of the desired opening brace,
+ ;; if there is one.
+ ;;
+ ;; Return the position of the enclosing opening brace, or nil
+ (let (encl-decl) ; putative position of decl-scope's opening brace.
+ (save-restriction
+ (narrow-to-region orig-point-min orig-point-max)
+ (setq encl-decl (and paren-state
+ (c-most-enclosing-decl-block paren-state))))
+ (if encl-decl
+ (progn
+ (widen)
+ (narrow-to-region (1+ encl-decl)
+ (save-excursion
+ (goto-char encl-decl)
+ (or (c-safe (forward-list)
+ (1- (point)))
+ orig-point-max)))
+ encl-decl)
+ (narrow-to-region orig-point-min orig-point-max)
+ nil)))
+
+(eval-and-compile
+ (defmacro c-while-widening-to-decl-block (condition)
+ ;; Repeatedly evaluate CONDITION until it returns nil. After each
+ ;; evaluation, if `c-defun-tactic' is set appropriately, widen to innards
+ ;; of the next enclosing declaration block (e.g. namespace, class), or the
+ ;; buffer's original restriction.
+ ;;
+ ;; This is a very special purpose macro, which assumes the existence of
+ ;; several variables. It is for use only in c-beginning-of-defun and
+ ;; c-end-of-defun.
+ `(while
+ (and ,condition
+ (eq c-defun-tactic 'go-outward)
+ lim)
+ (setq paren-state (c-whack-state-after lim paren-state))
+ (setq lim (c-widen-to-enclosing-decl-scope
+ paren-state orig-point-min orig-point-max))
+ (setq where 'in-block))))
+
(defun c-beginning-of-defun (&optional arg)
"Move backward to the beginning of a defun.
Every top level declaration that contains a brace paren block is
@@ -1509,50 +1581,66 @@
(c-save-buffer-state
(beginning-of-defun-function end-of-defun-function
(start (point))
- where paren-state pos)
-
- ;; Move back out of any macro/comment/string we happen to be in.
- (c-beginning-of-macro)
- (setq pos (c-literal-limits))
- (if pos (goto-char (car pos)))
-
- (setq where (c-where-wrt-brace-construct))
-
- (if (< arg 0)
- ;; Move forward to the closing brace of a function.
- (progn
- (if (memq where '(at-function-end outwith-function))
- (setq arg (1+ arg)))
- (if (< arg 0)
- (setq arg (c-forward-to-nth-EOF-} (- arg) where)))
- ;; Move forward to the next opening brace....
- (when (and (= arg 0)
- (c-syntactic-re-search-forward "{" nil 'eob))
- (backward-char)
- ;; ... and backward to the function header.
- (c-beginning-of-decl-1)
- t))
-
- ;; Move backward to the opening brace of a function.
- (when (and (> arg 0)
- (eq (setq arg (c-backward-to-nth-BOF-{ arg where)) 0))
-
- ;; Go backward to this function's header.
- (c-beginning-of-decl-1)
-
- (setq pos (point))
- ;; We're now there, modulo comments and whitespace.
- ;; Try to be line oriented; position point at the closest
- ;; preceding boi that isn't inside a comment, but if we hit
- ;; the previous declaration then we use the current point
- ;; instead.
- (while (and (/= (point) (c-point 'boi))
- (c-backward-single-comment)))
- (if (/= (point) (c-point 'boi))
- (goto-char pos)))
-
- (c-keep-region-active)
- (= arg 0))))
+ (paren-state (copy-tree (c-parse-state))) ; This must not share list
+ ; structure with other users of
c-state-cache.
+ (orig-point-min (point-min)) (orig-point-max (point-max))
+ lim ; Position of { which has been widened to.
+ where pos)
+
+ (save-restriction
+ (if (eq c-defun-tactic 'go-outward)
+ (setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace.
+ paren-state orig-point-min orig-point-max)))
+
+ ;; Move back out of any macro/comment/string we happen to be in.
+ (c-beginning-of-macro)
+ (setq pos (c-literal-limits))
+ (if pos (goto-char (car pos)))
+
+ (setq where (c-where-wrt-brace-construct))
+
+ (if (< arg 0)
+ ;; Move forward to the closing brace of a function.
+ (progn
+ (if (memq where '(at-function-end outwith-function))
+ (setq arg (1+ arg)))
+ (if (< arg 0)
+ (c-while-widening-to-decl-block
+ (< (setq arg (- (c-forward-to-nth-EOF-} (- arg) where))) 0)))
+ ;; Move forward to the next opening brace....
+ (when (and (= arg 0)
+ (progn
+ (c-while-widening-to-decl-block
+ (not (c-syntactic-re-search-forward "{" nil 'eob)))
+ (eq (char-before) ?{)))
+ (backward-char)
+ ;; ... and backward to the function header.
+ (c-beginning-of-decl-1)
+ t))
+
+ ;; Move backward to the opening brace of a function, making successively
+ ;; larger portions of the buffer visible as necessary.
+ (when (> arg 0)
+ (c-while-widening-to-decl-block
+ (> (setq arg (c-backward-to-nth-BOF-{ arg where)) 0)))
+
+ (when (eq arg 0)
+ ;; Go backward to this function's header.
+ (c-beginning-of-decl-1)
+
+ (setq pos (point))
+ ;; We're now there, modulo comments and whitespace.
+ ;; Try to be line oriented; position point at the closest
+ ;; preceding boi that isn't inside a comment, but if we hit
+ ;; the previous declaration then we use the current point
+ ;; instead.
+ (while (and (/= (point) (c-point 'boi))
+ (c-backward-single-comment)))
+ (if (/= (point) (c-point 'boi))
+ (goto-char pos)))
+
+ (c-keep-region-active)
+ (= arg 0)))))
(defun c-forward-to-nth-EOF-} (n where)
;; Skip to the closing brace of the Nth function after point. If
@@ -1617,50 +1705,62 @@
(c-save-buffer-state
(beginning-of-defun-function end-of-defun-function
(start (point))
- where paren-state pos)
-
- ;; Move back out of any macro/comment/string we happen to be in.
- (c-beginning-of-macro)
- (setq pos (c-literal-limits))
- (if pos (goto-char (car pos)))
-
- (setq where (c-where-wrt-brace-construct))
-
- (if (< arg 0)
- ;; Move backwards to the } of a function
- (progn
- (if (memq where '(at-header outwith-function))
- (setq arg (1+ arg)))
- (if (< arg 0)
- (setq arg (c-backward-to-nth-BOF-{ (- arg) where)))
- (if (= arg 0)
- (c-syntactic-skip-backward "^}")))
-
- ;; Move forward to the } of a function
- (if (> arg 0)
- (setq arg (c-forward-to-nth-EOF-} arg where))))
-
- ;; Do we need to move forward from the brace to the semicolon?
- (when (eq arg 0)
- (if (c-in-function-trailer-p) ; after "}" of struct/enum, etc.
- (c-syntactic-re-search-forward ";"))
-
- (setq pos (point))
- ;; We're there now, modulo comments and whitespace.
- ;; Try to be line oriented; position point after the next
- ;; newline that isn't inside a comment, but if we hit the
- ;; next declaration then we use the current point instead.
- (while (and (not (bolp))
- (not (looking-at "\\s *$"))
- (c-forward-single-comment)))
- (cond ((bolp))
- ((looking-at "\\s *$")
- (forward-line 1))
- (t
- (goto-char pos))))
-
- (c-keep-region-active)
- (= arg 0)))
+ (paren-state (copy-tree (c-parse-state))) ; This must not share list
+ ; structure with other users of c-state-cache.
+ (orig-point-min (point-min)) (orig-point-max (point-max))
+ lim
+ where pos)
+ (save-restriction
+ (if (eq c-defun-tactic 'go-outward)
+ (setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace
+ paren-state orig-point-min orig-point-max)))
+
+ ;; Move back out of any macro/comment/string we happen to be in.
+ (c-beginning-of-macro)
+ (setq pos (c-literal-limits))
+ (if pos (goto-char (car pos)))
+
+ (setq where (c-where-wrt-brace-construct))
+
+ (if (< arg 0)
+ ;; Move backwards to the } of a function
+ (progn
+ (if (memq where '(at-header outwith-function))
+ (setq arg (1+ arg)))
+ (if (< arg 0)
+ (c-while-widening-to-decl-block
+ (< (setq arg (- (c-backward-to-nth-BOF-{ (- arg) where))) 0)))
+ (if (= arg 0)
+ (c-while-widening-to-decl-block
+ (progn (c-syntactic-skip-backward "^}")
+ (not (eq (char-before) ?}))))))
+
+ ;; Move forward to the } of a function
+ (if (> arg 0)
+ (c-while-widening-to-decl-block
+ (> (setq arg (c-forward-to-nth-EOF-} arg where)) 0))))
+
+ ;; Do we need to move forward from the brace to the semicolon?
+ (when (eq arg 0)
+ (if (c-in-function-trailer-p) ; after "}" of struct/enum, etc.
+ (c-syntactic-re-search-forward ";"))
+
+ (setq pos (point))
+ ;; We're there now, modulo comments and whitespace.
+ ;; Try to be line oriented; position point after the next
+ ;; newline that isn't inside a comment, but if we hit the
+ ;; next declaration then we use the current point instead.
+ (while (and (not (bolp))
+ (not (looking-at "\\s *$"))
+ (c-forward-single-comment)))
+ (cond ((bolp))
+ ((looking-at "\\s *$")
+ (forward-line 1))
+ (t
+ (goto-char pos))))
+
+ (c-keep-region-active)
+ (= arg 0))))
(defun c-defun-name ()
"Return the name of the current defun, or NIL if there isn't one.
@@ -1746,6 +1846,11 @@
;;
;; This function might do hidden buffer changes.
(save-excursion
+ (save-restriction
+ (when (eq c-defun-tactic 'go-outward)
+ (c-narrow-to-most-enclosing-decl-block t) ; e.g. class, namespace
+ (or (save-restriction
+ (c-narrow-to-most-enclosing-decl-block nil)
;; Note: Some code duplication in `c-beginning-of-defun' and
;; `c-end-of-defun'.
@@ -1755,11 +1860,12 @@
lim pos end-pos)
(unless (c-safe
(goto-char (c-least-enclosing-brace paren-state))
- ;; If we moved to the outermost enclosing paren then we
- ;; can use c-safe-position to set the limit. Can't do
- ;; that otherwise since the earlier paren pair on
- ;; paren-state might very well be part of the
- ;; declaration we should go to.
+ ;; If we moved to the outermost enclosing paren
+ ;; then we can use c-safe-position to set the
+ ;; limit. Can't do that otherwise since the
+ ;; earlier paren pair on paren-state might very
+ ;; well be part of the declaration we should go
+ ;; to.
(setq lim (c-safe-position (point) paren-state))
t)
;; At top level. Make sure we aren't inside a literal.
@@ -1843,8 +1949,12 @@
(forward-line 1)
(point))
(t
- pos)))))
- ))))
+ pos))))))))
+ (and (not near)
+ (goto-char (point-min))
+ (c-forward-decl-or-cast-1 -1 nil nil)
+ (eq (char-after) ?\{)
+ (cons (point-min) (point-max))))))))
(defun c-mark-function ()
"Put mark at end of the current top-level declaration or macro, point at
beginning.
=== modified file 'lisp/progmodes/cc-engine.el'
--- a/lisp/progmodes/cc-engine.el 2011-10-27 20:34:23 +0000
+++ b/lisp/progmodes/cc-engine.el 2011-10-28 14:35:39 +0000
@@ -705,7 +705,7 @@
;; The last position where a label is possible provided the
;; statement started there. It's nil as long as no invalid
;; label content has been found (according to
- ;; `c-nonlabel-token-key'. It's `start' if no valid label
+ ;; `c-nonlabel-token-key'). It's `start' if no valid label
;; content was found in the label. Note that we might still
;; regard it a label if it starts with `c-label-kwds'.
label-good-pos
@@ -1035,7 +1035,12 @@
;; (including a case label) or something like C++'s "public:"?
;; A case label might use an expression rather than a token.
(setq after-case:-pos (or tok start))
- (if (looking-at c-nonlabel-token-key) ; e.g. "while" or "'a'"
+ (if (or (looking-at c-nonlabel-token-key) ; e.g. "while" or
"'a'"
+ ;; Catch C++'s inheritance construct "class foo :
bar".
+ (save-excursion
+ (and
+ (c-safe (c-backward-sexp) t)
+ (looking-at c-nonlabel-token-2-key))))
(setq c-maybe-labelp nil)
(if after-labels-pos ; Have we already encountered a label?
(if (not last-label-pos)
@@ -8062,6 +8067,29 @@
(back-to-indentation)
(vector (point) open-paren-pos))))))
+(defmacro c-pull-open-brace (ps)
+ ;; Pull the next open brace from PS (which has the form of paren-state),
+ ;; skipping over any brace pairs. Returns NIL when PS is exhausted.
+ `(progn
+ (while (consp (car ,ps))
+ (setq ,ps (cdr ,ps)))
+ (prog1 (car ,ps)
+ (setq ,ps (cdr ,ps)))))
+
+(defun c-most-enclosing-decl-block (paren-state)
+ ;; Return the buffer position of the most enclosing decl-block brace (in the
+ ;; sense of c-looking-at-decl-block) in the PAREN-STATE structure, or nil if
+ ;; none was found.
+ (let* ((open-brace (c-pull-open-brace paren-state))
+ (next-open-brace (c-pull-open-brace paren-state)))
+ (while (and open-brace
+ (save-excursion
+ (goto-char open-brace)
+ (not (c-looking-at-decl-block next-open-brace nil))))
+ (setq open-brace next-open-brace
+ next-open-brace (c-pull-open-brace paren-state)))
+ open-brace))
+
(defun c-inside-bracelist-p (containing-sexp paren-state)
;; return the buffer position of the beginning of the brace list
;; statement if we're inside a brace list, otherwise return nil.
=== modified file 'lisp/progmodes/cc-vars.el'
--- a/lisp/progmodes/cc-vars.el 2011-10-27 20:34:23 +0000
+++ b/lisp/progmodes/cc-vars.el 2011-10-28 14:35:39 +0000
@@ -340,6 +340,20 @@
:group 'c)
(put 'c-syntactic-indentation-in-macros 'safe-local-variable 'booleanp)
+(defcustom c-defun-tactic 'go-outward
+ "*Whether functions are recognized inside, e.g., a class.
+This is used by `c-beginning-of-defun' and like functions.
+
+Its value is one of:
+ t -- Functions are recognized only at the top level.
+ go-outward -- Nested functions are also recognized. Should a function
+ command hit the beginning/end of a nested scope, it will
+ carry on at the less nested level."
+ :type '(radio
+ (const :tag "Functions are at the top-level" t)
+ (const :tag "Functions are also recognized inside declaration scopes"
go-outward))
+ :group 'c)
+
(defcustom-c-stylevar c-comment-only-line-offset 0
"*Extra offset for line which contains only the start of a comment.
Can contain an integer or a cons cell of the form:
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] /srv/bzr/emacs/trunk r106221: DTRT for c-beginning/end-of-defun in nested declaration scopes.,
Alan Mackenzie <=