1 ;;;; This file provide various documentation functions, taking some existing
2 ;;;; XLISP-PLUS functionality and merging it with new Common Lisp functions.
4 ; Author -- Tom Almy, 10/96
6 ;;; It supercedes glos.lsp. Do not load glos.lsp if this file is used!
8 ;;; This file adds these new functions:
10 ;;; DOCUMENTATION -- get/set documentation string.
11 ;;; This function will fetch glossary info
12 ;;; for functions and variables defined in glos.txt (see description of GLOS
13 ;;; below) as well provided via DOCUMENTATION used with SETF or with
14 ;;; the DEF* macros listed below.
16 ;;; The documentation types variable, function, structure, and setf are stored
17 ;;; in properties named %doc-function, %doc-structure, %doc-variable, and
18 ;;; %doc-setf. In addition, documentation type type with property %doc-type
19 ;;; is provided for completeness.
21 ;;; DEFCONSTANT, DEFPARAMETER, DEFVAR, DEFUN, DEFMACRO, DEFSTRUCT, and DEFSETF
22 ;;; are modified to have the documentation arguments functional.
24 ;;; GLOS -- glossary function
26 ; GLOS requires the package and multiple value return facilities to
27 ; work, and uses a file called glos.txt which is the glossary portion
28 ; of the XLISP documentation file When loaded for the first time, it
29 ; adds documentation marks for all functions which are defined in
30 ; glos.txt and are in the XLISP package. This property is the
31 ; displacement into the file. When a glossary lookup occurs (or the
32 ; DOCUMENTATION function is used) the file itself is referenced. By
33 ; operating this way, very little space is taken for this feature.
35 ; There are two user-accessable symbols. tools:*glospaging* is a variable
36 ; which causes the output to "page" (pause for user response) at every
37 ; screenful. Set it to NIL to defeat this feature or to the number of lines
40 ; The main entry point is the function tools:glos. When given an
41 ; argument that is a function symbol, it will look up the glossary
42 ; definition. If the symbol is not visible, or if a second non-nil
43 ; argument is supplied, the name will be passed to APROPOS, and the
44 ; glossary definitions for all matching symbols will be displayed
46 ; For instance (glos :car) or (glos 'car) will show the definition for
47 ; the CAR function, while (glos 'car t) or (glos "car") will show that
48 ; of MAPCAR as well. (glos "X") will give the glossary listing of all
49 ; functions with names containing an X character.
53 (error "This utility was written asuming the package facility is in use")
56 (error "This utility was written asuming multiple value return is in use")
59 (load "common") ;; make sure these are defined first
63 (export '(documentation variable function structure setf
))
68 ; This is the glos.lsp package, modified to be integrated with
69 ; DOCUMENTATION. Glos.lsp should not be loaded if this file is used!
72 (export '(glos *glospaging
*))
74 (import '(xlisp::%doc-function xlisp
::%doc-variable
))
76 (defvar *glosfilename
*)
78 (setq *glosfilename
* nil
)
80 ; We will look things up while loading
81 ; so we can toss all the code when done
83 (unless *glosfilename
*
84 (format t
"~&Building glossary references---")
94 (xposition (chr str
&aux
(pos (position chr str
)))
95 (if pos pos
(length str
)))
98 (do ((thispos *pos
* (file-position strm
))
99 (text (read-line strm nil
) (read-line strm nil
)))
101 (when (and (> (length text
) 1)
102 (or (char= lpar
(char text
0))
103 (char= dot
(char text
0))))
105 (return-from seek-next-fcn
106 (cons (char= dot
(char text
0))
107 (subseq text
1 (min (xposition rpar text
)
108 (xposition #\space text
)))))))))
110 ;; The body of the code that does the work:
111 (unless (open "glos.txt" :direction
:probe
)
112 (error "Could not find glossary file glos.txt"))
115 (setq *glosfilename
* (truename strm
))
116 (do ((name (seek-next-fcn strm
) (seek-next-fcn strm
)))
118 (setq symbol
(find-symbol (string-upcase (cdr name
))))
120 (if (string-equal (cdr name
) "nil")
121 (setf (get nil
'%doc-variable
) (abs *pos
*))
123 "~&Documented symbol ~s not found in XLISP.~%"
126 ;; (format t "~s ~s" symbol *pos*)
127 (setf (get symbol
(if (car name
)
131 ;; Check for functions & vars in package XLISP that aren't documented
132 (format t
"~&Not documented, but found in XLISP:")
135 (when (or (and (fboundp x
) (not (get x
'%doc-function
)))
136 (and (specialp x
) (not (get x
'%doc-variable
))))
140 ))) ;; Ends the Flet, let, and unless
143 (defvar *glospaging
* 23)
146 (when (and *glospaging
*
147 (> (incf *linecount
*) *glospaging
*))
149 (if (y-or-n-p "--PAUSED-- Continue?")
151 (throw 'getoutahere
))))
153 (defun ppstring (string &aux
(strm (make-string-input-stream string
)))
154 (do ((line (read-line strm nil
) (read-line strm nil
)))
155 ((zerop (length line
))
159 (format t
"~a~%" line
)))
161 (defun glosx (val &aux
(ostrm (make-string-output-stream)))
163 (strm *glosfilename
*)
164 (file-position strm
(abs val
))
165 (do ((line (read-line strm nil
) (read-line strm nil
)))
166 ((zerop (length line
))
168 (if (eq #\.
(char line
0))
169 (format ostrm
"~a~%" (subseq line
1))
170 (format ostrm
"~a~%" line
))))
171 (get-output-stream-string ostrm
))
173 (defun glos (symbol &optional matchall
174 &aux val val2 val3
(sym (string symbol
)))
178 (if (and (null matchall
) (setq val
(find-symbol sym
)))
179 (progn (when (setq val2
(documentation val
'function
))
181 (when (setq val3
(documentation val
'variable
))
183 (unless (or val2 val3
)
184 (format t
"No information on ~a~%" sym
)))
187 (do ((list (apropos-list sym
) (cdr list
))
190 (when (setq val2
(documentation (car list
) 'function
))
191 (when (not (member val2 result
:test
#'string-equal
))
193 (when (setq val2
(documentation (car list
) 'variable
))
194 (when (not (member val2 result
:test
#'string-equal
))
195 (push val2 result
)))))
197 (if (zerop (length val
))
198 (format t
"No matches for ~a~%" symbol
)
199 (map nil
#'ppstring val
)))))
204 (defun documentation (sym type
&aux value
)
205 (unless (symbolp sym
) (error "bad argument type - ~s" sym
))
209 (variable (get sym
'%doc-variable
))
210 (function (get sym
'%doc-function
))
211 (structure (get sym
'%doc-structure
))
212 (setf (get sym
'%doc-setf
))
213 (type (get syp
'%doc-type
))
214 (t (error "invalid documentation type - ~s" type
))))
219 (defsetf documentation
(sym type
) (val)
221 (variable `(setf (get ,sym
'%doc-variable
) ,val
))
222 (function `(setf (get ,sym
'%doc-function
) ,val
))
223 (structure `(setf (get ,sym
'%doc-structure
) ,val
))
224 (setf `(setf (get ,sym
'%doc-setf
) ,val
))
225 (type `(type (get ,sym
'%doc-type
) ,val
))
226 (t (error "invalid documentation type - ~s" type
))))
228 ;; If we haven't done it before, save function binding of defining words
230 (unless (fboundp 'old-defun
)
231 (setf (symbol-function 'old-defun
)
232 (symbol-function 'defun
)))
233 (unless (fboundp 'old-defmacro
)
234 (setf (symbol-function 'old-defmacro
)
235 (symbol-function 'defmacro
)))
236 (unless (fboundp 'old-defvar
)
237 (setf (symbol-function 'old-defvar
)
238 (symbol-function 'defvar
)))
239 (unless (fboundp 'old-defparameter
)
240 (setf (symbol-function 'old-defparameter
)
241 (symbol-function 'defparameter
)))
242 (unless (fboundp 'old-defconstant
)
243 (setf (symbol-function 'old-defconstant
)
244 (symbol-function 'defconstant
)))
245 (unless (fboundp 'old-defstruct
)
246 (setf (symbol-function 'old-defstruct
)
247 (symbol-function 'defstruct
)))
249 ;; Redefine defun, defmacro, defvar, defconstant, defparameter, and defstruct
250 ;; to update the property list and then do the original function.
251 ;; In the case of defmacro and defvar, the documentation string is removed
252 ;; from the definition.
254 (defmacro defun
(&rest arglist
)
255 (if (and (stringp (third arglist
)) (cdddr arglist
))
257 (unless (symbolp (first arglist
))
258 (error "bad argument type - ~s" (first arglist
)))
259 (setf (get (first arglist
) '%doc-function
) (third arglist
))
260 `(old-defun ,(first arglist
)
263 `(old-defun ,@arglist
)))
265 (defmacro defmacro
(&rest arglist
)
266 (if (and (stringp (third arglist
)) (cdddr arglist
))
268 (unless (symbolp (first arglist
))
269 (error "bad argument type - ~s" (first arglist
)))
270 (setf (get (first arglist
) '%doc-function
) (third arglist
))
271 `(old-defmacro ,(first arglist
)
274 `(old-defmacro ,@arglist
)))
276 (defmacro defvar
(&rest arglist
)
277 (when (stringp (third arglist
))
279 (unless (symbolp (first arglist
))
280 (error "bad argument type - ~s" (first arglist
)))
281 (setf (get (first arglist
) '%doc-variable
) (third arglist
))))
282 `(old-defvar ,@arglist
))
285 (defmacro defparameter
(&rest arglist
)
286 (when (stringp (third arglist
))
288 (unless (symbolp (first arglist
))
289 (error "bad argument type - ~s" (first arglist
)))
290 (setf (get (first arglist
) '%doc-variable
) (third arglist
))))
291 `(old-defparameter ,@arglist
))
294 (defmacro defconstant
(&rest arglist
)
295 (when (stringp (third arglist
))
297 (unless (symbolp (first arglist
))
298 (error "bad argument type - ~s" (first arglist
)))
299 (setf (get (first arglist
) '%doc-variable
) (third arglist
))))
300 `(old-defconstant ,@arglist
))
302 (defmacro defstruct
(&rest arglist
)
303 (when (stringp (second arglist
))
304 (let ((sym (if (consp (first arglist
))
307 (unless (symbolp sym
)
308 (error "bad argument type - ~s" (first arglist
)))
309 (setf (get sym
'%doc-structure
) (second arglist
))))
310 `(old-defstruct ,@arglist
))