aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorAlan Mackenzie2011-10-28 14:34:39 +0000
committerAlan Mackenzie2011-10-28 14:34:39 +0000
commit020716e178cdae443a3630c4307023cb3fc4c350 (patch)
tree47ed6164c0d4a262cce8d41cef7d88592fe69fa4 /lisp
parent86c606818495d9411fd5d6b1477f9a097eb18020 (diff)
downloademacs-020716e178cdae443a3630c4307023cb3fc4c350.tar.gz
emacs-020716e178cdae443a3630c4307023cb3fc4c350.zip
DTRT for c-beginning/end-of-defun in nested declaration scopes.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/progmodes/cc-cmds.el284
-rw-r--r--lisp/progmodes/cc-engine.el32
-rw-r--r--lisp/progmodes/cc-vars.el14
3 files changed, 241 insertions, 89 deletions
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: