diff options
| author | Fabián Ezequiel Gallina | 2012-07-16 14:18:39 -0300 |
|---|---|---|
| committer | Fabián Ezequiel Gallina | 2012-07-16 14:18:39 -0300 |
| commit | 758e556a7ab8f61c007e34310ba399a9aaf15362 (patch) | |
| tree | 88669e3905313e194fc67a63a7b56a5a9f45c2b2 /lisp/progmodes/python.el | |
| parent | 032d23ab664d571be03f5661034d1962baa4f5ae (diff) | |
| download | emacs-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.el | 186 |
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. | ||
| 1312 | When optional argument INCLUDE-TYPE is non-nil the type is | ||
| 1313 | included the defun name. With optional argument RESCAN the | ||
| 1314 | `python-nav-list-defun-positions-cache' is invalidated and the | ||
| 1315 | list 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. | ||
| 1335 | A cons cell with the form (DEFUN-NAME . POINT-MARKER) is returned | ||
| 1336 | when defun is completed, else nil. With optional argument RESCAN | ||
| 1337 | forces `python-nav-list-defun-positions' to invalidate its | ||
| 1338 | cache." | ||
| 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. | ||
| 1352 | Locations are cached; use a `C-u' prefix argument to force a | ||
| 1353 | rescan." | ||
| 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. | ||
| 2615 | Set 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. | ||
| 2622 | It 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. | ||
| 2639 | ELEMENT-LIST is the defun name split by \".\" and FULL-ELEMENT | ||
| 2640 | is the same thing, the difference is that FULL-ELEMENT remains | ||
| 2641 | untouched in all recursive calls. | ||
| 2642 | Argument 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 | |||
| 2678 | The 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 | |||
| 2689 | This 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 | |||
| 2700 | Internally it uses `python-imenu-make-element-tree' to create all | ||
| 2701 | branches 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) |