Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
marvel
GitHub Repository: marvel/qnf
Path: blob/master/elisp/slime/contrib/slime-xref-browser.el
990 views
1
2
(define-slime-contrib slime-xref-browser
3
"Xref browsing with tree-widget"
4
(:authors "Rui Patroc�nio <[email protected]>")
5
(:license "GPL"))
6
7
8
;;;; classes browser
9
10
(defun slime-expand-class-node (widget)
11
(or (widget-get widget :args)
12
(let ((name (widget-get widget :tag)))
13
(loop for kid in (slime-eval `(swank:mop :subclasses ,name))
14
collect `(tree-widget :tag ,kid
15
:expander slime-expand-class-node
16
:has-children t)))))
17
18
(defun slime-browse-classes (name)
19
"Read the name of a class and show its subclasses."
20
(interactive (list (slime-read-symbol-name "Class Name: ")))
21
(slime-call-with-browser-setup
22
(slime-buffer-name :browser) (slime-current-package) "Class Browser"
23
(lambda ()
24
(widget-create 'tree-widget :tag name
25
:expander 'slime-expand-class-node
26
:has-echildren t))))
27
28
(defvar slime-browser-map nil
29
"Keymap for tree widget browsers")
30
31
(require 'tree-widget)
32
(unless slime-browser-map
33
(setq slime-browser-map (make-sparse-keymap))
34
(set-keymap-parent slime-browser-map widget-keymap)
35
(define-key slime-browser-map "q" 'bury-buffer))
36
37
(defun slime-call-with-browser-setup (buffer package title fn)
38
(switch-to-buffer buffer)
39
(kill-all-local-variables)
40
(setq slime-buffer-package package)
41
(let ((inhibit-read-only t)) (erase-buffer))
42
(widget-insert title "\n\n")
43
(save-excursion
44
(funcall fn))
45
(lisp-mode-variables t)
46
(slime-mode t)
47
(use-local-map slime-browser-map)
48
(widget-setup))
49
50
51
;;;; Xref browser
52
53
(defun slime-fetch-browsable-xrefs (type name)
54
"Return a list ((LABEL DSPEC)).
55
LABEL is just a string for display purposes.
56
DSPEC can be used to expand the node."
57
(let ((xrefs '()))
58
(loop for (_file . specs) in (slime-eval `(swank:xref ,type ,name)) do
59
(loop for (dspec . _location) in specs do
60
(let ((exp (ignore-errors (read (downcase dspec)))))
61
(cond ((and (consp exp) (eq 'flet (car exp)))
62
;; we can't expand FLET references so they're useless
63
)
64
((and (consp exp) (eq 'method (car exp)))
65
;; this isn't quite right, but good enough for now
66
(push (list dspec (string (second exp))) xrefs))
67
(t
68
(push (list dspec dspec) xrefs))))))
69
xrefs))
70
71
(defun slime-expand-xrefs (widget)
72
(or (widget-get widget :args)
73
(let* ((type (widget-get widget :xref-type))
74
(dspec (widget-get widget :xref-dspec))
75
(xrefs (slime-fetch-browsable-xrefs type dspec)))
76
(loop for (label dspec) in xrefs
77
collect `(tree-widget :tag ,label
78
:xref-type ,type
79
:xref-dspec ,dspec
80
:expander slime-expand-xrefs
81
:has-children t)))))
82
83
(defun slime-browse-xrefs (name type)
84
"Show the xref graph of a function in a tree widget."
85
(interactive
86
(list (slime-read-from-minibuffer "Name: "
87
(slime-symbol-at-point))
88
(read (completing-read "Type: " (slime-bogus-completion-alist
89
'(":callers" ":callees" ":calls"))
90
nil t ":"))))
91
(slime-call-with-browser-setup
92
(slime-buffer-name :xref) (slime-current-package) "Xref Browser"
93
(lambda ()
94
(widget-create 'tree-widget :tag name :xref-type type :xref-dspec name
95
:expander 'slime-expand-xrefs :has-echildren t))))
96
97
(provide 'slime-xref-browser)
98
99