imenuをツリー表示

なんとなくimenuをツリー表示できるのを作ってみた…けど…微妙。
便利になりそうなアイディア募集中。

使い方

  • M-x imenu-tree でツリーを表示。
  • 関数名とかを選んでRETでその要素の場所にジャンプ。

ソース

(require 'tree-widget)

(defvar imenu-tree-mode-map nil)
(unless imenu-tree-mode-map
  (let ((map (copy-keymap widget-keymap)))
    (define-key map (kbd "n") 'widget-forward)
    (define-key map (kbd "p") 'widget-backward)
    (define-key map (kbd "q") 'imenu-tree-quit)
    (setq imenu-tree-mode-map map)))
(defvar imenu-tree-mode-hook nil)
(defvar imenu-tree-goto-function nil)
(defvar imenu-tree-window-configuration nil)

(defun imenu-tree-create-widget-tree (tree)
  (append
   (list
   'tree-widget
   :node (list 'item :tag (car tree))
   :open t)
   (mapcar (lambda (node)
             (if (consp (cdr node))
                 (imenu-tree-create-widget-tree node)
               (list 'item
                     :tag (car node)
                     :position (cdr node)
                     :action 'imenu-tree-select)))
           (cdr tree))))

(defun imenu-tree-mode ()
  (interactive)
  (kill-all-local-variables)
  (use-local-map imenu-tree-mode-map)
  (setq mode-name "Imenu Tree")
  (setq major-mode 'imenu-tree-mode)
  (run-hooks 'imenu-tree-mode-hook))

(defun imenu-tree ()
  (interactive)
  (let ((tree (cons "Root" (funcall imenu-create-index-function)))
        (goto-function imenu-default-goto-function))
    (setq imenu-tree-window-configuration (current-window-configuration))
    (setq imenu-tree-goto-function goto-function)
    (with-current-buffer (get-buffer-create "*imenu-tree*")
      (let ((inhibit-read-only t))
        (erase-buffer)
        (remove-overlays)
        (imenu-tree-mode)
        (apply 'widget-create
               (imenu-tree-create-widget-tree tree))
        (widget-setup))
      (goto-char (point-min))
      (pop-to-buffer (current-buffer)))))
    
(defun imenu-tree-select (widget &rest args)
  (let ((name (widget-get widget :tag))
        (position (widget-get widget :position)))
    (imenu-tree-quit)
    (funcall imenu-tree-goto-function name position)))

(defun imenu-tree-quit ()
  (interactive)
  (bury-buffer)
  (set-window-configuration imenu-tree-window-configuration))

(provide 'imenu-tree)
;;; imenu-tree.el ends here