aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
authorFabián Ezequiel Gallina2012-07-16 14:18:39 -0300
committerFabián Ezequiel Gallina2012-07-16 14:18:39 -0300
commit758e556a7ab8f61c007e34310ba399a9aaf15362 (patch)
tree88669e3905313e194fc67a63a7b56a5a9f45c2b2 /lisp/progmodes/python.el
parent032d23ab664d571be03f5661034d1962baa4f5ae (diff)
downloademacs-758e556a7ab8f61c007e34310ba399a9aaf15362.tar.gz
emacs-758e556a7ab8f61c007e34310ba399a9aaf15362.zip
* progmodes/python.el: Simplified imenu implementation.
(python-nav-jump-to-defun): Remove command. (python-mode-map): Use `imenu' instead. (python-nav-list-defun-positions-cache) (python-imenu-include-defun-type, python-imenu-make-tree) (python-imenu-subtree-root-label, python-imenu-index-alist): Remove vars. (python-nav-list-defun-positions, python-nav-read-defun) (python-imenu-tree-assoc, python-imenu-make-element-tree) (python-imenu-make-tree, python-imenu-create-index): Remove functions. (python-mode): Update to interact with imenu by setting `imenu-extract-index-name-function' only.
Diffstat (limited to 'lisp/progmodes/python.el')
-rw-r--r--lisp/progmodes/python.el186
1 files changed, 8 insertions, 178 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index fe9faf54046..e0a58d1523e 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -53,8 +53,6 @@
53;; `python-nav-backward-statement', `python-nav-statement-start', 53;; `python-nav-backward-statement', `python-nav-statement-start',
54;; `python-nav-statement-end', `python-nav-block-start' and 54;; `python-nav-statement-end', `python-nav-block-start' and
55;; `python-nav-block-end' are included but no bound to any key. 55;; `python-nav-block-end' are included but no bound to any key.
56;; `python-nav-jump-to-defun' is provided and allows jumping to a
57;; function or class definition quickly in the current buffer.
58 56
59;; Shell interaction: is provided and allows you to execute easily any 57;; Shell interaction: is provided and allows you to execute easily any
60;; block of code of your current buffer in an inferior Python process. 58;; block of code of your current buffer in an inferior Python process.
@@ -168,10 +166,10 @@
168;; might guessed you should run `python-shell-send-buffer' from time 166;; might guessed you should run `python-shell-send-buffer' from time
169;; to time to get better results too. 167;; to time to get better results too.
170 168
171;; imenu: This mode supports imenu. It builds a plain or tree menu 169;; imenu: This mode supports imenu in its most basic form, letting it
172;; depending on the value of `python-imenu-make-tree'. Also you can 170;; build the necessary alist via `imenu-default-create-index-function'
173;; customize if menu items should include its type using 171;; by having set `imenu-extract-index-name-function' to
174;; `python-imenu-include-defun-type'. 172;; `python-info-current-defun'.
175 173
176;; If you used python-mode.el you probably will miss auto-indentation 174;; If you used python-mode.el you probably will miss auto-indentation
177;; when inserting newlines. To achieve the same behavior you have 175;; when inserting newlines. To achieve the same behavior you have
@@ -234,7 +232,7 @@
234 (substitute-key-definition 'forward-sentence 232 (substitute-key-definition 'forward-sentence
235 'python-nav-forward-block 233 'python-nav-forward-block
236 map global-map) 234 map global-map)
237 (define-key map "\C-c\C-j" 'python-nav-jump-to-defun) 235 (define-key map "\C-c\C-j" 'imenu)
238 ;; Indent specific 236 ;; Indent specific
239 (define-key map "\177" 'python-indent-dedent-line-backspace) 237 (define-key map "\177" 'python-indent-dedent-line-backspace)
240 (define-key map (kbd "<backtab>") 'python-indent-dedent-line) 238 (define-key map (kbd "<backtab>") 'python-indent-dedent-line)
@@ -275,7 +273,7 @@
275 :help "Go to end of definition around point"] 273 :help "Go to end of definition around point"]
276 ["Mark def/class" mark-defun 274 ["Mark def/class" mark-defun
277 :help "Mark outermost definition around point"] 275 :help "Mark outermost definition around point"]
278 ["Jump to def/class" python-nav-jump-to-defun 276 ["Jump to def/class" imenu
279 :help "Jump to a class or function definition"] 277 :help "Jump to a class or function definition"]
280 "--" 278 "--"
281 ("Skeletons") 279 ("Skeletons")
@@ -1304,62 +1302,6 @@ move backward N times."
1304 (t (python-nav-block-start)))) 1302 (t (python-nav-block-start))))
1305 (setq arg (1+ arg)))) 1303 (setq arg (1+ arg))))
1306 1304
1307(defvar python-nav-list-defun-positions-cache nil)
1308(make-variable-buffer-local 'python-nav-list-defun-positions-cache)
1309
1310(defun python-nav-list-defun-positions (&optional include-type rescan)
1311 "Make an Alist of defun names and point markers for current buffer.
1312When optional argument INCLUDE-TYPE is non-nil the type is
1313included the defun name. With optional argument RESCAN the
1314`python-nav-list-defun-positions-cache' is invalidated and the
1315list of defun is regenerated again."
1316 (if (and python-nav-list-defun-positions-cache (not rescan))
1317 python-nav-list-defun-positions-cache
1318 (let ((defs))
1319 (save-restriction
1320 (widen)
1321 (save-excursion
1322 (goto-char (point-max))
1323 (while (re-search-backward python-nav-beginning-of-defun-regexp nil t)
1324 (when (and (not (python-info-ppss-context 'string))
1325 (not (python-info-ppss-context 'comment))
1326 (not (python-info-ppss-context 'parent)))
1327 (add-to-list
1328 'defs (cons
1329 (python-info-current-defun include-type)
1330 (point-marker)))))
1331 (setq python-nav-list-defun-positions-cache defs))))))
1332
1333(defun python-nav-read-defun (&optional rescan)
1334 "Read a defun name of current buffer and return its point marker.
1335A cons cell with the form (DEFUN-NAME . POINT-MARKER) is returned
1336when defun is completed, else nil. With optional argument RESCAN
1337forces `python-nav-list-defun-positions' to invalidate its
1338cache."
1339 (let ((defs (python-nav-list-defun-positions nil rescan)))
1340 (minibuffer-with-setup-hook
1341 (lambda ()
1342 (setq minibuffer-completion-table (mapcar 'car defs)))
1343 (let ((stringdef
1344 (read-from-minibuffer
1345 "Jump to definition: " nil
1346 minibuffer-local-must-match-map)))
1347 (when (not (string= stringdef ""))
1348 (assoc-string stringdef defs))))))
1349
1350(defun python-nav-jump-to-defun (def)
1351 "Jump to the definition of DEF in current file.
1352Locations are cached; use a `C-u' prefix argument to force a
1353rescan."
1354 (interactive
1355 (list (python-nav-read-defun current-prefix-arg)))
1356 (when (not (called-interactively-p 'interactive))
1357 (setq def (assoc-string def (python-nav-list-defun-positions))))
1358 (let ((def-marker (cdr def)))
1359 (when (markerp def-marker)
1360 (goto-char (marker-position def-marker))
1361 (back-to-indentation))))
1362
1363 1305
1364;;; Shell integration 1306;;; Shell integration
1365 1307
@@ -2602,119 +2544,6 @@ Interactively, prompt for symbol."
2602 (message (python-eldoc--get-doc-at-point symbol process))))) 2544 (message (python-eldoc--get-doc-at-point symbol process)))))
2603 2545
2604 2546
2605;;; Imenu
2606
2607(defcustom python-imenu-include-defun-type t
2608 "Non-nil make imenu items to include its type."
2609 :type 'boolean
2610 :group 'python
2611 :safe 'booleanp)
2612
2613(defcustom python-imenu-make-tree t
2614 "Non-nil make imenu to build a tree menu.
2615Set to nil for speed."
2616 :type 'boolean
2617 :group 'python
2618 :safe 'booleanp)
2619
2620(defcustom python-imenu-subtree-root-label "<Jump to %s>"
2621 "Label displayed to navigate to root from a subtree.
2622It can contain a \"%s\" which will be replaced with the root name."
2623 :type 'string
2624 :group 'python
2625 :safe 'stringp)
2626
2627(defvar python-imenu-index-alist nil
2628 "Calculated index tree for imenu.")
2629
2630(defun python-imenu-tree-assoc (keylist tree)
2631 "Using KEYLIST traverse TREE."
2632 (if keylist
2633 (python-imenu-tree-assoc (cdr keylist)
2634 (ignore-errors (assoc (car keylist) tree)))
2635 tree))
2636
2637(defun python-imenu-make-element-tree (element-list full-element plain-index)
2638 "Make a tree from plain alist of module names.
2639ELEMENT-LIST is the defun name split by \".\" and FULL-ELEMENT
2640is the same thing, the difference is that FULL-ELEMENT remains
2641untouched in all recursive calls.
2642Argument PLAIN-INDEX is the calculated plain index used to build the tree."
2643 (when (not (python-imenu-tree-assoc full-element python-imenu-index-alist))
2644 (when element-list
2645 (let* ((subelement-point (cdr (assoc
2646 (mapconcat #'identity full-element ".")
2647 plain-index)))
2648 (subelement-name (car element-list))
2649 (subelement-position (python-util-position
2650 subelement-name full-element))
2651 (subelement-path (when subelement-position
2652 (butlast
2653 full-element
2654 (- (length full-element)
2655 subelement-position)))))
2656 (let ((path-ref (python-imenu-tree-assoc subelement-path
2657 python-imenu-index-alist)))
2658 (if (not path-ref)
2659 (push (cons subelement-name subelement-point)
2660 python-imenu-index-alist)
2661 (when (not (listp (cdr path-ref)))
2662 ;; Modify root cdr to be a list.
2663 (setcdr path-ref
2664 (list (cons (format python-imenu-subtree-root-label
2665 (car path-ref))
2666 (cdr (assoc
2667 (mapconcat #'identity
2668 subelement-path ".")
2669 plain-index))))))
2670 (when (not (assoc subelement-name path-ref))
2671 (push (cons subelement-name subelement-point) (cdr path-ref))))))
2672 (python-imenu-make-element-tree (cdr element-list)
2673 full-element plain-index))))
2674
2675(defun python-imenu-make-tree (index)
2676 "Build the imenu alist tree from plain INDEX.
2677
2678The idea of this function is that given the alist:
2679
2680 '((\"Test\" . 100)
2681 (\"Test.__init__\" . 200)
2682 (\"Test.some_method\" . 300)
2683 (\"Test.some_method.another\" . 400)
2684 (\"Test.something_else\" . 500)
2685 (\"test\" . 600)
2686 (\"test.reprint\" . 700)
2687 (\"test.reprint\" . 800))
2688
2689This tree gets built:
2690
2691 '((\"Test\" . ((\"jump to...\" . 100)
2692 (\"__init__\" . 200)
2693 (\"some_method\" . ((\"jump to...\" . 300)
2694 (\"another\" . 400)))
2695 (\"something_else\" . 500)))
2696 (\"test\" . ((\"jump to...\" . 600)
2697 (\"reprint\" . 700)
2698 (\"reprint\" . 800))))
2699
2700Internally it uses `python-imenu-make-element-tree' to create all
2701branches for each element."
2702 (setq python-imenu-index-alist nil)
2703 (mapc (lambda (element)
2704 (python-imenu-make-element-tree element element index))
2705 (mapcar (lambda (element)
2706 (split-string (car element) "\\." t)) index))
2707 python-imenu-index-alist)
2708
2709(defun python-imenu-create-index ()
2710 "`imenu-create-index-function' for Python."
2711 (let ((index
2712 (python-nav-list-defun-positions python-imenu-include-defun-type)))
2713 (if python-imenu-make-tree
2714 (python-imenu-make-tree index)
2715 index)))
2716
2717
2718;;; Misc helpers 2547;;; Misc helpers
2719 2548
2720(defun python-info-current-defun (&optional include-type) 2549(defun python-info-current-defun (&optional include-type)
@@ -3019,7 +2848,8 @@ if that value is non-nil."
3019 (add-hook 'post-self-insert-hook 2848 (add-hook 'post-self-insert-hook
3020 'python-indent-post-self-insert-function nil 'local) 2849 'python-indent-post-self-insert-function nil 'local)
3021 2850
3022 (setq imenu-create-index-function #'python-imenu-create-index) 2851 (set (make-local-variable 'imenu-extract-index-name-function)
2852 #'python-info-current-defun)
3023 2853
3024 (set (make-local-variable 'add-log-current-defun-function) 2854 (set (make-local-variable 'add-log-current-defun-function)
3025 #'python-info-current-defun) 2855 #'python-info-current-defun)