*** empty log message ***
[bpt/guile.git] / ice-9 / session.scm
CommitLineData
13ae9151 1;;;; Copyright (C) 1997, 2000 Free Software Foundation, Inc.
0e81dabd
MD
2;;;;
3;;;; This program is free software; you can redistribute it and/or modify
4;;;; it under the terms of the GNU General Public License as published by
5;;;; the Free Software Foundation; either version 2, or (at your option)
6;;;; any later version.
7;;;;
8;;;; This program is distributed in the hope that it will be useful,
9;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
10;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11;;;; GNU General Public License for more details.
12;;;;
13;;;; You should have received a copy of the GNU General Public License
14;;;; along with this software; see the file COPYING. If not, write to
c6e23ea2
JB
15;;;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16;;;; Boston, MA 02111-1307 USA
0e81dabd
MD
17;;;;
18\f
19
bbefd480 20(define-module (ice-9 session)
3bdca000
MD
21 :use-module (ice-9 documentation)
22 )
0e81dabd
MD
23
24\f
25
13ae9151
MD
26;;; Documentation
27;;;
28(define-public help
29 (procedure->syntax
30 (lambda (exp env)
31 "(help [NAME])
32Prints useful information. Try `(help)'."
33 (if (not (= (length exp) 2))
34 (help-usage)
3bdca000
MD
35 (let ((name (cadr exp)))
36 (cond ((symbol? name)
37 (help-doc name
38 (string-append "^"
39 (symbol->string name)
40 "$")))
41 ((string? name)
42 (help-doc name name))
d1c50f73
MD
43 ((and (list? name)
44 (= (length name) 2)
45 (eq? (car name) 'unquote))
46 (let ((doc (object-documentation (local-eval (cadr name)
47 env))))
48 (if (not doc)
49 (simple-format #t "No documentation found for ~S\n"
50 (cadr name))
51 (write-line doc))))
13ae9151 52 (else
3bdca000 53 (help-usage)))
13ae9151
MD
54 *unspecified*)))))
55
3bdca000
MD
56(define (help-doc term regexp)
57 (let ((entries (apropos-fold (lambda (module name object data)
58 (cons (list module
59 name
60 (object-documentation object))
61 data))
62 '()
63 regexp
64 apropos-fold-exported))
65 (module car)
66 (name cadr)
67 (doc caddr))
68 (if (null? entries)
69 ;; no matches
70 (begin
71 (display "Did not find any object ")
72 (simple-format #t
73 (if (symbol? term)
74 "named `~A'\n"
75 "matching regexp \"~A\"\n")
76 term))
77 (let ((first? #t))
78 (if (or-map doc entries)
79 ;; entries with documentation
80 (for-each (lambda (entry)
81 ;; *fixme*: Use `describe' when we have GOOPS?
82 (if (doc entry)
83 (begin
84 (if first?
85 (set! first? #f)
86 (newline))
87 (simple-format #t "~S: ~S\n~A\n"
88 (module-name (module entry))
89 (name entry)
90 (doc entry)))))
91 entries))
92 (if (or-map (lambda (x) (not (doc x))) entries)
93 ;; entries without documentation
94 (begin
95 (if (not first?)
96 (display "\nNo documentation found for:\n"))
97 (for-each (lambda (entry)
98 (if (not (doc entry))
99 (simple-format #t "~S: ~S\n"
100 (module-name (module entry))
101 (name entry))))
102 entries)))))))
103
13ae9151 104(define (help-usage)
3bdca000
MD
105 (display "Usage: (help NAME) gives documentation about objects named NAME (a symbol)
106 (help REGEXP) ditto for objects with names matching REGEXP (a string)
d1c50f73 107 (help ,EXPR) gives documentation for object returned by EXPR
13ae9151
MD
108 (help) gives this text
109
3bdca000
MD
110`help' searches among bindings exported from loaded modules, while
111`apropos' searches among bindings visible from the \"current\" module.
112
2f52380c
MD
113Examples: (help help)
114 (help cons)
3bdca000 115 (help \"output-string\")
13ae9151
MD
116
117Other useful sources of helpful information:
118
119(apropos STRING)
120(arity PROCEDURE)
121(name PROCEDURE-OR-MACRO)
122(source PROCEDURE-OR-MACRO)
123
124Tools:
125
2f52380c
MD
126(backtrace) ;show backtrace from last error
127(debug) ;enter the debugger
128(trace [PROCEDURE]) ;trace procedure (no arg => show)
129(untrace [PROCEDURE]) ;untrace (no arg => untrace all)
13ae9151
MD
130
131(OPTIONSET-options 'full) ;display option information
132(OPTIONSET-enable 'OPTION)
133(OPTIONSET-disable 'OPTION)
134(OPTIONSET-set! OPTION VALUE)
135
136where OPTIONSET is one of debug, read, eval, print
137
138"))
139
0e81dabd
MD
140;;; {Apropos}
141;;;
142;;; Author: Roland Orre <orre@nada.kth.se>
143;;;
144
145(define (id x) x)
146
0e81dabd
MD
147(define-public (apropos rgx . options)
148 "Search for bindings: apropos regexp {options= 'full 'shadow 'value}"
149 (if (zero? (string-length rgx))
150 "Empty string not allowed"
4f161c5c 151 (let* ((match (make-regexp rgx))
0e81dabd
MD
152 (modules (cons (current-module)
153 (module-uses (current-module))))
154 (separator #\tab)
155 (shadow (member 'shadow options))
156 (value (member 'value options)))
157 (cond ((member 'full options)
158 (set! shadow #t)
159 (set! value #t)))
160 (for-each
161 (lambda (module)
162 (let* ((builtin (or (eq? module the-scm-module)
163 (eq? module the-root-module)))
164 (name (module-name module))
165 (obarrays (if builtin
166 (list (builtin-weak-bindings)
167 (builtin-bindings))
168 (list (module-obarray module))))
169 (get-refs (if builtin
170 (list id id)
171 (list variable-ref)))
172 )
173 (for-each
174 (lambda (obarray get-ref)
68aed3ea 175 (array-for-each
0e81dabd
MD
176 (lambda (oblist)
177 (for-each
178 (lambda (x)
4f161c5c 179 (cond ((regexp-exec match (car x))
0e81dabd
MD
180 (display name)
181 (display ": ")
182 (display (car x))
183 (cond ((procedure? (get-ref (cdr x)))
184 (display separator)
185 (display (get-ref (cdr x))))
186 (value
187 (display separator)
188 (display (get-ref (cdr x)))))
189 (if (and shadow
190 (not (eq? (module-ref module
191 (car x))
192 (module-ref (current-module)
193 (car x)))))
194 (display " shadowed"))
195 (newline)
196 )))
197 oblist))
198 obarray))
199 obarrays get-refs)))
200 modules))))
68aed3ea
MD
201
202(define-public (apropos-internal rgx)
203 "Return a list of accessible variable names."
3bdca000
MD
204 (apropos-fold (lambda (module name var data)
205 (cons name data))
206 '()
207 rgx
208 (apropos-fold-accessible (current-module))))
209
210(define-public (apropos-fold proc init rgx folder)
211 "Folds PROCEDURE over bindings matching third arg REGEXP.
212
213Result is
214
215 (PROCEDURE MODULE1 NAME1 VALUE1
216 (PROCEDURE MODULE2 NAME2 VALUE2
217 ...
218 (PROCEDURE MODULEn NAMEn VALUEn INIT)))
219
220where INIT is the second arg to `apropos-fold'.
221
222Fourth arg FOLDER is one of
223
224 (apropos-fold-accessible MODULE) ;fold over bindings accessible in MODULE
225 apropos-fold-exported ;fold over all exported bindings
226 apropos-fold-all ;fold over all bindings"
227 (let ((match (make-regexp rgx))
228 (recorded (make-vector 61 '())))
229 (let ((fold-module
230 (lambda (module data)
231 (let* ((obarray-filter
232 (lambda (name val data)
233 (if (and (regexp-exec match name)
234 (not (hashq-get-handle recorded name)))
235 (begin
236 (hashq-set! recorded name #t)
237 (proc module name val data))
238 data)))
239 (module-filter
240 (lambda (name var data)
241 (obarray-filter name (variable-ref var) data))))
242 (cond ((or (eq? module the-scm-module)
243 (eq? module the-root-module))
244 (hash-fold obarray-filter
245 (hash-fold obarray-filter
246 data
247 (builtin-bindings))
248 (builtin-weak-bindings)))
249 (module (hash-fold module-filter
250 data
251 (module-obarray module)))
252 (else data))))))
253 (folder fold-module init))))
254
255(define (make-fold-modules init-thunk traverse extract)
256 "Return procedure capable of traversing a forest of modules.
257The forest traversed is the image of the forest generated by root
258modules returned by INIT-THUNK and the generator TRAVERSE.
259It is an image under the mapping EXTRACT."
260 (lambda (fold-module init)
261 (let rec ((data init)
262 (modules (init-thunk)))
263 (do ((modules modules (cdr modules))
264 (data data (rec (fold-module (extract (car modules)) data)
265 (traverse (car modules)))))
266 ((null? modules) data)))))
267
268(define-public (apropos-fold-accessible module)
269 (make-fold-modules (lambda () (list module))
270 module-uses
271 (lambda (x) x)))
272
273(define (root-modules)
274 (cons the-root-module
275 (submodules (nested-ref the-root-module '(app modules)))))
276
277(define (submodules m)
278 (hash-fold (lambda (name var data)
279 (let ((obj (variable-ref var)))
280 (if (and (module? obj)
281 (eq? (module-kind obj) 'directory))
282 (cons obj data)
283 data)))
284 '()
285 (module-obarray m)))
286
287(define-public apropos-fold-exported
288 (make-fold-modules root-modules submodules module-public-interface))
289
290(define-public apropos-fold-all
291 (make-fold-modules root-modules submodules (lambda (x) x)))
7cfae7e6
MD
292
293(define-public (source obj)
294 (cond ((procedure? obj) (procedure-source obj))
295 ((macro? obj) (procedure-source (macro-transformer obj)))
296 (else #f)))
4a9f464e
MD
297
298(define-public (arity obj)
299 (let ((arity (procedure-property obj 'arity)))
300 (display (car arity))
301 (cond ((caddr arity)
302 (display " or more"))
303 ((not (zero? (cadr arity)))
304 (display " required and ")
305 (display (cadr arity))
306 (display " optional")))
307 (if (and (not (caddr arity))
308 (= (car arity) 1)
309 (<= (cadr arity) 1))
310 (display " argument")
311 (display " arguments"))
312 (if (closure? obj)
313 (let ((formals (cadr (procedure-source obj))))
314 (if (pair? formals)
315 (begin
316 (display ": `")
317 (display (car formals))
318 (let loop ((ls (cdr formals)))
319 (cond ((null? ls)
320 (display #\'))
321 ((not (pair? ls))
322 (display "', the rest in `")
323 (display ls)
324 (display #\'))
325 (else
326 (if (pair? (cdr ls))
327 (display "', `")
328 (display "' and `"))
329 (display (car ls))
330 (loop (cdr ls))))))
331 (begin
332 (display " in `")
333 (display formals)
334 (display #\')))))
335 (display ".\n")))
6ae34994
MD
336
337(define-public system-module
338 (procedure->syntax
339 (lambda (exp env)
340 (let* ((m (nested-ref the-root-module
341 (append '(app modules) (cadr exp)))))
342 (if (not m)
343 (error "Couldn't find any module named" (cadr exp)))
344 (let ((s (not (procedure-property (module-eval-closure m)
345 'system-module))))
346 (set-system-module! m s)
347 (string-append "Module " (symbol->string (module-name m))
348 " is now a " (if s "system" "user") " module."))))))