home *** CD-ROM | disk | FTP | other *** search
- ;-*- mode:lisp; package:boxer;base: 10.; fonts:cptfont -*-
-
- ;; (C) Copyright 1985 Massachusetts Institute of Technology
- ;;
- ;; Permission to use, copy, modify, distribute, and sell this software
- ;; and its documentation for any purpose is hereby granted without fee,
- ;; provided that the above copyright notice appear in all copies and that
- ;; both that copyright notice and this permission notice appear in
- ;; supporting documentation, and that the name of M.I.T. not be used in
- ;; advertising or publicity pertaining to distribution of the software
- ;; without specific, written prior permission. M.I.T. makes no
- ;; representations about the suitability of this software for any
- ;; purpose. It is provided "as is" without express or implied warranty.
- ;;
-
- ;;;; The Boxer Manual Compiler
- ;;;
- ;;; How to convert from BOXER structure into a TEX/LATEX file
- ;;;
- ;;; This code is hacked up specifically for the BOXER Manual. If you want to wirte your
- ;;; own conversion routines, the core of the code (should be fairly portable) is in the
- ;;; functions TEXIFY-BOX, TEXIFY-ROW and TEXIFY-CHA. The functions which convert BOXER
- ;;; structure into TeX files which use the TeX Box drawing macros are TEXIFY-BOXER-EXAMPLE-BOX
- ;;; and TEXIFY-BOXER-EXAMPLE-ROW.
- ;;;
- ;;; The following conventions for the manual (in Boxer) are assumed:
- ;;;
- ;;; In general, successive levels of box correspond to successive levels of formatting
- ;;; i.e. \chapter, \section, etc. with the name of the Box as the name of the section
- ;;;
- ;;; Individual characters in boxer can be made to expand into arbitrary sequences of
- ;;; characters in the corresponding TeX File by pushing a pair consisting of the character
- ;;; and a function to be FUNCALLed onto the variable *SPECIAL-TEX-CHA-HANDLER-ALIST*. The
- ;;; function is called woth 2 args, the character being dispatched on and the output stream
- ;;;
- ;;; In the same way, boxes can also be expanded into an arbitrary sequence of TeX commands
- ;;; by pushing a consisting of the BOX and a function (2 args also) onto the variable
- ;;; *SPECIAL-TEX-BOX-HANDLER-ALIST*. The list is searched using BOX-EQUAL?
- ;;;
- ;;; BOXER Functions are documented as Label Pairs consisting of
- ;;; FUNCTION-NAME : <Function Documentation Box>
- ;;; The <Function Documentation Box> consists of a first line which is composed of the name
- ;;; of the function and its args, The args are enclosed in angle brackets.
- ;;; Successive lines consist of text and then a line with "***" on it after which are examples
-
-
-
- ;;; Some useful variables...
-
- (DEFVAR *SECTION-BOX-LEVEL-ALIST* '((1 . "\chapter") (2 . "\section") (3 . "\subsection")
- (4 . "\subsubsection")))
-
- (DEFVAR *BOX-TYPE-TEX-COMMAND-ALIST* '((DOIT-BOX . "\doitbox")
- (DATA-BOX . "\databox")
- (GRAPHICS-BOX . "\graphicsbox")
- (GRAPHICS-DATA-BOX . "\gdbox")
- (SPRITE-BOX . "\spritebox")
- (LL-BOX . "\llbox")))
-
- (DEFVAR *TEX-MINIMUM-BOX-SIZE* "3em,1.6em")
-
- (DEFVAR *TEX-GRAPHICS-BOX-SIZE* "200pt,150pt")
-
- (DEFVAR *SPECIAL-TEX-CHA-HANDLER-ALIST* '((#/< . MATH-MODE-CHARACTER)
- (#/> . MATH-MODE-CHARACTER)
- (#/= . MATH-MODE-CHARACTER)
- (#/| . MATH-MODE-CHARACTER)
- (#/^ . COMMAND-CHARACTER)
- (#/ . GEQ-CHARACTER)
- (#/ . LEQ-CHARACTER)
- (#/* . AST-CHARACTER)))
-
- (DEFVAR *SPECIAL-TEX-BOX-HANDLER-ALIST* `((,(MAKE-BOX '(("BOXER"))) . BOXER-NAME-HANDLER)
- (,(MAKE-BOX '(("TRUE"))) . TEX-TRUE-BOX)
- (,(MAKE-BOX '(("FALSE"))) . TEX-FALSE-BOX)))
-
- (DEFVAR *FONT-CHANGE-ALIST* '((0 . "\rm") (1 . "\em") (2 . "\sf") (3 . "\em")))
-
- (DEFVAR WITHIN-FUNCTION-DOC NIL "Within a function definition environment")
-
- (DEFVAR CURRENT-FONT NIL)
-
- ;;; we set up a separate readtable becaue we keep losing on things like parens...
-
- (DEFVAR *BOXER-TEX-READTABLE* (COPY-READTABLE SI:INITIAL-READTABLE))
-
- (DEFMACRO WITH-TEX-READTABLE (&BODY BODY)
- `(PROGV '(*BOXER-READTABLE*) `(,*BOXER-TEX-READTABLE*)
- . ,BODY))
-
- (EVAL-WHEN (LOAD)
-
- ;;; give us the minimal boxer syntax and make everything else alphabetic
- (SET-SYNTAX-FROM-CHAR *STRT-ROW-CODE* #/( *BOXER-TEX-READTABLE*)
- (SET-SYNTAX-FROM-CHAR *STOP-ROW-CODE* #/) *BOXER-TEX-READTABLE*)
- (SET-SYNTAX-MACRO-CHAR *STRT-BOX-CODE*
- 'BOXTEX-STRT-BOX-READER-MACRO
- *BOXER-TEX-READTABLE*)
- ;(SET-SYNTAX-MACRO-CHAR *STOP-BOX-CODE*
- ; 'BOXER-STOP-BOX-READER-MACRO
- ; *BOXER-READTABLE*)
- (SET-SYNTAX-MACRO-CHAR #/:
- 'BOXTEX-LABELLING-CHA-READER-MACRO
- *BOXER-TEX-READTABLE*)
- (SET-SYNTAX-MACRO-CHAR #/,
- 'BOXTEX-FUNCTIONDOC-SEPARATOR-READER-MACRO
- *BOXER-TEX-READTABLE*)
- (SET-SYNTAX-FROM-DESCRIPTION #/| 'SI:ALPHABETIC *BOXER-TEX-READTABLE*)
- (SET-SYNTAX-FROM-DESCRIPTION #/; 'SI:ALPHABETIC *BOXER-TEX-READTABLE*)
- (SET-SYNTAX-FROM-DESCRIPTION #/` 'SI:ALPHABETIC *BOXER-TEX-READTABLE*)
- (SET-SYNTAX-FROM-DESCRIPTION #/( 'SI:ALPHABETIC *BOXER-TEX-READTABLE*)
- (SET-SYNTAX-FROM-DESCRIPTION #/) 'SI:ALPHABETIC *BOXER-TEX-READTABLE*)
- (SET-SYNTAX-FROM-DESCRIPTION #/# 'SI:ALPHABETIC *BOXER-TEX-READTABLE*)
- (SET-SYNTAX-FROM-DESCRIPTION #// 'SI:ALPHABETIC *BOXER-TEX-READTABLE*)
- (SET-SYNTAX-FROM-DESCRIPTION #/' 'SI:ALPHABETIC *BOXER-TEX-READTABLE*)
- (SET-SYNTAX-FROM-DESCRIPTION #/. 'SI:ALPHABETIC *BOXER-TEX-READTABLE*)
-
- )
-
- ;;;; reader macros
-
- (DEFUN BOXTEX-FUNCTIONDOC-SEPARATOR-READER-MACRO (LIST IGNORE)
- (VALUES (NCONC LIST (NCONS :FUNCTION-SEPARATOR)) NIL T))
-
- (DEFUN BOXTEX-STRT-BOX-READER-MACRO (IGNORE STREAM)
- (MULTIPLE-VALUE-BIND (VAL ERROR-P)
- (IGNORE-ERRORS (FUNCALL STREAM ':TYI-A-BOX))
- (IF ERROR-P
- (VALUES '[ NIL NIL)
- (VALUES VAL NIL NIL))))
-
- (DEFUN BOXTEX-LABELLING-CHA-READER-MACRO (LIST-SO-FAR STREAM)
- (LET ((NEXT-NONBLANK-CHAR (TYIPEEK T STREAM *STOP-ROW-CODE*)))
- (IF (EQ LIST-SO-FAR ':TOPLEVEL)
- (VALUES (NCONS (MAKE-LABEL-PAIR NIL
- (IF (= NEXT-NONBLANK-CHAR *STOP-ROW-CODE*)
- ':NO-ELEMENT
- (READ STREAM ':NO-ELEMENT))))
- NIL T)
- (LET* ((LAST (get-sensible-last-thing-from list-so-far))
- (LAST-ELEMENT (CAR LAST)))
- (RPLACA LAST (MAKE-LABEL-PAIR LAST-ELEMENT
- (IF (= NEXT-NONBLANK-CHAR *STOP-ROW-CODE*)
- ':NO-ELEMENT
- (READ STREAM ':NO-ELEMENT))))
- (VALUES LIST-SO-FAR NIL T)))))
-
-
-
- (DEFUN TEXIFY-CHA (CHA STREAM)
- (LET ((SPECIAL-CHA-HANDLER (CDR (ASSQ (CHA-CODE CHA) *SPECIAL-TEX-CHA-HANDLER-ALIST*))))
- (WHEN (AND CURRENT-FONT
- ( (FONT-NO CHA) CURRENT-FONT)
- (ASSQ (FONT-NO CHA) *FONT-CHANGE-ALIST*))
- (SETQ CURRENT-FONT (FONT-NO CHA))
- (FORMAT STREAM "~A{}" (CDR (ASSQ (FONT-NO CHA) *FONT-CHANGE-ALIST*))))
- (IF (NULL SPECIAL-CHA-HANDLER)
- (SEND STREAM :TYO CHA)
- (FUNCALL SPECIAL-CHA-HANDLER CHA STREAM))))
-
- (DEFUN COLLECT-ARGS-FOR-FUNCTION-DECLARATION (ENTRIES)
- (DECLARE (VALUES ARGS REST-OF-ENTRIES))
- (LOOP WITH ARGS = NIL
- FOR REST = ENTRIES THEN (CDR REST)
- FOR ARG = (CAR REST)
- UNTIL (NULL REST)
- WHEN (EQ ARG ':FUNCTION-SEPARATOR)
- RETURN (VALUES ARGS (CDR REST))
- DO (SETQ ARGS (APPEND ARGS (NCONS ARG)))
- FINALLY
- (RETURN (VALUES ARGS NIL))))
-
- (DEFUN TEXIFY-FUNCTION-DECLARATION-ENTRIES (ENTRIES STREAM)
- (FORMAT STREAM "\fcn{")
- (DOLIST (CHA (LISTARRAY (STRING (CAR ENTRIES))))
- (TEXIFY-CHA CHA STREAM))
- (FORMAT STREAM "}")
- (MULTIPLE-VALUE-BIND (ARGS REST)
- (COLLECT-ARGS-FOR-FUNCTION-DECLARATION (CDR ENTRIES))
- (DOLIST (ARG ARGS)
- (FORMAT STREAM "\argument{")
- (DOLIST (CHA (LISTARRAY (STRING ARG)))
- (TEXIFY-CHA CHA STREAM))
- (FORMAT STREAM "} "))
- (UNLESS (NULL REST)
- (FORMAT STREAM ", ")
- (TEXIFY-FUNCTION-DECLARATION-ENTRIES REST STREAM))))
-
- (DEFUN TEXIFY-FUNCTION-DECLARATION-ROW (FUNCTION-ROW STREAM)
- (FORMAT STREAM "~%~%\functiondoc{")
- (TEXIFY-FUNCTION-DECLARATION-ENTRIES (TELL FUNCTION-ROW :ENTRIES) STREAM)
- (FORMAT STREAM "}~%~%"))
-
- (DEFUN TEXIFY-FUNCTION-DOC (LABEL-PAIR OUTPUT-STREAM)
- (LET ((BOX (LABEL-PAIR-ELEMENT LABEL-PAIR))
- (WITHIN-FUNCTION-DOC T))
- (TEXIFY-FUNCTION-DECLARATION-ROW (TELL BOX :FIRST-INFERIOR-ROW) OUTPUT-STREAM)
- (LOOP WITH EXAMPLE-FLAG = NIL
- FOR ROW IN (CDR (TELL BOX :ROWS))
- FOR ROW-STRING = (TELL ROW :TEXT-STRING)
- WHEN (STRING-SEARCH "***" ROW-STRING)
- DO (SETQ EXAMPLE-FLAG T)
- (FORMAT OUTPUT-STREAM "~%\startboxerexample~%")
- DO (COND ((STRING-SEARCH "***" ROW-STRING))
- ((NULL EXAMPLE-FLAG) (TEXIFY-ROW ROW OUTPUT-STREAM))
- (T (TEXIFY-BOXER-EXAMPLE-ROW ROW OUTPUT-STREAM)))
- FINALLY
- (WHEN EXAMPLE-FLAG
- (FORMAT OUTPUT-STREAM "~%\stopboxerexample~%")))))
-
- (DEFUN CALCULATE-BOX-SIZE-FOR-TEX (BOX)
- "returns either a string <WIDTH>,<HEIGHT> or a s(for stretch) string"
- (COND ((GRAPHICS-BOX? BOX) *TEX-GRAPHICS-BOX-SIZE*)
- ((AND (= 1 (TELL BOX :LENGTH-IN-ROWS))
- (< (ROW-LENGTH-IN-CHAS (TELL BOX :FIRST-INFERIOR-ROW)) 5)
- (NULL (SUBSET #'BOX? (TELL (TELL BOX :FIRST-INFERIOR-ROW) :CHAS))))
- *TEX-MINIMUM-BOX-SIZE*)
- (T "s")))
-
- (DEFUN TEXIFY-BOXER-EXAMPLE-BOX (BOX STREAM)
- (LET ((HEADER (CDR (ASSQ (TYPEP BOX) *BOX-TYPE-TEX-COMMAND-ALIST*))))
- (WHEN (NOT (NULL (TELL BOX :NAME-ROW)))
- (FORMAT STREAM "\nametab{~A}" (TELL BOX :NAME)))
- (IF (NULL HEADER) (FERROR "There are currently no TeX macros for ~A's" (TYPEP BOX))
- (SEND STREAM :STRING-OUT HEADER)
- (FORMAT STREAM "[~A]{" (CALCULATE-BOX-SIZE-FOR-TEX BOX))
- (UNLESS (GRAPHICS-BOX? BOX)
- (DOLIST (ROW (TELL BOX :ROWS))
- (TEXIFY-BOXER-EXAMPLE-ROW ROW STREAM)))
- (SEND STREAM :TYO #/}))))
-
- (DEFUN TEXIFY-BOXER-EXAMPLE-ROW (ROW STREAM)
- (FORMAT STREAM "\row{")
- (LOOP WITH RETURN-FLAG = NIL
- FOR CHA IN (TELL ROW :CHAS)
- DO (COND ((BOX? CHA)
- (TEXIFY-BOXER-EXAMPLE-BOX CHA STREAM))
- ((CHAR= CHA #/|)
- (SETQ RETURN-FLAG T) (FORMAT STREAM "\return{"))
- (T (TEXIFY-CHA CHA STREAM)))
- FINALLY
- (WHEN RETURN-FLAG (SEND STREAM :TYO #/})))
- (SEND STREAM :TYO #/}))
-
- (DEFUN TEXIFY-ROW (ROW STREAM &OPTIONAL (LEVEL 0))
- (LET ((ENTRIES (IGNORE-ERRORS (TELL ROW :ENTRIES))) ;in case of special chas in the text
- (CHAS (TELL ROW :CHAS))) ;like {'s and }'s
- (LET ((CURRENT-FONT 0))
- (IF (NOT (NULL (SUBSET #'(LAMBDA (E) (AND (LABEL-PAIR? E)
- (BOX? (LABEL-PAIR-ELEMENT E))))
- ENTRIES)))
- (DOLIST (ENTRY ENTRIES)
- (COND ((AND (LABEL-PAIR? ENTRY) (BOX? (LABEL-PAIR-ELEMENT ENTRY)))
- (TEXIFY-FUNCTION-DOC ENTRY STREAM))
- ((BOX? ENTRY) (TEXIFY-BOX ENTRY STREAM (1+ LEVEL)))
- ((OR (NUMBERP ENTRY) (SYMBOLP ENTRY))
- (FORMAT STREAM "~A " ENTRY))
- (T (FERROR "unrecognized type in ~A" ROW))))
- (DOLIST (CHA CHAS)
- (COND ((BOX? CHA) (TEXIFY-BOX CHA STREAM (1+ LEVEL)))
- (T (TEXIFY-CHA CHA STREAM)))))
- (WHEN ( 0 CURRENT-FONT)
- ;;reset the current font for the next row
- (FORMAT STREAM "\rm"))
- (FORMAT STREAM "~%")))
- (FORMAT T ".")) ;a blip for the user
-
- (DEFUN TEXIFY-BOX (BOX OUTPUT-STREAM &OPTIONAL (LEVEL 0))
- (WITH-TEX-READTABLE
- (LET ((ROWS (TELL BOX :ROWS))
- (HEADING (CDR (ASSQ LEVEL *SECTION-BOX-LEVEL-ALIST*)))
- (BOX-HANDLER (CDR (ASS #'BOX-EQUAL? BOX *SPECIAL-TEX-BOX-HANDLER-ALIST*))))
- (IF (NOT (NULL BOX-HANDLER))
- (FUNCALL BOX-HANDLER BOX OUTPUT-STREAM)
- (COND ((AND (NOT (NULL HEADING)) (NOT (NULL (TELL BOX :NAME-ROW))))
- ;; named boxes are used for sectioning
- (TERPRI) (DOTIMES (I LEVEL) (FORMAT T " "))
- (FORMAT T "[~A : ~A" HEADING (TELL BOX :NAME))
- (TELL OUTPUT-STREAM :STRING-OUT (FORMAT NIL "~%~%~A{~A}~%~%"
- HEADING (TELL BOX :NAME))))
- (T (FORMAT T "~%[")))
- ;; now process the rows themselves
- (LOOP WITH EXAMPLE-FLAG = NIL
- FOR ROW IN ROWS
- FOR EXAMPLE-DELIMITER = (AND (NULL (TELL ROW :BOXES-IN-ROW))
- (STRING-SEARCH "***" (TELL ROW :TEXT-STRING)))
- WHEN EXAMPLE-DELIMITER
- DO (COND ((NULL EXAMPLE-FLAG)
- (SETQ EXAMPLE-FLAG T)
- (FORMAT OUTPUT-STREAM "~%\startboxerexample~%"))
- (T
- (SETQ EXAMPLE-FLAG NIL)
- (FORMAT OUTPUT-STREAM "~%\stopboxerexample~%")))
- DO (COND ((NOT (NULL EXAMPLE-DELIMITER)))
- ((NULL EXAMPLE-FLAG) (TEXIFY-ROW ROW OUTPUT-STREAM LEVEL))
- (T (TEXIFY-BOXER-EXAMPLE-ROW ROW OUTPUT-STREAM)))
- FINALLY
- (WHEN (NOT (NULL EXAMPLE-FLAG))
- (FORMAT OUTPUT-STREAM "~%\stopboxerexample~%")))
- (FORMAT T "]~%")))))
-
-
- (DEFUN MAKE-CHAPTER-FROM-BOX (BOX TITLE)
- (ZWEI:WITH-EDITOR-STREAM (S :PATHNAME TITLE)
- (TEXIFY-BOX BOX S 1)))
-
- ;;; special cha handlers
-
- (DEFUN MATH-MODE-CHARACTER (CHA STREAM)
- (FORMAT STREAM "$~C$" CHA))
-
- (DEFUN COMMAND-CHARACTER (CHA STREAM)
- (FORMAT STREAM "\~C{}" CHA))
-
- (DEFUN GEQ-CHARACTER (IGNORE STREAM)
- (FORMAT STREAM "$\geq$"))
-
- (DEFUN LEQ-CHARACTER (IGNORE STREAM)
- (FORMAT STREAM "$\leq$"))
-
- (DEFUN AST-CHARACTER (IGNORE STREAM)
- (FORMAT STREAM "$\ast$"))
-
- ;;; special box handlers
-
- (DEFUN BOXER-NAME-HANDLER (BOX STREAM)
- BOX ;bound but never used...
- (FORMAT STREAM "\BOXER "))
-
- (DEFUN TEX-TRUE-BOX (BOX STREAM)
- BOX
- (FORMAT STREAM "\true"))
-
- (DEFUN TEX-FALSE-BOX (BOX STREAM)
- BOX
- (FORMAT STREAM "\false"))
-
- ;;; need this to make the keywording procedure work
- ;;; WARNING, don't use this for anything else. It is INCREDIBLY DANGEROUS
- ;;; for example, directly calling it ANYWHERE will cause you to lose horribly
-
- (DEFBOXER-FUNCTION PORT-TO-POINT ()
- (MAKE-EVDATA ROWS `((,(PORT-TO-INTERNAL (POINT-BOX))))))
-