aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabián Ezequiel Gallina2013-08-13 13:36:32 -0300
committerFabián Ezequiel Gallina2013-08-13 13:36:32 -0300
commitad75644970a5deccb1d40465e20087f5806ed3df (patch)
tree8dc0ba2c980d3f6a3abc98918912b71c7141f363
parent866c710eeb75ce47767442952028d79b76c1606a (diff)
downloademacs-ad75644970a5deccb1d40465e20087f5806ed3df.tar.gz
emacs-ad75644970a5deccb1d40465e20087f5806ed3df.zip
* lisp/progmodes/python.el (python-imenu--build-tree)
(python-imenu--put-parent): Simplify and Fix (GH bug 146). * test/automated/python-tests.el (python-imenu-create-index-4) (python-imenu-create-flat-index-2): New tests.
-rw-r--r--lisp/ChangeLog5
-rw-r--r--lisp/progmodes/python.el114
-rw-r--r--test/ChangeLog5
-rw-r--r--test/automated/python-tests.el52
4 files changed, 94 insertions, 82 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 0c8791d8af7..11e5e913398 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,8 @@
12013-08-13 Fabián Ezequiel Gallina <fgallina@gnu.org>
2
3 * progmodes/python.el (python-imenu--build-tree)
4 (python-imenu--put-parent): Simplify and Fix (GH bug 146).
5
12013-08-13 Xue Fuqiao <xfq.free@gmail.com> 62013-08-13 Xue Fuqiao <xfq.free@gmail.com>
2 7
3 * simple.el (backward-word): Mention the optional argument. 8 * simple.el (backward-word): Mention the optional argument.
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 62870f9085b..70c2e5dec53 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -3042,32 +3042,22 @@ It must be a function with two arguments: TYPE and NAME.")
3042 "*class definition*" 3042 "*class definition*"
3043 "*function definition*")) 3043 "*function definition*"))
3044 3044
3045(defun python-imenu--put-parent (type name pos num-children tree &optional root) 3045(defun python-imenu--put-parent (type name pos tree)
3046 "Add the parent with TYPE, NAME, POS and NUM-CHILDREN to TREE. 3046 "Add the parent with TYPE, NAME and POS to TREE."
3047Optional Argument ROOT must be non-nil when the node being
3048processed is the root of the TREE."
3049 (let ((label 3047 (let ((label
3050 (funcall python-imenu-format-item-label-function type name)) 3048 (funcall python-imenu-format-item-label-function type name))
3051 (jump-label 3049 (jump-label
3052 (funcall python-imenu-format-parent-item-jump-label-function type name))) 3050 (funcall python-imenu-format-parent-item-jump-label-function type name)))
3053 (if root 3051 (if (not tree)
3054 ;; This is the root, everything is a children. 3052 (cons label pos)
3055 (cons label (cons (cons jump-label pos) tree)) 3053 (cons label (cons (cons jump-label pos) tree)))))
3056 ;; This is node a which may contain some children.
3057 (cons
3058 (cons label (cons (cons jump-label pos)
3059 ;; Append all the children
3060 (python-util-popn tree num-children)))
3061 ;; All previous non-children nodes.
3062 (nthcdr num-children tree)))))
3063 3054
3064(defun python-imenu--build-tree (&optional min-indent prev-indent num-children tree) 3055(defun python-imenu--build-tree (&optional min-indent prev-indent tree)
3065 "Recursively build the tree of nested definitions of a node. 3056 "Recursively build the tree of nested definitions of a node.
3066Arguments MIN-INDENT PREV-INDENT NUM-CHILDREN and TREE are 3057Arguments MIN-INDENT PREV-INDENT and TREE are internal and should
3067internal and should not be passed explicitly unless you know what 3058not be passed explicitly unless you know what you are doing."
3068you are doing." 3059 (setq min-indent (or min-indent 0)
3069 (setq num-children (or num-children 0) 3060 prev-indent (or prev-indent python-indent-offset))
3070 min-indent (or min-indent 0))
3071 (let* ((pos (python-nav-backward-defun)) 3061 (let* ((pos (python-nav-backward-defun))
3072 (type) 3062 (type)
3073 (name (when (and pos (looking-at python-nav-beginning-of-defun-regexp)) 3063 (name (when (and pos (looking-at python-nav-beginning-of-defun-regexp))
@@ -3076,73 +3066,33 @@ you are doing."
3076 (cadr split)))) 3066 (cadr split))))
3077 (label (when name 3067 (label (when name
3078 (funcall python-imenu-format-item-label-function type name))) 3068 (funcall python-imenu-format-item-label-function type name)))
3079 (indent (current-indentation))) 3069 (indent (current-indentation))
3070 (children-indent-limit (+ python-indent-offset min-indent)))
3080 (cond ((not pos) 3071 (cond ((not pos)
3081 ;; No defun found, nothing to add. 3072 ;; Nothing found, probably near to bobp.
3082 tree) 3073 nil)
3083 ((equal indent 0) 3074 ((<= indent min-indent)
3084 (if (> num-children 0) 3075 ;; The current indentation points that this is a parent
3085 ;; Append it as the parent of everything collected to 3076 ;; node, add it to the tree and stop recursing.
3086 ;; this point. 3077 (python-imenu--put-parent type name pos tree))
3087 (python-imenu--put-parent type name pos num-children tree t)
3088 ;; There are no children, this is a lonely defun.
3089 (cons label pos)))
3090 ((equal min-indent indent)
3091 ;; Stop collecting nodes after moving to a position with
3092 ;; indentation equaling min-indent. This is specially
3093 ;; useful for navigating nested definitions recursively.
3094 (if (> num-children 0)
3095 tree
3096 ;; When there are no children, the collected tree is a
3097 ;; single node intended to be added in the list of defuns
3098 ;; of its parent.
3099 (car tree)))
3100 (t 3078 (t
3101 (python-imenu--build-tree 3079 (python-imenu--build-tree
3102 min-indent 3080 min-indent
3103 indent 3081 indent
3104 ;; Add another children, either when this is the 3082 (if (<= indent children-indent-limit)
3105 ;; first call or when indentation is 3083 ;; This lays within the children indent offset range,
3106 ;; less-or-equal than previous. And do not 3084 ;; so it's a normal children of its parent (i.e., not
3107 ;; discard the number of children, because the 3085 ;; a children of a children).
3108 ;; way code is scanned, all children are 3086 (cons (cons label pos) tree)
3109 ;; collected until a root node yet to be found 3087 ;; Oh noes, a children of a children?!. Fear not, we
3110 ;; appears. 3088 ;; know how to roll. We recursely parse these by
3111 (if (or (not prev-indent) 3089 ;; swapping prev-indent and min-indent plus adding this
3112 (and 3090 ;; newly found item to a fresh subtree. This works, I
3113 (> indent min-indent) 3091 ;; promise.
3114 (<= indent prev-indent))) 3092 (cons
3115 (1+ num-children) 3093 (python-imenu--build-tree
3116 num-children) 3094 prev-indent indent (list (cons label pos)))
3117 (cond ((not prev-indent) 3095 tree)))))))
3118 ;; First call to the function: append this
3119 ;; defun to the index.
3120 (list (cons label pos)))
3121 ((= indent prev-indent)
3122 ;; Add another defun with the same depth
3123 ;; as the previous.
3124 (cons (cons label pos) tree))
3125 ((and (< indent prev-indent)
3126 (< 0 num-children))
3127 ;; There are children to be appended and
3128 ;; the previous defun had more
3129 ;; indentation, the current one must be a
3130 ;; parent.
3131 (python-imenu--put-parent type name pos num-children tree))
3132 ((> indent prev-indent)
3133 ;; There are children defuns deeper than
3134 ;; current depth. Fear not, we already
3135 ;; know how to treat them.
3136 (cons
3137 (prog1
3138 (python-imenu--build-tree
3139 prev-indent indent 0 (list (cons label pos)))
3140 ;; Adjustment: after scanning backwards
3141 ;; for all deeper children, we need to
3142 ;; continue our scan for a parent from
3143 ;; the current defun we are looking at.
3144 (python-nav-forward-defun))
3145 tree))))))))
3146 3096
3147(defun python-imenu-create-index () 3097(defun python-imenu-create-index ()
3148 "Return tree Imenu alist for the current python buffer. 3098 "Return tree Imenu alist for the current python buffer.
diff --git a/test/ChangeLog b/test/ChangeLog
index 2e4d19e7a36..1d38f2dd429 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,8 @@
12013-08-13 Fabián Ezequiel Gallina <fgallina@gnu.org>
2
3 * automated/python-tests.el (python-imenu-create-index-4)
4 (python-imenu-create-flat-index-2): New tests.
5
12013-08-05 Glenn Morris <rgm@gnu.org> 62013-08-05 Glenn Morris <rgm@gnu.org>
2 7
3 * automated/mule-util.el: New file, with tests extracted from 8 * automated/mule-util.el: New file, with tests extracted from
diff --git a/test/automated/python-tests.el b/test/automated/python-tests.el
index fdae235ad38..ef1c0155ab5 100644
--- a/test/automated/python-tests.el
+++ b/test/automated/python-tests.el
@@ -1792,6 +1792,34 @@ class Foo(object):
1792 (cons "foo2 (def)" (copy-marker 77))))) 1792 (cons "foo2 (def)" (copy-marker 77)))))
1793 (python-imenu-create-index))))) 1793 (python-imenu-create-index)))))
1794 1794
1795(ert-deftest python-imenu-create-index-4 ()
1796 (python-tests-with-temp-buffer
1797 "
1798class Foo(object):
1799 class Bar(object):
1800 def __init__(self):
1801 pass
1802
1803 def __str__(self):
1804 pass
1805
1806 def __init__(self):
1807 pass
1808"
1809 (goto-char (point-max))
1810 (should (equal
1811 (list
1812 (list
1813 "Foo (class)"
1814 (cons "*class definition*" (copy-marker 2))
1815 (list
1816 "Bar (class)"
1817 (cons "*class definition*" (copy-marker 21))
1818 (cons "__init__ (def)" (copy-marker 44))
1819 (cons "__str__ (def)" (copy-marker 90)))
1820 (cons "__init__ (def)" (copy-marker 135))))
1821 (python-imenu-create-index)))))
1822
1795(ert-deftest python-imenu-create-flat-index-1 () 1823(ert-deftest python-imenu-create-flat-index-1 ()
1796 (python-tests-with-temp-buffer 1824 (python-tests-with-temp-buffer
1797 " 1825 "
@@ -1851,6 +1879,30 @@ class Baz(object):
1851 (cons "Baz.Frob.c" (copy-marker 626))) 1879 (cons "Baz.Frob.c" (copy-marker 626)))
1852 (python-imenu-create-flat-index))))) 1880 (python-imenu-create-flat-index)))))
1853 1881
1882(ert-deftest python-imenu-create-flat-index-2 ()
1883 (python-tests-with-temp-buffer
1884 "
1885class Foo(object):
1886 class Bar(object):
1887 def __init__(self):
1888 pass
1889
1890 def __str__(self):
1891 pass
1892
1893 def __init__(self):
1894 pass
1895"
1896 (goto-char (point-max))
1897 (should (equal
1898 (list
1899 (cons "Foo" (copy-marker 2))
1900 (cons "Foo.Bar" (copy-marker 21))
1901 (cons "Foo.Bar.__init__" (copy-marker 44))
1902 (cons "Foo.Bar.__str__" (copy-marker 90))
1903 (cons "Foo.__init__" (copy-marker 135)))
1904 (python-imenu-create-flat-index)))))
1905
1854 1906
1855;;; Misc helpers 1907;;; Misc helpers
1856 1908