Def D OC An extensible, dynamic document creation system By Rahul Jain
TeX The Positives Excellent breaking algorithm Layerable macros Simple data model Nested sequences of hboxes and vboxes Lots of existing libraries
TeX The Negatives Syntax requires a lot of confusing escaping and unescaping Simple data model Info is lost quickly All data is stored in fixed-sized arrays … size is fixed at compile time!
CLOS to the Rescue! CONTENTS slot for tree structure Other slots indicate properties of document elements Mixins allow orthogonalizing concerns such as: –Wrapping –Flowing –Floating –Layout direction
Examples (defclass logical-structure-element (vertical-element vertical-container flowing-container-mixin) ()) (defclass paragraph (logical-structure-element wrapping-container-mixin) () (:documentation "A standard paragraph of text."))
More CLOS! (defclass html-output (output-destination pretty-printable-mixin) ()) (defclass plain-text-output (output-destination fixed-width-layout) ((page-width :initform (make-length 72 'em)))) (defclass pdf-output (output-destination fixed-layout) ())
Layout Engine (defgeneric prepare (input output) (:documentation "Breaks up the input into the basic elements to be laid out …")) (defgeneric convert (input output) (:documentation "Converts the input into the format specified by the output.")) Multiple Dispatch!
HTML Ouptut (defmacro define-html-conversion (type (element &optional (html-class 'html-output)) &body body) `(defmethod convert ((,element,type) (.output.,html-class)) (flet ((convert (&optional (element (contents,element))) (convert element.output.)) (convert-to-text (element) (let ((*suppress-html-tags* t)) (convert
HTML Output (define-html-conversion paragraph (input) (with-html-block (:P) (convert))) (define-html-conversion itemized-list (input) (with-html-block (:UL) (dolist (element (contents input)) (with-html-block (:LI) (convert element))))) (define-html-conversion link (input) (with-html-inline (:A :href (url input)) (convert))) (define-html-conversion discretionary-hyphen (input) (write-html-entity "shy"))
Project Website (defclass project-website (document) ((title :accessor name :initarg name :initform (error "Name is required.")) (subtitle :initarg short-description))) (defclass documentation (section) ((title :allocation :class :initform "Documentation"))) (defclass code (section) ((title :allocation :class :initform "Code"))) (defclass communication (section) ((title :allocation :class :initform "Communication"))) (defclass dependencies (section) ((title :allocation :class :initform "Dependencies")))
Project Website (defmethod convert ((input dependencies) (output t)) (convert (make-instance 'itemized-list (contents input)) output)) (defgeneric section-before-p (o1 o2)) (let ((order '(documentation code dependencies communication))) (loop for (prior. following-list) on order nconc (loop for following in following-list collect `(defmethod section-before-p ((o1,prior) (o2,following)) t) collect `(defmethod section-before-p ((o2,following) (o1,prior)) nil))))) (defmethod prepare :before ((input project-website) output) (setf (contents input) (sort (contents input) 'section-before-p)))
The DefDoc Website (defpackage :defdoc.website (:use :common-lisp :defdoc :defdoc.elements :defdoc.layout :defdoc.frontends.basic :defdoc.contrib.project-website)) (in-package :defdoc.website) Starts off looking a lot like lisp code!
The DefDoc Website (defabbreviation DefDoc (doc italic () "Def") (doc small-caps () "Doc")) (defabbreviation LaTeX "LaTeX") Abstraction is a beautiful thing!
The DefDoc Website (defun gen-src-link (target) (concatenate 'string "/cgi-bin/viewcvs.cgi/DefDoc/src" target "?cvsroot=defdoc" (unless (eql (aref target (1- (length target))) #\/) "&rev=HEAD&content-type=text/vnd.viewcvs-markup"))) (defun gen-mailing-list-link (target) (concatenate 'string "/mailman/listinfo/defdoc-" target)) Defun, huh.
The DefDoc Website (defdoc index (project-website name (doc DefDoc) short-description "…" author "Rahul Jain") Note the class name and initargs
The DefDoc Website (documentation () (paragraph () "I have written up a document that is an overview“ "of the goals and rationale behind "(DefDoc)". " "It is available as " (link (url "overview.tex") (LaTeX))", " (link (url "overview.pdf") "PDF")", and " (link (url "overview.ps") "Postscript")".")) Note the usage of the abbreviations
The DefDoc Website (code () (paragraph () "The code is very incomplete, but what there is is " (link (url (gen-src-link "/")) "publically available")". " "There are definitions for various types of " (link (url (gen-src-link "/elements/")) "document elements")". " "There are also definitions for the abstract types of " (link (url (gen-src-link "/layout/")) "layout engines") " as well as the " (link (url (gen-src-link "/layout/html-engine.lisp")) " HTML layout engine")". " "Finally, there is a " (link (url (gen-src-link "/frontends/basic/")) "basic frontend")", " "essentially a few simple macros for creating "(DefDoc)" documents. " "A more fully-featured frontend is planned, which will be " "sensitive to the current context and allow texual content " "to be entered unquoted.") ; Ugh, that last sentence says it all… (paragraph () "This site is actually a "(DefDoc)" " (link (url (gen-src-link "/../website/website.lisp")) "document")"."))
The DefDoc Website (dependencies () (link (url " ") "Specified types")) (communication () (paragraph () "There are 3 mailing lists for "(DefDoc)", " (link (url (gen-mailing-list-link "announce")) "defdoc-announce")", " (link (url (gen-mailing-list-link "devel")) "defdoc-devel")", and " (link (url (gen-mailing-list-link "cvs")) "defdoc-cvs")".")))