Better module help
[geiser.git] / elisp / geiser-autodoc.el
blob5bdfb1a7ab5bbe13857b58c29851a2a88b283e8d
1 ;; geiser-autodoc.el -- autodoc mode
3 ;; Copyright (C) 2009, 2010 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)
19 (require 'eldoc)
22 ;;; Customization:
24 (defgroup geiser-autodoc nil
25 "Options for displaying autodoc strings in the echo area."
26 :group 'geiser)
28 (geiser-custom--defface autodoc-current-arg
29 'bold geiser-autodoc "highlighting current argument in autodoc messages")
31 (geiser-custom--defface autodoc-identifier
32 'font-lock-function-name-face
33 geiser-autodoc "highlighting procedure name in autodoc messages")
35 (geiser-custom--defcustom geiser-autodoc-delay 0.3
36 "Delay before autodoc messages are fetched and displayed, in seconds."
37 :type 'number
38 :group 'geiser-autodoc)
40 (geiser-custom--defcustom geiser-autodoc-display-module-p t
41 "Whether to display procedure module in autodoc strings."
42 :type 'boolean
43 :group 'geiser-autodoc)
45 (geiser-custom--defcustom geiser-autodoc-identifier-format "%s:%s"
46 "Format for displaying module and procedure or variable name, in that order,
47 when `geiser-autodoc-display-module-p' is on."
48 :type 'string
49 :group 'geiser-autodoc)
52 ;;; Procedure arguments:
54 (make-variable-buffer-local
55 (defvar geiser-autodoc--cached-signatures nil))
57 (defsubst geiser-autodoc--clean-cache ()
58 (setq geiser-autodoc--cached-signatures nil))
60 (defun geiser-autodoc--get-signatures (funs &optional keep-cached)
61 (when funs
62 (let ((fs (assq (car funs) geiser-autodoc--cached-signatures)))
63 (unless fs
64 (let ((missing) (cached))
65 (if (not geiser-autodoc--cached-signatures)
66 (setq missing funs)
67 (dolist (f funs)
68 (let ((cf (assq f geiser-autodoc--cached-signatures)))
69 (if cf (push cf cached)
70 (push f missing)))))
71 (unless (or cached keep-cached) (geiser-autodoc--clean-cache))
72 (when missing
73 (let ((res (geiser-eval--send/result `(:eval (:ge autodoc
74 (quote ,missing)))
75 500)))
76 (when res
77 (setq geiser-autodoc--cached-signatures
78 (append res (if keep-cached
79 geiser-autodoc--cached-signatures
80 cached))))))))
81 geiser-autodoc--cached-signatures)))
83 (defun geiser-autodoc--sanitize-args (args)
84 (cond ((null args) nil)
85 ((listp args)
86 (cons (car args) (geiser-autodoc--sanitize-args (cdr args))))
87 (t '...)))
89 (defun geiser-autodoc--format-arg (a)
90 (if (and (listp a) (keywordp (car a)))
91 (if (and (cdr a) (listp (cdr a)))
92 (format "(#%s %s)" (car a) (cadr a))
93 (format "(#%s)" (car a)))
94 (format "%s" a)))
96 (defun geiser-autodoc--insert-arg-group (args current &optional pos)
97 (when args (insert " "))
98 (dolist (a (geiser-autodoc--sanitize-args args))
99 (let ((p (point)))
100 (insert (geiser-autodoc--format-arg a))
101 (when (or (and (numberp pos)
102 (numberp current)
103 (setq current (1+ current))
104 (= (1+ pos) current))
105 (and (keywordp current)
106 (listp a)
107 (eq current (car a))))
108 (put-text-property p (point)
109 'face 'geiser-font-lock-autodoc-current-arg)
110 (setq pos nil current nil)))
111 (insert " "))
112 (when args (backward-char))
113 current)
115 (defun geiser-autodoc--insert-args (args pos prev)
116 (let ((cpos 1)
117 (reqs (cdr (assoc 'required args)))
118 (opts (mapcar (lambda (a)
119 (if (and (symbolp a) (not (eq a '...))) (list a) a))
120 (cdr (assoc 'optional args))))
121 (keys (cdr (assoc 'key args))))
122 (setq cpos
123 (geiser-autodoc--insert-arg-group reqs
124 cpos
125 (and (not (zerop pos)) pos)))
126 (setq cpos (geiser-autodoc--insert-arg-group opts cpos pos))
127 (geiser-autodoc--insert-arg-group keys prev nil)))
129 (defsubst geiser-autodoc--id-name (proc module)
130 (let ((str (if module
131 (format geiser-autodoc-identifier-format module proc)
132 (format "%s" proc))))
133 (propertize str 'face 'geiser-font-lock-autodoc-identifier)))
135 (defun geiser-autodoc--str* (full-signature)
136 (geiser-autodoc--str (list (car full-signature)) full-signature))
138 (defsubst geiser-autodoc--value-str (proc module value)
139 (let ((name (geiser-autodoc--id-name proc module)))
140 (if value (format "%s => %s" name value) name)))
142 (defun geiser-autodoc--str (desc signature)
143 (let ((proc (car desc))
144 (args (cdr (assoc 'args signature)))
145 (module (cdr (assoc 'module signature))))
146 (if (not args)
147 (geiser-autodoc--value-str proc module (cdr (assoc 'value signature)))
148 (save-current-buffer
149 (set-buffer (geiser-syntax--font-lock-buffer))
150 (erase-buffer)
151 (insert (format "(%s" (geiser-autodoc--id-name proc module)))
152 (let ((pos (or (cadr desc) 0))
153 (prev (car (cddr desc))))
154 (dolist (a args)
155 (when (not (member a (cdr (member a args))))
156 (geiser-autodoc--insert-args a pos prev)
157 (insert " |"))))
158 (delete-char -2)
159 (insert ")")
160 (buffer-string)))))
162 (defun geiser-autodoc--autodoc (path &optional keep-cached)
163 (let ((signs (geiser-autodoc--get-signatures (mapcar 'car path)
164 keep-cached))
165 (p (car path))
166 (s))
167 (while (and p (not s))
168 (unless (setq s (cdr (assq (car p) signs)))
169 (setq p (car path))
170 (setq path (cdr path))))
171 (when s (geiser-autodoc--str p s))))
174 ;;; Autodoc function:
176 (make-variable-buffer-local
177 (defvar geiser-autodoc--inhibit-function nil))
179 (defsubst geiser-autodoc--inhibit ()
180 (and geiser-autodoc--inhibit-function
181 (funcall geiser-autodoc--inhibit-function)))
183 (defun geiser-autodoc--eldoc-function ()
184 (condition-case e
185 (and (not (geiser-autodoc--inhibit))
186 (geiser-autodoc--autodoc (geiser-syntax--scan-sexps)))
187 (error (format "Autodoc not available (%s)" (error-message-string e)))))
190 ;;; Autodoc mode:
192 (make-variable-buffer-local
193 (defvar geiser-autodoc-mode-string " A"
194 "Modeline indicator for geiser-autodoc-mode"))
196 (define-minor-mode geiser-autodoc-mode
197 "Toggle Geiser's Autodoc mode.
198 With no argument, this command toggles the mode.
199 Non-null prefix argument turns on the mode.
200 Null prefix argument turns off the mode.
202 When Autodoc mode is enabled, a synopsis of the word at point is
203 displayed in the minibuffer."
204 :init-value nil
205 :lighter geiser-autodoc-mode-string
206 :group 'geiser-autodoc
208 (set (make-local-variable 'eldoc-documentation-function)
209 (when geiser-autodoc-mode 'geiser-autodoc--eldoc-function))
210 (set (make-local-variable 'eldoc-minor-mode-string) nil)
211 (set (make-local-variable 'eldoc-idle-delay) geiser-autodoc-delay)
212 (eldoc-mode geiser-autodoc-mode)
213 (message "Geiser Autodoc %s" (if geiser-autodoc-mode "enabled" "disabled")))
216 (provide 'geiser-autodoc)
217 ;;; geiser-autodoc.el ends here