diff options
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 114 |
1 files changed, 32 insertions, 82 deletions
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." |
| 3047 | Optional Argument ROOT must be non-nil when the node being | ||
| 3048 | processed 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. |
| 3066 | Arguments MIN-INDENT PREV-INDENT NUM-CHILDREN and TREE are | 3057 | Arguments MIN-INDENT PREV-INDENT and TREE are internal and should |
| 3067 | internal and should not be passed explicitly unless you know what | 3058 | not be passed explicitly unless you know what you are doing." |
| 3068 | you 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. |