|
|
- (eval-and-compile
- (require 'slime))
-
- (define-slime-contrib slime-xref-browser
- "Xref browsing with tree-widget"
- (:authors "Rui Patroc�nio <rui.patrocinio@netvisao.pt>")
- (:license "GPL"))
-
- ;;;; classes browser
-
- (defun slime-expand-class-node (widget)
- (or (widget-get widget :args)
- (let ((name (widget-get widget :tag)))
- (cl-loop for kid in (slime-eval `(swank:mop :subclasses ,name))
- collect `(tree-widget :tag ,kid
- :expander slime-expand-class-node
- :has-children t)))))
-
- (defun slime-browse-classes (name)
- "Read the name of a class and show its subclasses."
- (interactive (list (slime-read-symbol-name "Class Name: ")))
- (slime-call-with-browser-setup
- (slime-buffer-name :browser) (slime-current-package) "Class Browser"
- (lambda ()
- (widget-create 'tree-widget :tag name
- :expander 'slime-expand-class-node
- :has-echildren t))))
-
- (defvar slime-browser-map nil
- "Keymap for tree widget browsers")
-
- (require 'tree-widget)
- (unless slime-browser-map
- (setq slime-browser-map (make-sparse-keymap))
- (set-keymap-parent slime-browser-map widget-keymap)
- (define-key slime-browser-map "q" 'bury-buffer))
-
- (defun slime-call-with-browser-setup (buffer package title fn)
- (switch-to-buffer buffer)
- (kill-all-local-variables)
- (setq slime-buffer-package package)
- (let ((inhibit-read-only t)) (erase-buffer))
- (widget-insert title "\n\n")
- (save-excursion
- (funcall fn))
- (lisp-mode-variables t)
- (slime-mode t)
- (use-local-map slime-browser-map)
- (widget-setup))
-
- ;;;; Xref browser
-
- (defun slime-fetch-browsable-xrefs (type name)
- "Return a list ((LABEL DSPEC)).
- LABEL is just a string for display purposes.
- DSPEC can be used to expand the node."
- (let ((xrefs '()))
- (cl-loop for (_file . specs) in (slime-eval `(swank:xref ,type ,name)) do
- (cl-loop for (dspec . _location) in specs do
- (let ((exp (ignore-errors (read (downcase dspec)))))
- (cond ((and (consp exp) (eq 'flet (car exp)))
- ;; we can't expand FLET references so they're useless
- )
- ((and (consp exp) (eq 'method (car exp)))
- ;; this isn't quite right, but good enough for now
- (push (list dspec (string (cl-second exp))) xrefs))
- (t
- (push (list dspec dspec) xrefs))))))
- xrefs))
-
- (defun slime-expand-xrefs (widget)
- (or (widget-get widget :args)
- (let* ((type (widget-get widget :xref-type))
- (dspec (widget-get widget :xref-dspec))
- (xrefs (slime-fetch-browsable-xrefs type dspec)))
- (cl-loop for (label dspec) in xrefs
- collect `(tree-widget :tag ,label
- :xref-type ,type
- :xref-dspec ,dspec
- :expander slime-expand-xrefs
- :has-children t)))))
-
- (defun slime-browse-xrefs (name type)
- "Show the xref graph of a function in a tree widget."
- (interactive
- (list (slime-read-from-minibuffer "Name: "
- (slime-symbol-at-point))
- (read (completing-read "Type: " (slime-bogus-completion-alist
- '(":callers" ":callees" ":calls"))
- nil t ":"))))
- (slime-call-with-browser-setup
- (slime-buffer-name :xref) (slime-current-package) "Xref Browser"
- (lambda ()
- (widget-create 'tree-widget :tag name :xref-type type :xref-dspec name
- :expander 'slime-expand-xrefs :has-echildren t))))
-
- (provide 'slime-xref-browser)
|