1 ;; geiser-autodoc.el -- autodoc mode
3 ;; Copyright (C) 2009, 2010, 2011, 2012, 2015, 2016 Jose Antonio Ortega Ruiz
5 ;; This program is free software; you can redistribute it and/or
6 ;; modify it under the terms of the Modified BSD License. You should
7 ;; have received a copy of the license along with this program. If
8 ;; not, see <http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5>.
10 ;; Start date: Sun Feb 08, 2009 19:44
14 (require 'geiser-eval
)
15 (require 'geiser-syntax
)
16 (require 'geiser-custom
)
17 (require 'geiser-base
)
24 (defgroup geiser-autodoc nil
25 "Options for displaying autodoc strings in the echo area."
28 (geiser-custom--defface autodoc-current-arg
29 'font-lock-variable-name-face
30 geiser-autodoc
"highlighting current argument in autodoc messages")
32 (geiser-custom--defface autodoc-identifier
33 'font-lock-function-name-face
34 geiser-autodoc
"highlighting procedure name in autodoc messages")
36 (geiser-custom--defcustom geiser-autodoc-delay
0.3
37 "Delay before autodoc messages are fetched and displayed, in seconds."
39 :group
'geiser-autodoc
)
41 (geiser-custom--defcustom geiser-autodoc-display-module-p t
42 "Whether to display procedure module in autodoc strings."
44 :group
'geiser-autodoc
)
46 (geiser-custom--defcustom geiser-autodoc-identifier-format
"%s:%s"
47 "Format for displaying module and procedure or variable name, in that order,
48 when `geiser-autodoc-display-module-p' is on."
50 :group
'geiser-autodoc
)
53 ;;; Procedure arguments:
55 (make-variable-buffer-local
56 (defvar geiser-autodoc--cached-signatures nil
))
58 (defsubst geiser-autodoc--clean-cache
()
59 (setq geiser-autodoc--cached-signatures nil
))
61 (defun geiser-autodoc--show-signatures (ret)
62 (let ((res (geiser-eval--retort-result ret
))
66 (push (cons (format "%s" (car item
)) (cdr item
)) signs
))
67 (let ((str (geiser-autodoc--autodoc (geiser-syntax--scan-sexps) signs
)))
68 (when (not (string-equal str eldoc-last-message
))
70 (setq geiser-autodoc--cached-signatures signs
))))
72 (defun geiser-autodoc--get-signatures (funs)
74 (let ((m (format "'(%s)" (mapconcat 'identity funs
" "))))
75 (geiser-eval--send `(:eval
(:ge autodoc
(:scm
,m
)))
76 'geiser-autodoc--show-signatures
)))
77 (and (or (assoc (car funs
) geiser-autodoc--cached-signatures
)
78 (assoc (cadr funs
) geiser-autodoc--cached-signatures
))
79 geiser-autodoc--cached-signatures
))
81 (defun geiser-autodoc--sanitize-args (args)
82 (cond ((null args
) nil
)
84 (cons (car args
) (geiser-autodoc--sanitize-args (cdr args
))))
87 (defun geiser-autodoc--format-arg (a)
88 (cond ((and (listp a
) (geiser-syntax--keywordp (car a
)))
89 (if (and (cdr a
) (listp (cdr a
)))
90 (format "(#%s %s)" (car a
) (geiser-syntax--display (cadr a
)))
91 (format "(#%s)" (car a
))))
92 (t (geiser-syntax--display a
))))
94 (defun geiser-autodoc--insert-arg-group (args current
&optional pos
)
95 (when args
(insert " "))
96 (dolist (a (geiser-autodoc--sanitize-args args
))
98 (insert (geiser-autodoc--format-arg a
))
99 (when (or (and (numberp pos
)
101 (setq current
(1+ current
))
102 (= (1+ pos
) current
))
103 (and (geiser-syntax--keywordp current
)
105 (geiser-syntax--symbol-eq current
(car a
))))
106 (put-text-property p
(point)
107 'face
'geiser-font-lock-autodoc-current-arg
)
108 (setq pos nil current nil
)))
110 (when args
(backward-char))
113 (defun geiser-autodoc--insert-args (args pos prev
)
115 (reqs (cdr (assoc "required" args
)))
116 (opts (mapcar (lambda (a)
118 (not (equal (symbol-name a
) "...")))
121 (cdr (assoc "optional" args
))))
122 (keys (cdr (assoc "key" args
))))
124 (geiser-autodoc--insert-arg-group reqs
126 (and (not (zerop pos
)) pos
)))
127 (setq cpos
(geiser-autodoc--insert-arg-group opts cpos pos
))
128 (geiser-autodoc--insert-arg-group keys prev nil
)))
130 (defsubst geiser-autodoc--id-name
(proc module
)
131 (let ((str (if module
132 (format geiser-autodoc-identifier-format module proc
)
133 (format "%s" proc
))))
134 (propertize str
'face
'geiser-font-lock-autodoc-identifier
)))
136 (defun geiser-autodoc--str* (full-signature)
137 (let ((geiser-font-lock-autodoc-current-arg 'default
))
138 (geiser-autodoc--str (list (car full-signature
)) full-signature
)))
140 (defsubst geiser-autodoc--value-str
(proc module value
)
141 (let ((name (geiser-autodoc--id-name proc module
)))
142 (if value
(format "%s => %s" name value
) name
)))
144 (defun geiser-autodoc--str (desc signature
)
145 (let ((proc (car desc
))
146 (args (cdr (assoc "args" signature
)))
147 (module (cdr (assoc "module" signature
))))
149 (geiser-autodoc--value-str proc module
(cdr (assoc "value" signature
)))
151 (set-buffer (geiser-syntax--font-lock-buffer))
153 (insert (format "(%s" (geiser-autodoc--id-name proc module
)))
154 (let ((pos (or (cadr desc
) 0))
155 (prev (car (cddr desc
))))
157 (when (not (member a
(cdr (member a args
))))
158 (geiser-autodoc--insert-args a pos prev
)
162 (buffer-substring (point-min) (point))))))
164 (defun geiser-autodoc--autodoc (path &optional signs
)
165 (let ((signs (or signs
(geiser-autodoc--get-signatures (mapcar 'car path
))))
168 (while (and p
(not s
))
169 (unless (setq s
(cdr (assoc (car p
) signs
)))
171 (setq path
(cdr path
))))
172 (when s
(geiser-autodoc--str p s
))))
175 ;;; Autodoc functions:
177 (make-variable-buffer-local
178 (defvar geiser-autodoc--inhibit-function nil
))
180 (defsubst geiser-autodoc--inhibit
()
181 (and geiser-autodoc--inhibit-function
182 (funcall geiser-autodoc--inhibit-function
)))
184 (defsubst geiser-autodoc--inhibit-autodoc
()
185 (setq geiser-autodoc--inhibit-function
(lambda () t
)))
187 (defsubst geiser-autodoc--disinhibit-autodoc
()
188 (setq geiser-autodoc--inhibit-function nil
))
190 (defsubst geiser-autodoc--autodoc-at-point
()
191 (geiser-autodoc--autodoc (geiser-syntax--scan-sexps)))
193 (defun geiser-autodoc--eldoc-function ()
195 (when (not (geiser-autodoc--inhibit))
196 (geiser-autodoc--autodoc-at-point))))
198 (defun geiser-autodoc-show ()
199 "Show the signature or value of the symbol at point in the echo area."
201 (message (geiser-autodoc--autodoc-at-point)))
206 (make-variable-buffer-local
207 (defvar geiser-autodoc-mode-string
" A"
208 "Modeline indicator for geiser-autodoc-mode"))
210 (define-minor-mode geiser-autodoc-mode
211 "Toggle Geiser's Autodoc mode.
212 With no argument, this command toggles the mode.
213 Non-null prefix argument turns on the mode.
214 Null prefix argument turns off the mode.
216 When Autodoc mode is enabled, a synopsis of the word at point is
217 displayed in the minibuffer."
219 :lighter geiser-autodoc-mode-string
220 :group
'geiser-autodoc
222 (set (make-local-variable 'eldoc-documentation-function
)
223 (when geiser-autodoc-mode
'geiser-autodoc--eldoc-function
))
224 (set (make-local-variable 'eldoc-minor-mode-string
) nil
)
225 (set (make-local-variable 'eldoc-idle-delay
) geiser-autodoc-delay
)
226 (eldoc-mode (if geiser-autodoc-mode
1 -
1))
227 (when (called-interactively-p nil
)
228 (message "Geiser Autodoc %s"
229 (if geiser-autodoc-mode
"enabled" "disabled"))))
231 (defadvice eldoc-display-message-no-interference-p
232 (after geiser-autodoc--message-ok-p
)
233 (when geiser-autodoc-mode
234 (setq ad-return-value
236 ;; Display arglist only when the minibuffer is
237 ;; inactive, e.g. not on `C-x C-f'. Lifted from slime.
238 (not (active-minibuffer-window)))))
243 (provide 'geiser-autodoc
)