;;;; This file provide various documentation functions, taking some existing
;;;; XLISP-PLUS functionality and merging it with new Common Lisp functions.
; Author -- Tom Almy, 10/96
;;; It supercedes glos.lsp. Do not load glos.lsp if this file is used!
;;; This file adds these new functions:
;;; DOCUMENTATION -- get/set documentation string.
;;; This function will fetch glossary info
;;; for functions and variables defined in glos.txt (see description of GLOS
;;; below) as well provided via DOCUMENTATION used with SETF or with
;;; the DEF* macros listed below.
;;; The documentation types variable, function, structure, and setf are stored
;;; in properties named %doc-function, %doc-structure, %doc-variable, and
;;; %doc-setf. In addition, documentation type type with property %doc-type
;;; is provided for completeness.
;;; DEFCONSTANT, DEFPARAMETER, DEFVAR, DEFUN, DEFMACRO, DEFSTRUCT, and DEFSETF
;;; are modified to have the documentation arguments functional.
;;; GLOS -- glossary function
; GLOS requires the package and multiple value return facilities to
; work, and uses a file called glos.txt which is the glossary portion
; of the XLISP documentation file When loaded for the first time, it
; adds documentation marks for all functions which are defined in
; glos.txt and are in the XLISP package. This property is the
; displacement into the file. When a glossary lookup occurs (or the
; DOCUMENTATION function is used) the file itself is referenced. By
; operating this way, very little space is taken for this feature.
; There are two user-accessable symbols. tools:*glospaging* is a variable
; which causes the output to "page" (pause for user response) at every
; screenful. Set it to NIL to defeat this feature or to the number of lines
; per page to enable.
; The main entry point is the function tools:glos. When given an
; argument that is a function symbol, it will look up the glossary
; definition. If the symbol is not visible, or if a second non-nil
; argument is supplied, the name will be passed to APROPOS, and the
; glossary definitions for all matching symbols will be displayed
; For instance (glos :car) or (glos 'car) will show the definition for
; the CAR function, while (glos 'car t) or (glos "car") will show that
; of MAPCAR as well. (glos "X") will give the glossary listing of all
; functions with names containing an X character.
#-:packages
(error "This utility was written asuming the package facility is in use")
#-:mulvals
(error "This utility was written asuming multiple value return is in use")
#-:common
(load "common") ;; make sure these are defined first
(in-package "XLISP")
(export '(documentation variable function structure setf))
(in-package "TOOLS")
; This is the glos.lsp package, modified to be integrated with
; DOCUMENTATION. Glos.lsp should not be loaded if this file is used!
;
(export '(glos *glospaging*))
(import '(xlisp::%doc-function xlisp::%doc-variable))
(defvar *glosfilename*)
(setq *glosfilename* nil)
; We will look things up while loading
; so we can toss all the code when done
(unless *glosfilename*
(format t "~&Building glossary references---")
(let ((lpar #\()
(rpar #\))
(dot #\.)
(*pos* 0)
symbol)
(labels
(
(xposition (chr str &aux (pos (position chr str)))
(if pos pos (length str)))
(seek-next-fcn (strm)
(do ((thispos *pos* (file-position strm))
(text (read-line strm nil) (read-line strm nil)))
((null text) nil)
(when (and (> (length text) 1)
(or (char= lpar (char text 0))
(char= dot (char text 0))))
(setf *pos* thispos)
(return-from seek-next-fcn
(cons (char= dot (char text 0))
(subseq text 1 (min (xposition rpar text)
(xposition #\space text)))))))))
;; The body of the code that does the work:
(unless (open "glos.txt" :direction :probe)
(error "Could not find glossary file glos.txt"))
(with-open-file
(strm "glos.txt")
(setq *glosfilename* (truename strm))
(do ((name (seek-next-fcn strm) (seek-next-fcn strm)))
((null name) nil)
(setq symbol (find-symbol (string-upcase (cdr name))))
(unless symbol
(if (string-equal (cdr name) "nil")
(setf (get nil '%doc-variable) (abs *pos*))
(format t
"~&Documented symbol ~s not found in XLISP.~%"
(cdr name))))
(when symbol
;; (format t "~s ~s" symbol *pos*)
(setf (get symbol (if (car name)
'%doc-variable
'%doc-function))
(abs *pos*)))))
;; Check for functions & vars in package XLISP that aren't documented
(format t "~&Not documented, but found in XLISP:")
(do-external-symbols
(x :xlisp)
(when (or (and (fboundp x) (not (get x '%doc-function)))
(and (specialp x) (not (get x '%doc-variable))))
(format t "~s " x)))
(format t "~&")
))) ;; Ends the Flet, let, and unless
(defvar *linecount*)
(defvar *glospaging* 23)
(defun linechk ()
(when (and *glospaging*
(> (incf *linecount*) *glospaging*))
(setq *linecount* 0)
(if (y-or-n-p "--PAUSED-- Continue?")
(fresh-line)
(throw 'getoutahere))))
(defun ppstring (string &aux (strm (make-string-input-stream string)))
(do ((line (read-line strm nil) (read-line strm nil)))
((zerop (length line))
(linechk)
(format t "~%"))
(linechk)
(format t "~a~%" line)))
(defun glosx (val &aux (ostrm (make-string-output-stream)))
(with-open-file
(strm *glosfilename*)
(file-position strm (abs val))
(do ((line (read-line strm nil) (read-line strm nil)))
((zerop (length line))
(format ostrm "~%"))
(if (eq #\. (char line 0))
(format ostrm "~a~%" (subseq line 1))
(format ostrm "~a~%" line))))
(get-output-stream-string ostrm))
(defun glos (symbol &optional matchall
&aux val val2 val3 (sym (string symbol)))
(catch
'getoutahere
(setq *linecount* 0)
(if (and (null matchall) (setq val (find-symbol sym)))
(progn (when (setq val2 (documentation val 'function))
(ppstring val2))
(when (setq val3 (documentation val 'variable))
(ppstring val3))
(unless (or val2 val3)
(format t "No information on ~a~%" sym)))
(progn
(setq val
(do ((list (apropos-list sym) (cdr list))
(result nil result))
((null list) result)
(when (setq val2 (documentation (car list) 'function))
(when (not (member val2 result :test #'string-equal))
(push val2 result)))
(when (setq val2 (documentation (car list) 'variable))
(when (not (member val2 result :test #'string-equal))
(push val2 result)))))
(if (zerop (length val))
(format t "No matches for ~a~%" symbol)
(map nil #'ppstring val)))))
(values)
)
(in-package "XLISP")
(defun documentation (sym type &aux value)
(unless (symbolp sym) (error "bad argument type - ~s" sym))
(setq
value
(case type
(variable (get sym '%doc-variable))
(function (get sym '%doc-function))
(structure (get sym '%doc-structure))
(setf (get sym '%doc-setf))
(type (get syp '%doc-type))
(t (error "invalid documentation type - ~s" type))))
(if (numberp value)
(tools::glosx value)
value))
(defsetf documentation (sym type) (val)
(case (eval type)
(variable `(setf (get ,sym '%doc-variable) ,val))
(function `(setf (get ,sym '%doc-function) ,val))
(structure `(setf (get ,sym '%doc-structure) ,val))
(setf `(setf (get ,sym '%doc-setf) ,val))
(type `(type (get ,sym '%doc-type) ,val))
(t (error "invalid documentation type - ~s" type))))
;; If we haven't done it before, save function binding of defining words
(unless (fboundp 'old-defun)
(setf (symbol-function 'old-defun)
(symbol-function 'defun)))
(unless (fboundp 'old-defmacro)
(setf (symbol-function 'old-defmacro)
(symbol-function 'defmacro)))
(unless (fboundp 'old-defvar)
(setf (symbol-function 'old-defvar)
(symbol-function 'defvar)))
(unless (fboundp 'old-defparameter)
(setf (symbol-function 'old-defparameter)
(symbol-function 'defparameter)))
(unless (fboundp 'old-defconstant)
(setf (symbol-function 'old-defconstant)
(symbol-function 'defconstant)))
(unless (fboundp 'old-defstruct)
(setf (symbol-function 'old-defstruct)
(symbol-function 'defstruct)))
;; Redefine defun, defmacro, defvar, defconstant, defparameter, and defstruct
;; to update the property list and then do the original function.
;; In the case of defmacro and defvar, the documentation string is removed
;; from the definition.
(defmacro defun (&rest arglist)
(if (and (stringp (third arglist)) (cdddr arglist))
(progn
(unless (symbolp (first arglist))
(error "bad argument type - ~s" (first arglist)))
(setf (get (first arglist) '%doc-function) (third arglist))
`(old-defun ,(first arglist)
,(second arglist)
,@(cdddr arglist)))
`(old-defun ,@arglist)))
(defmacro defmacro (&rest arglist)
(if (and (stringp (third arglist)) (cdddr arglist))
(progn
(unless (symbolp (first arglist))
(error "bad argument type - ~s" (first arglist)))
(setf (get (first arglist) '%doc-function) (third arglist))
`(old-defmacro ,(first arglist)
,(second arglist)
,@(cdddr arglist)))
`(old-defmacro ,@arglist)))
(defmacro defvar (&rest arglist)
(when (stringp (third arglist))
(progn
(unless (symbolp (first arglist))
(error "bad argument type - ~s" (first arglist)))
(setf (get (first arglist) '%doc-variable) (third arglist))))
`(old-defvar ,@arglist))
(defmacro defparameter (&rest arglist)
(when (stringp (third arglist))
(progn
(unless (symbolp (first arglist))
(error "bad argument type - ~s" (first arglist)))
(setf (get (first arglist) '%doc-variable) (third arglist))))
`(old-defparameter ,@arglist))
(defmacro defconstant (&rest arglist)
(when (stringp (third arglist))
(progn
(unless (symbolp (first arglist))
(error "bad argument type - ~s" (first arglist)))
(setf (get (first arglist) '%doc-variable) (third arglist))))
`(old-defconstant ,@arglist))
(defmacro defstruct (&rest arglist)
(when (stringp (second arglist))
(let ((sym (if (consp (first arglist))
(caar arglist)
(first arglist))))
(unless (symbolp sym)
(error "bad argument type - ~s" (first arglist)))
(setf (get sym '%doc-structure) (second arglist))))
`(old-defstruct ,@arglist))
syntax highlighted by Code2HTML, v. 0.9.1