aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2011-10-28 14:34:39 +0000
committerAlan Mackenzie2011-10-28 14:34:39 +0000
commit020716e178cdae443a3630c4307023cb3fc4c350 (patch)
tree47ed6164c0d4a262cce8d41cef7d88592fe69fa4
parent86c606818495d9411fd5d6b1477f9a097eb18020 (diff)
downloademacs-020716e178cdae443a3630c4307023cb3fc4c350.tar.gz
emacs-020716e178cdae443a3630c4307023cb3fc4c350.zip
DTRT for c-beginning/end-of-defun in nested declaration scopes.
-rw-r--r--doc/misc/cc-mode.texi11
-rw-r--r--lisp/progmodes/cc-cmds.el284
-rw-r--r--lisp/progmodes/cc-engine.el32
-rw-r--r--lisp/progmodes/cc-vars.el14
4 files changed, 252 insertions, 89 deletions
diff --git a/doc/misc/cc-mode.texi b/doc/misc/cc-mode.texi
index a9339162666..8818904982b 100644
--- a/doc/misc/cc-mode.texi
+++ b/doc/misc/cc-mode.texi
@@ -882,6 +882,8 @@ lines.
882@itemx @kbd{C-M-e} (@code{c-end-of-defun}) 882@itemx @kbd{C-M-e} (@code{c-end-of-defun})
883@findex c-beginning-of-defun 883@findex c-beginning-of-defun
884@findex c-end-of-defun 884@findex c-end-of-defun
885@vindex c-defun-tactic
886@vindex defun-tactic (c-)
885 887
886Move to the beginning or end of the current or next function. Other 888Move to the beginning or end of the current or next function. Other
887constructs (such as a structs or classes) which have a brace block 889constructs (such as a structs or classes) which have a brace block
@@ -895,6 +897,15 @@ commands try to leave point at the beginning of a line near the actual
895start or end of the function. This occasionally causes point not to 897start or end of the function. This occasionally causes point not to
896move at all. 898move at all.
897 899
900By default, these commands will recognize functions contained within a
901@dfn{declaration scope} such as a C++ @code{class} or @code{namespace}
902construct, should the point start inside it. If @ccmode fails to find
903function beginnings or ends inside the current declaration scope, it
904will search the enclosing scopes. If you want @ccmode to recognize
905functions only at the top level@footnote{this was @ccmode{}'s
906behaviour prior to version 5.32.}, set @code{c-defun-tatic} to
907@code{t}.
908
898These functions are analogous to the Emacs built-in commands 909These functions are analogous to the Emacs built-in commands
899@code{beginning-of-defun} and @code{end-of-defun}, except they 910@code{beginning-of-defun} and @code{end-of-defun}, except they
900eliminate the constraint that the top-level opening brace of the defun 911eliminate the constraint that the top-level opening brace of the defun
diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index 0f873e678c3..e59fdc16af7 100644
--- a/lisp/progmodes/cc-cmds.el
+++ b/lisp/progmodes/cc-cmds.el
@@ -1485,6 +1485,78 @@ No indentation or other \"electric\" behavior is performed."
1485 (setq n (1- n)))) 1485 (setq n (1- n))))
1486 n) 1486 n)
1487 1487
1488(defun c-narrow-to-most-enclosing-decl-block (&optional inclusive)
1489 ;; If we are inside a decl-block (in the sense of c-looking-at-decl-block),
1490 ;; i.e. something like namespace{} or extern{}, narrow to the insides of
1491 ;; that block (NOT including the enclosing braces) if INCLUSIVE is nil,
1492 ;; otherwise include the braces. If the closing brace is missing,
1493 ;; (point-max) is used instead.
1494 (let ((paren-state (c-parse-state))
1495 encl-decl)
1496 (setq encl-decl (and paren-state (c-most-enclosing-decl-block paren-state)))
1497 (if encl-decl
1498 (save-excursion
1499 (narrow-to-region
1500 (if inclusive
1501 (progn (goto-char encl-decl)
1502 (c-beginning-of-decl-1)
1503 (point))
1504 (1+ encl-decl))
1505 (progn
1506 (goto-char encl-decl)
1507 (or (c-safe (forward-list)
1508 (if inclusive
1509 (point)
1510 (1- (point))))
1511 (point-max))))))))
1512
1513(defun c-widen-to-enclosing-decl-scope (paren-state orig-point-min orig-point-max)
1514 ;; Narrow the buffer to the innermost declaration scope (e.g. a class, a
1515 ;; namespace or the "whole buffer") recorded in PAREN-STATE, the bounding
1516 ;; braces NOT being included in the resulting region. On no account may the
1517 ;; final region exceed that bounded by ORIG-POINT-MIN, ORIG-POINT-MAX.
1518 ;; PAREN-STATE is a list of buffer positions in the style of
1519 ;; (c-parse-state), one of which will be that of the desired opening brace,
1520 ;; if there is one.
1521 ;;
1522 ;; Return the position of the enclosing opening brace, or nil
1523 (let (encl-decl) ; putative position of decl-scope's opening brace.
1524 (save-restriction
1525 (narrow-to-region orig-point-min orig-point-max)
1526 (setq encl-decl (and paren-state
1527 (c-most-enclosing-decl-block paren-state))))
1528 (if encl-decl
1529 (progn
1530 (widen)
1531 (narrow-to-region (1+ encl-decl)
1532 (save-excursion
1533 (goto-char encl-decl)
1534 (or (c-safe (forward-list)
1535 (1- (point)))
1536 orig-point-max)))
1537 encl-decl)
1538 (narrow-to-region orig-point-min orig-point-max)
1539 nil)))
1540
1541(eval-and-compile
1542 (defmacro c-while-widening-to-decl-block (condition)
1543 ;; Repeatedly evaluate CONDITION until it returns nil. After each
1544 ;; evaluation, if `c-defun-tactic' is set appropriately, widen to innards
1545 ;; of the next enclosing declaration block (e.g. namespace, class), or the
1546 ;; buffer's original restriction.
1547 ;;
1548 ;; This is a very special purpose macro, which assumes the existence of
1549 ;; several variables. It is for use only in c-beginning-of-defun and
1550 ;; c-end-of-defun.
1551 `(while
1552 (and ,condition
1553 (eq c-defun-tactic 'go-outward)
1554 lim)
1555 (setq paren-state (c-whack-state-after lim paren-state))
1556 (setq lim (c-widen-to-enclosing-decl-scope
1557 paren-state orig-point-min orig-point-max))
1558 (setq where 'in-block))))
1559
1488(defun c-beginning-of-defun (&optional arg) 1560(defun c-beginning-of-defun (&optional arg)
1489 "Move backward to the beginning of a defun. 1561 "Move backward to the beginning of a defun.
1490Every top level declaration that contains a brace paren block is 1562Every top level declaration that contains a brace paren block is
@@ -1509,50 +1581,66 @@ defun."
1509 (c-save-buffer-state 1581 (c-save-buffer-state
1510 (beginning-of-defun-function end-of-defun-function 1582 (beginning-of-defun-function end-of-defun-function
1511 (start (point)) 1583 (start (point))
1512 where paren-state pos) 1584 (paren-state (copy-tree (c-parse-state))) ; This must not share list
1585 ; structure with other users of c-state-cache.
1586 (orig-point-min (point-min)) (orig-point-max (point-max))
1587 lim ; Position of { which has been widened to.
1588 where pos)
1513 1589
1514 ;; Move back out of any macro/comment/string we happen to be in. 1590 (save-restriction
1515 (c-beginning-of-macro) 1591 (if (eq c-defun-tactic 'go-outward)
1516 (setq pos (c-literal-limits)) 1592 (setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace.
1517 (if pos (goto-char (car pos))) 1593 paren-state orig-point-min orig-point-max)))
1518
1519 (setq where (c-where-wrt-brace-construct))
1520
1521 (if (< arg 0)
1522 ;; Move forward to the closing brace of a function.
1523 (progn
1524 (if (memq where '(at-function-end outwith-function))
1525 (setq arg (1+ arg)))
1526 (if (< arg 0)
1527 (setq arg (c-forward-to-nth-EOF-} (- arg) where)))
1528 ;; Move forward to the next opening brace....
1529 (when (and (= arg 0)
1530 (c-syntactic-re-search-forward "{" nil 'eob))
1531 (backward-char)
1532 ;; ... and backward to the function header.
1533 (c-beginning-of-decl-1)
1534 t))
1535
1536 ;; Move backward to the opening brace of a function.
1537 (when (and (> arg 0)
1538 (eq (setq arg (c-backward-to-nth-BOF-{ arg where)) 0))
1539 1594
1540 ;; Go backward to this function's header. 1595 ;; Move back out of any macro/comment/string we happen to be in.
1541 (c-beginning-of-decl-1) 1596 (c-beginning-of-macro)
1597 (setq pos (c-literal-limits))
1598 (if pos (goto-char (car pos)))
1542 1599
1543 (setq pos (point)) 1600 (setq where (c-where-wrt-brace-construct))
1544 ;; We're now there, modulo comments and whitespace.
1545 ;; Try to be line oriented; position point at the closest
1546 ;; preceding boi that isn't inside a comment, but if we hit
1547 ;; the previous declaration then we use the current point
1548 ;; instead.
1549 (while (and (/= (point) (c-point 'boi))
1550 (c-backward-single-comment)))
1551 (if (/= (point) (c-point 'boi))
1552 (goto-char pos)))
1553 1601
1554 (c-keep-region-active) 1602 (if (< arg 0)
1555 (= arg 0)))) 1603 ;; Move forward to the closing brace of a function.
1604 (progn
1605 (if (memq where '(at-function-end outwith-function))
1606 (setq arg (1+ arg)))
1607 (if (< arg 0)
1608 (c-while-widening-to-decl-block
1609 (< (setq arg (- (c-forward-to-nth-EOF-} (- arg) where))) 0)))
1610 ;; Move forward to the next opening brace....
1611 (when (and (= arg 0)
1612 (progn
1613 (c-while-widening-to-decl-block
1614 (not (c-syntactic-re-search-forward "{" nil 'eob)))
1615 (eq (char-before) ?{)))
1616 (backward-char)
1617 ;; ... and backward to the function header.
1618 (c-beginning-of-decl-1)
1619 t))
1620
1621 ;; Move backward to the opening brace of a function, making successively
1622 ;; larger portions of the buffer visible as necessary.
1623 (when (> arg 0)
1624 (c-while-widening-to-decl-block
1625 (> (setq arg (c-backward-to-nth-BOF-{ arg where)) 0)))
1626
1627 (when (eq arg 0)
1628 ;; Go backward to this function's header.
1629 (c-beginning-of-decl-1)
1630
1631 (setq pos (point))
1632 ;; We're now there, modulo comments and whitespace.
1633 ;; Try to be line oriented; position point at the closest
1634 ;; preceding boi that isn't inside a comment, but if we hit
1635 ;; the previous declaration then we use the current point
1636 ;; instead.
1637 (while (and (/= (point) (c-point 'boi))
1638 (c-backward-single-comment)))
1639 (if (/= (point) (c-point 'boi))
1640 (goto-char pos)))
1641
1642 (c-keep-region-active)
1643 (= arg 0)))))
1556 1644
1557(defun c-forward-to-nth-EOF-} (n where) 1645(defun c-forward-to-nth-EOF-} (n where)
1558 ;; Skip to the closing brace of the Nth function after point. If 1646 ;; Skip to the closing brace of the Nth function after point. If
@@ -1617,50 +1705,62 @@ the open-parenthesis that starts a defun; see `beginning-of-defun'."
1617 (c-save-buffer-state 1705 (c-save-buffer-state
1618 (beginning-of-defun-function end-of-defun-function 1706 (beginning-of-defun-function end-of-defun-function
1619 (start (point)) 1707 (start (point))
1620 where paren-state pos) 1708 (paren-state (copy-tree (c-parse-state))) ; This must not share list
1709 ; structure with other users of c-state-cache.
1710 (orig-point-min (point-min)) (orig-point-max (point-max))
1711 lim
1712 where pos)
1713 (save-restriction
1714 (if (eq c-defun-tactic 'go-outward)
1715 (setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace
1716 paren-state orig-point-min orig-point-max)))
1621 1717
1622 ;; Move back out of any macro/comment/string we happen to be in. 1718 ;; Move back out of any macro/comment/string we happen to be in.
1623 (c-beginning-of-macro) 1719 (c-beginning-of-macro)
1624 (setq pos (c-literal-limits)) 1720 (setq pos (c-literal-limits))
1625 (if pos (goto-char (car pos))) 1721 (if pos (goto-char (car pos)))
1626 1722
1627 (setq where (c-where-wrt-brace-construct)) 1723 (setq where (c-where-wrt-brace-construct))
1628 1724
1629 (if (< arg 0) 1725 (if (< arg 0)
1630 ;; Move backwards to the } of a function 1726 ;; Move backwards to the } of a function
1631 (progn 1727 (progn
1632 (if (memq where '(at-header outwith-function)) 1728 (if (memq where '(at-header outwith-function))
1633 (setq arg (1+ arg))) 1729 (setq arg (1+ arg)))
1634 (if (< arg 0) 1730 (if (< arg 0)
1635 (setq arg (c-backward-to-nth-BOF-{ (- arg) where))) 1731 (c-while-widening-to-decl-block
1636 (if (= arg 0) 1732 (< (setq arg (- (c-backward-to-nth-BOF-{ (- arg) where))) 0)))
1637 (c-syntactic-skip-backward "^}"))) 1733 (if (= arg 0)
1638 1734 (c-while-widening-to-decl-block
1639 ;; Move forward to the } of a function 1735 (progn (c-syntactic-skip-backward "^}")
1640 (if (> arg 0) 1736 (not (eq (char-before) ?}))))))
1641 (setq arg (c-forward-to-nth-EOF-} arg where)))) 1737
1642 1738 ;; Move forward to the } of a function
1643 ;; Do we need to move forward from the brace to the semicolon? 1739 (if (> arg 0)
1644 (when (eq arg 0) 1740 (c-while-widening-to-decl-block
1645 (if (c-in-function-trailer-p) ; after "}" of struct/enum, etc. 1741 (> (setq arg (c-forward-to-nth-EOF-} arg where)) 0))))
1646 (c-syntactic-re-search-forward ";")) 1742
1647 1743 ;; Do we need to move forward from the brace to the semicolon?
1648 (setq pos (point)) 1744 (when (eq arg 0)
1649 ;; We're there now, modulo comments and whitespace. 1745 (if (c-in-function-trailer-p) ; after "}" of struct/enum, etc.
1650 ;; Try to be line oriented; position point after the next 1746 (c-syntactic-re-search-forward ";"))
1651 ;; newline that isn't inside a comment, but if we hit the
1652 ;; next declaration then we use the current point instead.
1653 (while (and (not (bolp))
1654 (not (looking-at "\\s *$"))
1655 (c-forward-single-comment)))
1656 (cond ((bolp))
1657 ((looking-at "\\s *$")
1658 (forward-line 1))
1659 (t
1660 (goto-char pos))))
1661 1747
1662 (c-keep-region-active) 1748 (setq pos (point))
1663 (= arg 0))) 1749 ;; We're there now, modulo comments and whitespace.
1750 ;; Try to be line oriented; position point after the next
1751 ;; newline that isn't inside a comment, but if we hit the
1752 ;; next declaration then we use the current point instead.
1753 (while (and (not (bolp))
1754 (not (looking-at "\\s *$"))
1755 (c-forward-single-comment)))
1756 (cond ((bolp))
1757 ((looking-at "\\s *$")
1758 (forward-line 1))
1759 (t
1760 (goto-char pos))))
1761
1762 (c-keep-region-active)
1763 (= arg 0))))
1664 1764
1665(defun c-defun-name () 1765(defun c-defun-name ()
1666 "Return the name of the current defun, or NIL if there isn't one. 1766 "Return the name of the current defun, or NIL if there isn't one.
@@ -1746,6 +1846,11 @@ with a brace block."
1746 ;; 1846 ;;
1747 ;; This function might do hidden buffer changes. 1847 ;; This function might do hidden buffer changes.
1748 (save-excursion 1848 (save-excursion
1849 (save-restriction
1850 (when (eq c-defun-tactic 'go-outward)
1851 (c-narrow-to-most-enclosing-decl-block t) ; e.g. class, namespace
1852 (or (save-restriction
1853 (c-narrow-to-most-enclosing-decl-block nil)
1749 1854
1750 ;; Note: Some code duplication in `c-beginning-of-defun' and 1855 ;; Note: Some code duplication in `c-beginning-of-defun' and
1751 ;; `c-end-of-defun'. 1856 ;; `c-end-of-defun'.
@@ -1755,11 +1860,12 @@ with a brace block."
1755 lim pos end-pos) 1860 lim pos end-pos)
1756 (unless (c-safe 1861 (unless (c-safe
1757 (goto-char (c-least-enclosing-brace paren-state)) 1862 (goto-char (c-least-enclosing-brace paren-state))
1758 ;; If we moved to the outermost enclosing paren then we 1863 ;; If we moved to the outermost enclosing paren
1759 ;; can use c-safe-position to set the limit. Can't do 1864 ;; then we can use c-safe-position to set the
1760 ;; that otherwise since the earlier paren pair on 1865 ;; limit. Can't do that otherwise since the
1761 ;; paren-state might very well be part of the 1866 ;; earlier paren pair on paren-state might very
1762 ;; declaration we should go to. 1867 ;; well be part of the declaration we should go
1868 ;; to.
1763 (setq lim (c-safe-position (point) paren-state)) 1869 (setq lim (c-safe-position (point) paren-state))
1764 t) 1870 t)
1765 ;; At top level. Make sure we aren't inside a literal. 1871 ;; At top level. Make sure we aren't inside a literal.
@@ -1843,8 +1949,12 @@ with a brace block."
1843 (forward-line 1) 1949 (forward-line 1)
1844 (point)) 1950 (point))
1845 (t 1951 (t
1846 pos))))) 1952 pos))))))))
1847 )))) 1953 (and (not near)
1954 (goto-char (point-min))
1955 (c-forward-decl-or-cast-1 -1 nil nil)
1956 (eq (char-after) ?\{)
1957 (cons (point-min) (point-max))))))))
1848 1958
1849(defun c-mark-function () 1959(defun c-mark-function ()
1850 "Put mark at end of the current top-level declaration or macro, point at beginning. 1960 "Put mark at end of the current top-level declaration or macro, point at beginning.
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index b2c548847c3..bc42e1032ab 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -705,7 +705,7 @@ comment at the start of cc-engine.el for more info."
705 ;; The last position where a label is possible provided the 705 ;; The last position where a label is possible provided the
706 ;; statement started there. It's nil as long as no invalid 706 ;; statement started there. It's nil as long as no invalid
707 ;; label content has been found (according to 707 ;; label content has been found (according to
708 ;; `c-nonlabel-token-key'. It's `start' if no valid label 708 ;; `c-nonlabel-token-key'). It's `start' if no valid label
709 ;; content was found in the label. Note that we might still 709 ;; content was found in the label. Note that we might still
710 ;; regard it a label if it starts with `c-label-kwds'. 710 ;; regard it a label if it starts with `c-label-kwds'.
711 label-good-pos 711 label-good-pos
@@ -1035,7 +1035,12 @@ comment at the start of cc-engine.el for more info."
1035 ;; (including a case label) or something like C++'s "public:"? 1035 ;; (including a case label) or something like C++'s "public:"?
1036 ;; A case label might use an expression rather than a token. 1036 ;; A case label might use an expression rather than a token.
1037 (setq after-case:-pos (or tok start)) 1037 (setq after-case:-pos (or tok start))
1038 (if (looking-at c-nonlabel-token-key) ; e.g. "while" or "'a'" 1038 (if (or (looking-at c-nonlabel-token-key) ; e.g. "while" or "'a'"
1039 ;; Catch C++'s inheritance construct "class foo : bar".
1040 (save-excursion
1041 (and
1042 (c-safe (c-backward-sexp) t)
1043 (looking-at c-nonlabel-token-2-key))))
1039 (setq c-maybe-labelp nil) 1044 (setq c-maybe-labelp nil)
1040 (if after-labels-pos ; Have we already encountered a label? 1045 (if after-labels-pos ; Have we already encountered a label?
1041 (if (not last-label-pos) 1046 (if (not last-label-pos)
@@ -8037,6 +8042,29 @@ comment at the start of cc-engine.el for more info."
8037 (back-to-indentation) 8042 (back-to-indentation)
8038 (vector (point) open-paren-pos)))))) 8043 (vector (point) open-paren-pos))))))
8039 8044
8045(defmacro c-pull-open-brace (ps)
8046 ;; Pull the next open brace from PS (which has the form of paren-state),
8047 ;; skipping over any brace pairs. Returns NIL when PS is exhausted.
8048 `(progn
8049 (while (consp (car ,ps))
8050 (setq ,ps (cdr ,ps)))
8051 (prog1 (car ,ps)
8052 (setq ,ps (cdr ,ps)))))
8053
8054(defun c-most-enclosing-decl-block (paren-state)
8055 ;; Return the buffer position of the most enclosing decl-block brace (in the
8056 ;; sense of c-looking-at-decl-block) in the PAREN-STATE structure, or nil if
8057 ;; none was found.
8058 (let* ((open-brace (c-pull-open-brace paren-state))
8059 (next-open-brace (c-pull-open-brace paren-state)))
8060 (while (and open-brace
8061 (save-excursion
8062 (goto-char open-brace)
8063 (not (c-looking-at-decl-block next-open-brace nil))))
8064 (setq open-brace next-open-brace
8065 next-open-brace (c-pull-open-brace paren-state)))
8066 open-brace))
8067
8040(defun c-inside-bracelist-p (containing-sexp paren-state) 8068(defun c-inside-bracelist-p (containing-sexp paren-state)
8041 ;; return the buffer position of the beginning of the brace list 8069 ;; return the buffer position of the beginning of the brace list
8042 ;; statement if we're inside a brace list, otherwise return nil. 8070 ;; statement if we're inside a brace list, otherwise return nil.
diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el
index 58dc1737c5a..769bf63f63c 100644
--- a/lisp/progmodes/cc-vars.el
+++ b/lisp/progmodes/cc-vars.el
@@ -340,6 +340,20 @@ better with the \"do { ... } while \(0)\" trick)."
340 :group 'c) 340 :group 'c)
341(put 'c-syntactic-indentation-in-macros 'safe-local-variable 'booleanp) 341(put 'c-syntactic-indentation-in-macros 'safe-local-variable 'booleanp)
342 342
343(defcustom c-defun-tactic 'go-outward
344 "*Whether functions are recognized inside, e.g., a class.
345This is used by `c-beginning-of-defun' and like functions.
346
347Its value is one of:
348 t -- Functions are recognized only at the top level.
349 go-outward -- Nested functions are also recognized. Should a function
350 command hit the beginning/end of a nested scope, it will
351 carry on at the less nested level."
352 :type '(radio
353 (const :tag "Functions are at the top-level" t)
354 (const :tag "Functions are also recognized inside declaration scopes" go-outward))
355 :group 'c)
356
343(defcustom-c-stylevar c-comment-only-line-offset 0 357(defcustom-c-stylevar c-comment-only-line-offset 0
344 "*Extra offset for line which contains only the start of a comment. 358 "*Extra offset for line which contains only the start of a comment.
345Can contain an integer or a cons cell of the form: 359Can contain an integer or a cons cell of the form: