major Scribble revision (v4.2.1.2)

svn: r15569

original commit: 345c17e85c78771b1dd237c99c58571eb9f5fe7d
This commit is contained in:
Matthew Flatt 2009-07-25 20:25:33 +00:00
parent 44a248fef1
commit 478de81b55
81 changed files with 7720 additions and 3796 deletions

View File

@ -1,6 +1,7 @@
#lang scheme/base
(require "struct.ss"
(require "core.ss"
"private/render-utils.ss"
mzlib/class
mzlib/serialize
scheme/file
@ -51,36 +52,109 @@
;; ----------------------------------------
(define/public (extract-part-style-files d ri tag stop-at-part?)
(let loop ([p d][up? #t][only-up? #f])
(let ([s (part-style p)])
(apply
append
(if up?
(let ([p (collected-info-parent (part-collected-info p ri))])
(if p
(loop p #t #t)
null))
null)
(if (list? s)
(filter
values
(map (lambda (s)
(and (list? s)
(= 2 (length s))
(eq? (car s) tag)
(path-string? (cadr s))
(cadr s)))
s))
null)
(if only-up?
null
(map (lambda (p)
(if (stop-at-part? p)
null
(loop p #f #f)))
(part-parts p)))))))
(define/public (extract-part-style-files d ri tag stop-at-part? pred extract)
(let ([ht (make-hash)])
(let loop ([p d][up? #t][only-up? #f])
(let ([s (part-style p)])
(when up?
(let ([p (collected-info-parent (part-collected-info p ri))])
(if p
(loop p #t #t)
null)))
(extract-style-style-files (part-style p) ht pred extract)
(unless only-up?
(extract-content-style-files (part-to-collect p) d ri ht pred extract)
(extract-content-style-files (part-title-content p) d ri ht pred extract)
(extract-flow-style-files (part-blocks p) d ri ht pred extract))
(unless only-up?
(for-each (lambda (p)
(unless (stop-at-part? p)
(loop p #f #f)))
(part-parts p)))))
(for/list ([k (in-hash-keys ht)]) (main-collects-relative->path k))))
(define/private (extract-style-style-files s ht pred extract)
(for ([v (in-list (style-variants s))])
(when (pred v)
(hash-set! ht (extract v) #t))))
(define/private (extract-flow-style-files blocks d ri ht pred extract)
(for ([b (in-list blocks)])
(extract-block-style-files b d ri ht pred extract)))
(define/private (extract-block-style-files p d ri ht pred extract)
(cond
[(table? p)
(extract-style-style-files (table-style p) ht pred extract)
(for-each (lambda (blocks)
(for-each (lambda (block)
(unless (eq? block 'cont)
(extract-block-style-files block d ri ht pred extract)))
blocks))
(table-blockss p))]
[(itemization? p)
(extract-style-style-files (itemization-style p) ht pred extract)
(for-each (lambda (blocks)
(extract-flow-style-files blocks d ri ht pred extract))
(itemization-blockss p))]
[(nested-flow? p)
(extract-style-style-files (nested-flow-style p) ht pred extract)
(extract-flow-style-files (nested-flow-blocks p) d ri ht pred extract)]
[(compound-paragraph? p)
(extract-style-style-files (compound-paragraph-style p) ht pred extract)
(extract-flow-style-files (compound-paragraph-blocks p) d ri ht pred extract)]
[(delayed-block? p)
(let ([v ((delayed-block-resolve p) this d ri)])
(extract-block-style-files v d ri ht pred extract))]
[else
(extract-style-style-files (paragraph-style p) ht pred extract)
(extract-content-style-files (paragraph-content p) d ri ht pred extract)]))
(define/private (extract-content-style-files e d ri ht pred extract)
(cond
[(element? e)
(when (style? (element-style e))
(extract-style-style-files (element-style e) ht pred extract))
(extract-content-style-files (element-content e) d ri ht pred extract)]
[(multiarg-element? e)
(when (style? (multiarg-element-style e))
(extract-style-style-files (multiarg-element-style e) ht pred extract))
(extract-content-style-files (multiarg-element-contents e) d ri ht pred extract)]
[(list? e)
(for ([e (in-list e)])
(extract-content-style-files e d ri ht pred extract))]
[(delayed-element? e)
(extract-content-style-files (delayed-element-content e ri) d ri ht pred extract)]
[(part-relative-element? e)
(extract-content-style-files (part-relative-element-content e ri) d ri ht pred extract)]))
(define/public (extract-version d)
(or (ormap (lambda (v)
(and (document-version? v)
(document-version-text v)))
(style-variants (part-style d)))
""))
(define/private (extract-pre-paras d sym)
(let loop ([l (part-blocks d)])
(cond
[(null? l) null]
[else (let ([v (car l)])
(cond
[(and (paragraph? v)
(eq? sym (style-name (paragraph-style v))))
(cons v (loop (cdr l)))]
[(compound-paragraph? v)
(append (loop (compound-paragraph-blocks v))
(loop (cdr l)))]
[else (loop (cdr l))]))])))
(define/public (extract-authors d)
(extract-pre-paras d 'author))
(define/public (extract-pretitle d)
(extract-pre-paras d 'pretitle))
;; ----------------------------------------
(define root (make-mobile-root root-path))
@ -196,20 +270,18 @@
(collect-content (part-title-content d) p-ci))
(collect-part-tags d p-ci number)
(collect-content (part-to-collect d) p-ci)
(collect-flow (part-flow d) p-ci)
(collect-flow (part-blocks d) p-ci)
(let loop ([parts (part-parts d)]
[pos 1])
(unless (null? parts)
(let ([s (car parts)])
(collect-part s d p-ci
(cons (if (or (unnumbered-part? s)
(part-style? s 'unnumbered))
(cons (if (part-style? s 'unnumbered)
#f
pos)
number))
(loop (cdr parts)
(if (or (unnumbered-part? s)
(part-style? s 'unnumbered))
(if (part-style? s 'unnumbered)
pos
(add1 pos)))))))
(let ([prefix (part-tag-prefix d)])
@ -241,41 +313,38 @@
number
(add-current-tag-prefix t))))))
(define/public (collect-content c ci)
(for ([i (in-list c)]) (collect-element i ci)))
(define/public (collect-paragraph p ci)
(collect-content (paragraph-content p) ci))
(define/public (collect-flow p ci)
(for ([p (in-list (flow-paragraphs p))])
(for ([p (in-list p)])
(collect-block p ci)))
(define/public (collect-block p ci)
(cond [(table? p) (collect-table p ci)]
[(itemization? p) (collect-itemization p ci)]
[(blockquote? p) (collect-blockquote p ci)]
[(nested-flow? p) (collect-nested-flow p ci)]
[(compound-paragraph? p) (collect-compound-paragraph p ci)]
[(delayed-block? p) (void)]
[else (collect-paragraph p ci)]))
(define/public (collect-table i ci)
(for ([d (in-list (apply append (table-flowss i)))])
(when (flow? d) (collect-flow d ci))))
(for ([d (in-list (apply append (table-blockss i)))])
(unless (eq? d 'cont) (collect-block d ci))))
(define/public (collect-itemization i ci)
(for ([d (in-list (itemization-flows i))])
(for ([d (in-list (itemization-blockss i))])
(collect-flow d ci)))
(define/public (collect-blockquote i ci)
(for ([d (in-list (blockquote-paragraphs i))])
(define/public (collect-nested-flow i ci)
(for ([d (in-list (nested-flow-blocks i))])
(collect-block d ci)))
(define/public (collect-compound-paragraph i ci)
(for ([d (in-list (compound-paragraph-blocks i))])
(collect-block d ci)))
(define/public (collect-element i ci)
(define/public (collect-content i ci)
(if (part-relative-element? i)
(let ([content (or (hash-ref (collect-info-relatives ci) i #f)
(let ([v ((part-relative-element-collect i) ci)])
@ -286,7 +355,11 @@
(when (index-element? i) (collect-index-element i ci))
(when (collect-element? i) ((collect-element-collect i) ci))
(when (element? i)
(for ([e (element-content i)]) (collect-element e ci))))))
(collect-content (element-content i) ci))
(when (multiarg-element? i)
(collect-content (multiarg-element-contents i) ci))
(when (list? i)
(for ([e (in-list i)]) (collect-content e ci))))))
(define/public (collect-target-element i ci)
(let ([t (generate-tag (target-element-tag i) ci)])
@ -315,26 +388,22 @@
(extend-prefix d (fresh-tag-resolve-context? d ri))])
(when (part-title-content d)
(resolve-content (part-title-content d) d ri))
(resolve-flow (part-flow d) d ri)
(resolve-flow (part-blocks d) d ri)
(for ([p (part-parts d)])
(resolve-part p ri))))
(define/public (resolve-content c d ri)
(for ([i (in-list c)])
(resolve-element i d ri)))
(define/public (resolve-paragraph p d ri)
(resolve-content (paragraph-content p) d ri))
(define/public (resolve-flow p d ri)
(for ([p (flow-paragraphs p)])
(define/public (resolve-flow f d ri)
(for ([p (in-list f)])
(resolve-block p d ri)))
(define/public (resolve-block p d ri)
(cond
[(table? p) (resolve-table p d ri)]
[(itemization? p) (resolve-itemization p d ri)]
[(blockquote? p) (resolve-blockquote p d ri)]
[(nested-flow? p) (resolve-nested-flow p d ri)]
[(compound-paragraph? p) (resolve-compound-paragraph p d ri)]
[(delayed-block? p)
(let ([v ((delayed-block-resolve p) this d ri)])
@ -343,22 +412,22 @@
[else (resolve-paragraph p d ri)]))
(define/public (resolve-table i d ri)
(for ([f (in-list (apply append (table-flowss i)))])
(when (flow? f) (resolve-flow f d ri))))
(for ([f (in-list (apply append (table-blockss i)))])
(unless (eq? f 'cont) (resolve-block f d ri))))
(define/public (resolve-itemization i d ri)
(for ([f (in-list (itemization-flows i))])
(for ([f (in-list (itemization-blockss i))])
(resolve-flow f d ri)))
(define/public (resolve-blockquote i d ri)
(for ([f (in-list (blockquote-paragraphs i))])
(define/public (resolve-nested-flow i d ri)
(for ([f (in-list (nested-flow-blocks i))])
(resolve-block f d ri)))
(define/public (resolve-compound-paragraph i d ri)
(for ([f (in-list (compound-paragraph-blocks i))])
(resolve-block f d ri)))
(define/public (resolve-element i d ri)
(define/public (resolve-content i d ri)
(cond
[(part-relative-element? i)
(resolve-content (part-relative-element-content i ri) d ri)]
@ -368,6 +437,9 @@
(hash-set! (resolve-info-delays ri) i v)
v))
d ri)]
[(list? i)
(for ([i (in-list i)])
(resolve-content i d ri))]
[(element? i)
(cond
[(index-element? i)
@ -377,19 +449,30 @@
(hash-set! (resolve-info-delays ri) e v))))]
[(link-element? i)
(resolve-get d ri (link-element-tag i))])
(for ([e (element-content i)])
(resolve-element e d ri))]))
(resolve-content (element-content i) d ri)]
[(multiarg-element? i)
(resolve-content (multiarg-element-contents i) d ri)]))
;; ----------------------------------------
;; render methods
(define/public (install-extra-files)
(for ([fn extra-files]) (install-file fn)))
(define/public (auto-extra-files? v) #f)
(define/public (auto-extra-files-paths v) null)
(define/public (install-extra-files ds)
(for ([fn extra-files]) (install-file fn))
(unless prefix-file
(for ([d (in-list ds)])
(let ([extras (ormap (lambda (v) (and (auto-extra-files? v) v))
(style-variants (part-style d)))])
(when extras
(for ([fn (in-list (auto-extra-files-paths extras))])
(install-file (main-collects-relative->path fn))))))))
(define/public (render ds fns ri)
;; maybe this should happen even if fns is empty or all #f?
;; or maybe it should happen for each file rendered (when d is not #f)?
(unless (andmap not ds) (install-extra-files))
(unless (andmap not ds) (install-extra-files ds))
(map (lambda (d fn)
(define (one) (render-one d ri fn))
(when (report-output?) (printf " [Output to ~a]\n" fn))
@ -415,13 +498,10 @@
(list
(when (part-title-content d)
(render-content (part-title-content d) d ri))
(render-flow (part-flow d) d ri #f)
(render-flow (part-blocks d) d ri #f)
(map (lambda (s) (render-part s ri))
(part-parts d))))
(define/public (render-content c part ri)
(apply append (map (lambda (i) (render-element i part ri)) c)))
(define/public (render-paragraph p part ri)
(render-content (paragraph-content p) part ri))
@ -436,49 +516,51 @@
(loop (cdr l) #f))]))))
(define/public (render-flow p part ri starting-item?)
(if (null? (flow-paragraphs p))
(if (null? p)
null
(append
(render-block (car (flow-paragraphs p))
(render-block (car p)
part ri starting-item?)
(apply append
(map (lambda (p)
(render-block p part ri #f))
(cdr (flow-paragraphs p)))))))
(cdr p))))))
(define/public (render-intrapara-block p part ri first? last? starting-item?)
(render-block p part ri starting-item?))
(define/public (render-block p part ri inline?)
(define/public (render-block p part ri starting-item?)
(cond
[(table? p) (if (auxiliary-table? p)
(render-auxiliary-table p part ri)
(render-table p part ri inline?))]
[(itemization? p) (render-itemization p part ri)]
[(blockquote? p) (render-blockquote p part ri)]
[(compound-paragraph? p) (render-compound-paragraph p part ri inline?)]
[(delayed-block? p)
(render-block (delayed-block-blocks p ri) part ri inline?)]
[else (render-paragraph p part ri)]))
[(table? p) (if (memq 'aux (style-variants (table-style p)))
(render-auxiliary-table p part ri)
(render-table p part ri starting-item?))]
[(itemization? p) (render-itemization p part ri)]
[(nested-flow? p) (render-nested-flow p part ri)]
[(compound-paragraph? p) (render-compound-paragraph p part ri starting-item?)]
[(delayed-block? p)
(render-block (delayed-block-blocks p ri) part ri starting-item?)]
[else (render-paragraph p part ri)]))
(define/public (render-auxiliary-table i part ri)
null)
(define/public (render-table i part ri inline?)
(map (lambda (d) (if (flow? i) (render-flow d part ri #f) null))
(apply append (table-flowss i))))
(define/public (render-table i part ri starting-item?)
(map (lambda (d) (if (eq? i 'cont) null (render-block d part ri #f)))
(apply append (table-blockss i))))
(define/public (render-itemization i part ri)
(map (lambda (d) (render-flow d part ri #t))
(itemization-flows i)))
(itemization-blockss i)))
(define/public (render-blockquote i part ri)
(define/public (render-nested-flow i part ri)
(map (lambda (d) (render-block d part ri #f))
(blockquote-paragraphs i)))
(nested-flow-blocks i)))
(define/public (render-element i part ri)
(define/public (render-content i part ri)
(cond
[(string? i) (render-other i part ri)] ; short-cut for common case
[(list? i)
(apply append (for/list ([i (in-list i)]) (render-content i part ri)))]
[(and (link-element? i)
(null? (element-content i)))
(let ([v (resolve-get part ri (link-element-tag i))])
@ -489,6 +571,8 @@
(when (render-element? i)
((render-element-render i) this part ri))
(render-content (element-content i) part ri)]
[(multiarg-element? i)
(render-content (multiarg-element-contents i) part ri)]
[(delayed-element? i)
(render-content (delayed-element-content i ri) part ri)]
[(part-relative-element? i)
@ -568,15 +652,15 @@
;; ----------------------------------------
(define/private (do-table-of-contents part ri delta quiet depth)
(make-table #f (generate-toc part
ri
(+ delta
(length (collected-info-number
(part-collected-info part ri))))
#t
quiet
depth
null)))
(make-table plain (generate-toc part
ri
(+ delta
(length (collected-info-number
(part-collected-info part ri))))
#t
quiet
depth
null)))
(define/public (table-of-contents part ri)
(do-table-of-contents part ri -1 not +inf.0))
@ -605,31 +689,30 @@
(if skip?
subs
(let ([l (cons
(list (make-flow
(list (make-paragraph
plain
(list
(make-paragraph
(list
(make-element
'hspace
(list (make-string (* 2 (- (length number)
base-len))
#\space)))
(make-link-element
(if (= 1 (length number)) "toptoclink" "toclink")
(append
(format-number
number
(list (make-element 'hspace '(" "))))
(or (part-title-content part) '("???")))
(for/fold ([t (car (part-tags part))])
([prefix (in-list prefixes)])
(convert-key prefix t))))))))
(make-element
'hspace
(list (make-string (* 2 (- (length number)
base-len))
#\space)))
(make-link-element
(if (= 1 (length number)) "toptoclink" "toclink")
(append
(format-number
number
(list (make-element 'hspace '(" "))))
(or (part-title-content part) '("???")))
(for/fold ([t (car (part-tags part))])
([prefix (in-list prefixes)])
(convert-key prefix t))))))
subs)])
(if (and (= 1 (length number))
(or (not (car number)) ((car number) . > . 1)))
(cons (list (make-flow
(list (make-paragraph
(list (make-element 'hspace (list "")))))))
(cons (list (make-paragraph
plain
(list (make-element 'hspace (list "")))))
l)
l)))))

740
collects/scribble/base.ss Normal file
View File

@ -0,0 +1,740 @@
#lang scheme/base
(require "decode.ss"
"core.ss"
"manual-struct.ss"
"decode-struct.ss"
"html-variants.ss"
scheme/list
scheme/class
scheme/contract
setup/main-collects
syntax/modresolve
(for-syntax scheme/base))
;; ----------------------------------------
(define-syntax-rule (title-like-contract)
(->* ()
(#:tag (or/c #f string? (listof string?))
#:tag-prefix (or/c #f string? module-path?)
#:style (or/c style? string? symbol? (listof symbol?) #f))
#:rest (listof pre-content?)
part-start?))
(provide/contract
[title (->* ()
(#:tag (or/c #f string? (listof string?))
#:tag-prefix (or/c #f string? module-path?)
#:style (or/c style? string? symbol? (listof symbol?) #f)
#:version (or/c string? #f))
#:rest (listof pre-content?)
title-decl?)]
[section (title-like-contract)]
[subsection (title-like-contract)]
[subsubsection (title-like-contract)]
[subsubsub*section (->* ()
(#:tag (or/c #f string? (listof string?)))
#:rest (listof pre-content?)
block?)])
(provide include-section)
(define (gen-tag content)
(regexp-replace* "[^-a-zA-Z0-9_=]" (content->string content) "_"))
(define (prefix->string p)
(and p (if (string? p) p (module-path-prefix->string p))))
(define (convert-tag tag content)
(if (list? tag)
(append-map (lambda (t) (convert-tag t content)) tag)
`((part ,(or tag (gen-tag content))))))
(define (convert-part-style who s)
(cond
[(style? s) s]
[(not s) plain]
[(string? s) (make-style s null)]
[(symbol? s) (make-style #f (list s))]
[(and (list? s) (andmap symbol? s)) (make-style #f s)]
[else (raise-type-error who "style, string, symbol, list of symbols, or #f" s)]))
(define (title #:tag [tag #f] #:tag-prefix [prefix #f] #:style [style plain]
#:version [version #f] . str)
(let ([content (decode-content str)])
(make-title-decl (prefix->string prefix)
(convert-tag tag content)
version
(convert-part-style 'title style)
content)))
(define (section #:tag [tag #f] #:tag-prefix [prefix #f] #:style [style plain]
. str)
(let ([content (decode-content str)])
(make-part-start 0 (prefix->string prefix)
(convert-tag tag content)
(convert-part-style 'section style)
content)))
(define (subsection #:tag [tag #f] #:tag-prefix [prefix #f] #:style [style plain]
. str)
(let ([content (decode-content str)])
(make-part-start 1
(prefix->string prefix)
(convert-tag tag content)
(convert-part-style 'subsection style)
content)))
(define (subsubsection #:tag [tag #f] #:tag-prefix [prefix #f]
#:style [style plain] . str)
(let ([content (decode-content str)])
(make-part-start 2
(prefix->string prefix)
(convert-tag tag content)
(convert-part-style 'subsubsection style)
content)))
(define (subsubsub*section #:tag [tag #f] . str)
(let ([content (decode-content str)])
(make-paragraph plain
(list
(make-element 'bold
(if tag
(make-target-element #f content `(part ,tag))
content))))))
(define-syntax (include-section stx)
(syntax-case stx ()
[(_ mod)
(with-syntax ([mod (syntax-local-introduce #'mod)])
(unless (module-path? (syntax->datum #'mod))
(raise-syntax-error #f
"not a module path"
stx
#'mod))
#'(begin
(require (only-in mod doc))
doc))]))
;; ----------------------------------------
(provide/contract
[author (->* (content?) () #:rest (listof content?) block?)]
[author+email (-> content? string? element?)])
(define (author . auths)
(make-paragraph
(make-style 'author null)
(let ([nl (make-element 'newline '("\n"))])
(case (length auths)
[(1) auths]
[(2) (list (car auths) nl "and " (cadr auths))]
[else (let ([r (reverse auths)])
(append (add-between (reverse (cdr r))
(make-element #f (list "," nl)))
(list "," nl "and " (car r))))]))))
(define (author+email name email)
(make-element #f
(list
name
" <"
(regexp-replace* #rx"[.]"
(regexp-replace* #rx"@" email " at ")
" dot ")
">")))
;; ----------------------------------------
(provide intern-taglet
module-path-index->taglet
module-path-prefix->string
doc-prefix)
(require syntax/modcollapse
;; Needed to normalize planet version numbers:
(only-in planet/resolver get-planet-module-path/pkg)
(only-in planet/private/data pkg-maj pkg-min))
(define interned (make-weak-hash))
(define (intern-taglet v)
(let ([v (if (list? v)
(map intern-taglet v)
v)])
(if (or (string? v)
(bytes? v)
(list? v))
(let ([b (hash-ref interned v #f)])
(if b
(or (weak-box-value b)
;; just in case the value is GCed before we extract it:
(intern-taglet v))
(begin
(hash-set! interned v (make-weak-box v))
v)))
v)))
(define (do-module-path-index->taglet mod)
;; Derive the name from the module path:
(let ([p (collapse-module-path-index
mod
(lambda () (build-path (current-directory) "dummy")))])
(if (path? p)
;; If we got a path back anyway, then it's best to use the resolved
;; name; if the current directory has changed since we
;; the path-index was resolved, then p might not be right. Also,
;; the resolved path might be a symbol instead of a path.
(let ([rp (resolved-module-path-name
(module-path-index-resolve mod))])
(if (path? rp)
(intern-taglet
(path->main-collects-relative rp))
rp))
(let ([p (if (and (pair? p)
(eq? (car p) 'planet))
;; Normalize planet verion number based on current
;; linking:
(let-values ([(path pkg)
(get-planet-module-path/pkg p #f #f)])
(list* 'planet
(cadr p)
(list (car (caddr p))
(cadr (caddr p))
(pkg-maj pkg)
(pkg-min pkg))
(cdddr p)))
;; Otherwise the path is fully normalized:
p)])
(intern-taglet p)))))
(define collapsed (make-weak-hasheq))
(define (module-path-index->taglet mod)
(or (hash-ref collapsed mod #f)
(let ([v (do-module-path-index->taglet mod)])
(hash-set! collapsed mod v)
v)))
(define (module-path-prefix->string p)
(format "~a" (module-path-index->taglet (module-path-index-join p #f))))
(define doc-prefix
(case-lambda
[(doc s)
(if doc
(list (module-path-prefix->string doc) s)
s)]
[(doc prefix s)
(doc-prefix doc (if prefix
(append prefix (list s))
s))]))
;; ----------------------------------------
(define (item? x) (an-item? x))
(provide/contract
[itemlist (->* ()
(#:style (or/c style? string? symbol? #f))
#:rest (listof item?)
itemization?)]
[item (->* ()
()
#:rest (listof pre-flow?)
item?)])
(provide item?)
(define (itemlist #:style [style plain] . items)
(let ([flows (map an-item-flow items)])
(make-itemization (convert-block-style style) flows)))
(define-struct an-item (flow))
(define (item . str)
(make-an-item (decode-flow str)))
;; ----------------------------------------
(define elem-like-contract
(->* () () #:rest (listof pre-content?) element?))
(provide/contract
[hspace (-> exact-nonnegative-integer? element?)]
[elem (->* ()
(#:style element-style?)
#:rest (listof pre-content?)
element?)]
[italic elem-like-contract]
[bold elem-like-contract]
[smaller elem-like-contract]
[larger elem-like-contract]
[emph elem-like-contract]
[tt elem-like-contract]
[subscript elem-like-contract]
[superscript elem-like-contract]
[literal (->* (string?) () #:rest (listof string?) element?)]
[image (->* ((or/c path-string? (cons/c 'collects (listof bytes?))))
(#:scale real?
#:suffixes (listof #rx"^[.]"))
#:rest (listof content?)
image-element?)])
(define hspace-cache (make-vector 100 #f))
(define (hspace n)
(if (n . < . (vector-length hspace-cache))
(or (vector-ref hspace-cache n)
(let ([h (make-element 'hspace (list (make-string n #\space)))])
(vector-set! hspace-cache n h)
h))
(make-element 'hspace (list (make-string n #\space)))))
(define (elem #:style [style plain] . str)
(make-element style (decode-content str)))
(define (italic . str)
(make-element 'italic (decode-content str)))
(define (bold . str)
(make-element 'bold (decode-content str)))
(define (smaller . str)
(make-element 'smaller (decode-content str)))
(define (larger . str)
(make-element 'larger (decode-content str)))
(define (emph . str)
(make-element 'italic (decode-content str)))
(define (tt . str)
(let* ([l (decode-content str)]
[l (let ([m (and (pair? l)
(string? (car l))
(regexp-match-positions #rx"^ +" (car l)))])
(if m
(list* (hspace (- (cdar m) (caar m)))
(substring (car l) (cdar m))
(cdr l))
l))])
(if (andmap string? l)
(make-element 'tt l)
(make-element #f (map (lambda (s)
(if (or (string? s) (symbol? s))
(make-element 'tt (list s))
s))
l)))))
(define (span-class classname . str)
(make-element classname (decode-content str)))
(define (subscript . str)
(make-element 'subscript (decode-content str)))
(define (superscript . str)
(make-element 'superscript (decode-content str)))
(define (literal s . strs)
(let ([s (apply string-append s strs)])
(make-element #f s)))
(define (image #:scale [scale 1.0]
filename-relative-to-source
#:suffixes [suffixes null]
. alt)
(make-image-element #f
(decode-content alt)
filename-relative-to-source
suffixes
scale))
;; ----------------------------------------
(provide/contract
[para (->* ()
(#:style (or/c style? string? symbol? #f ))
#:rest (listof pre-content?)
paragraph?)]
[nested (->* ()
(#:style (or/c style? string? symbol? #f ))
#:rest (listof pre-flow?)
nested-flow?)]
[compound (->* ()
(#:style (or/c style? string? symbol? #f ))
#:rest (listof pre-flow?)
compound-paragraph?)]
[tabular (->* ((listof (listof (or/c 'cont block? content?))))
(#:style (or/c style? string? symbol? #f ))
table?)])
(define (convert-block-style style)
(cond
[(style? style) style]
[(or (string? style) (symbol? style)) (make-style style null)]
[else plain]))
(define (nested #:style [style #f] . c)
(make-nested-flow (convert-block-style style)
(decode-flow c)))
(define (para #:style [style #f] . c)
(make-paragraph (convert-block-style style)
(decode-content c)))
(define (compound #:style [style #f] . c)
(make-compound-paragraph (convert-block-style style)
(decode-flow c)))
(define (tabular #:style [style #f] cells)
(define (nth-str pos)
(case (modulo pos 10)
[(1) "st"]
[(2) "nd"]
[(3) "rd"]
[else "th"]))
(unless (null? cells)
(let ([n (length (car cells))])
(for ([row (in-list (cdr cells))]
[pos (in-naturals 2)])
(unless (= n (length row))
(raise-mismatch-error
'tabular
(format "bad length (~a does not match first row's length ~a) for ~a~a row: "
(length row)
n
pos
(nth-str pos))
row)))))
(for ([row (in-list cells)]
[pos (in-naturals 1)])
(when (and (pair? row) (eq? (car row) 'cont))
(raise-mismatch-error
'tabular
(format "~a~a row starts with 'cont: " pos (nth-str pos))
row)))
(make-table (convert-block-style style)
(map (lambda (row)
(map (lambda (cell)
(cond
[(eq? cell 'cont) cell]
[(block? cell) cell]
[else (make-paragraph plain cell)]))
row))
cells)))
;; ----------------------------------------
(provide/contract
[elemtag (->* ((or/c tag? string?))
()
#:rest (listof pre-content?)
element?)]
[elemref (->* ((or/c tag? string?))
(#:underline? any/c)
#:rest (listof pre-content?)
element?)]
[secref (->* (string?)
(#:doc module-path?
#:tag-prefixes (or/c #f (listof string))
#:underline? any/c)
element?)]
[Secref (->* (string?)
(#:doc module-path?
#:tag-prefixes (or/c #f (listof string))
#:underline? any/c)
element?)]
[seclink (->* (string?)
(#:doc module-path?
#:tag-prefixes (or/c #f (listof string))
#:underline? any/c)
#:rest (listof pre-content?)
element?)]
[other-doc (->* (module-path?)
(#:underline? any/c)
element?)])
(define (elemtag t . body)
(make-target-element #f (decode-content body) `(elem ,t)))
(define (elemref #:underline? [u? #t] t . body)
(make-link-element (if u? #f "plainlink") (decode-content body) `(elem ,t)))
(define (secref s #:underline? [u? #t] #:doc [doc #f] #:tag-prefixes [prefix #f])
(make-link-element (if u? #f "plainlink") null `(part ,(doc-prefix doc prefix s))))
(define (Secref s #:underline? [u? #t] #:doc [doc #f] #:tag-prefixes [prefix #f])
(let ([le (secref s #:underline? u? #:doc doc #:tag-prefixes prefix)])
(make-link-element
(make-style (element-style le) '(uppercase))
(element-content le)
(link-element-tag le))))
(define (seclink tag #:underline? [u? #t] #:doc [doc #f] #:tag-prefixes [prefix #f] . s)
(make-link-element (if u? #f "plainlink") (decode-content s)
`(part ,(doc-prefix doc prefix tag))))
(define (other-doc #:underline? [u? #t] doc)
(secref #:doc doc #:underline? u? "top"))
;; ----------------------------------------
(provide/contract
[hyperlink (->* ((or/c string? path?))
(#:underline? any/c
#:style element-style?)
#:rest (listof pre-content?)
element?)]
[url (-> string? element?)]
[margin-note (->* () () #:rest (listof pre-flow?) block?)]
[centered (->* () () #:rest (listof pre-flow?) block?)]
[verbatim (->* (string?) (#:indent exact-nonnegative-integer?) #:rest (listof string?) block?)])
(define (centered . s)
(make-nested-flow (make-style "SCentered" null) (decode-flow s)))
(define (hyperlink url
#:underline? [underline? #t]
#:style [style (if underline? #f "plainlink")]
. str)
(make-element (make-style (if (style? style)
(style-name style)
style)
(cons (make-target-url url)
(if (style? style)
(style-variants style)
null)))
(decode-content str)))
(define (url str)
(hyperlink str (make-element 'url str)))
(define (margin-note . c)
(make-nested-flow
(make-style "refpara" '(command))
(list
(make-nested-flow
(make-style "refcolumn" null)
(list
(make-nested-flow
(make-style "refcontent" null)
(decode-flow c)))))))
(define (verbatim #:indent [i 0] s . more)
(define indent
(if (zero? i)
values
(let ([hs (hspace i)]) (lambda (x) (cons hs x)))))
(define strs (regexp-split #rx"\n" (apply string-append s more)))
(define (str->elts str)
(let ([spaces (regexp-match-positions #rx"(?:^| ) +" str)])
(if spaces
(list* (substring str 0 (caar spaces))
(hspace (- (cdar spaces) (caar spaces)))
(str->elts (substring str (cdar spaces))))
(list (make-element 'tt (list str))))))
(define (make-nonempty l)
(if (let loop ([l l])
(cond
[(null? l) #t]
[(equal? "" l) #t]
[(list? l) (andmap loop l)]
[(element? l) (loop (element-content l))]
[(multiarg-element? l) (loop (multiarg-element-contents l))]
[else #f]))
(list l (hspace 1))
l))
(define (make-line str)
(let* ([line (indent (str->elts str))]
[line (list (make-element 'tt line))])
(list (make-paragraph omitable-style (make-nonempty line)))))
(make-table plain (map make-line strs)))
(define omitable-style (make-style 'omitable null))
;; ----------------------------------------
(provide section-index index index* as-index index-section
get-index-entries index-block)
(define (section-index . elems)
(make-part-index-decl (map content->string elems) elems))
(define (record-index word-seq element-seq tag content)
(make-index-element #f
(list (make-target-element #f content `(idx ,tag)))
`(idx ,tag)
word-seq
element-seq
#f))
(define (index* word-seq content-seq . s)
(let ([key (make-generated-tag)])
(record-index (map clean-up-index-string word-seq)
content-seq key (decode-content s))))
(define (index word-seq . s)
(let ([word-seq (if (string? word-seq) (list word-seq) word-seq)])
(apply index* word-seq word-seq s)))
(define (as-index . s)
(let ([key (make-generated-tag)]
[content (decode-content s)])
(record-index
(list (clean-up-index-string (content->string content)))
(if (= 1 (length content)) content (list (make-element #f content)))
key
content)))
(define (index-section #:title [title "Index"] #:tag [tag #f])
(make-part #f
`((part ,(or tag "doc-index")))
(list title)
(make-style 'index '(unnumbered))
null
(list (index-block))
null))
;; returns an ordered list of (list tag (text ...) (element ...) index-desc)
(define (get-index-entries sec ri)
(define (compare-lists xs ys <?)
(let loop ([xs xs] [ys ys])
(cond [(and (null? xs) (null? ys)) '=]
[(null? xs) '<]
[(null? ys) '>]
[(<? (car xs) (car ys)) '<]
[(<? (car ys) (car xs)) '>]
[else (loop (cdr ys) (cdr xs))])))
;; string-ci<? as a major key, and string<? next, so "Foo" precedes "foo"
;; (define (string*<? s1 s2)
;; (or (string-ci<? s1 s2)
;; (and (not (string-ci<? s2 s1)) (string<? s1 s2))))
(define (get-desc entry)
(let ([desc (cadddr entry)])
(cond [(exported-index-desc? desc)
(cons 'libs (map (lambda (l)
(format "~s" l))
(exported-index-desc-from-libs desc)))]
[(module-path-index-desc? desc) '(mod)]
[(part-index-desc? desc) '(part)]
[(delayed-index-desc? desc) '(delayed)]
[else '(#f)])))
;; parts first, then modules, then bindings, delayed means it's not
;; the last round, and #f means no desc
(define desc-order '(part mod libs delayed #f))
;; this defines an imposed ordering for module names
(define lib-order '(#rx"^scheme(?:/|$)" #rx"^r.rs(?:/|$)" #rx"^lang(?:/|$)"))
(define (lib<? lib1 lib2)
(define (lib-level lib)
(let loop ([i 0] [rxs lib-order])
(if (or (null? rxs) (regexp-match? (car rxs) lib))
i (loop (add1 i) (cdr rxs)))))
(let ([l1 (lib-level lib1)] [l2 (lib-level lib2)])
(if (= l1 l2) (string<? lib1 lib2) (< l1 l2))))
(define (compare-desc e1 e2)
(let* ([d1 (get-desc e1)] [d2 (get-desc e2)]
[t1 (car d1)] [t2 (car d2)])
(cond [(memq t2 (cdr (memq t1 desc-order))) '<]
[(memq t1 (cdr (memq t2 desc-order))) '>]
[else (case t1 ; equal to t2
[(part) '=] ; will just compare tags
[(mod) '=] ; the text fields are the names of the modules
[(libs) (compare-lists (cdr d1) (cdr d2) lib<?)]
[(delayed) '>] ; dosn't matter, will run again
[(#f) '=])])))
(define (entry<? e1 e2)
(let ([text1 (cadr e1)] [text2 (cadr e2)])
(case (compare-lists text1 text2 string-ci<?)
[(<) #t] [(>) #f]
[else (case (compare-desc e1 e2)
[(<) #t] [(>) #f]
[else (case (compare-lists text1 text2 string<?)
[(<) #t] [(>) #f]
[else
;; (error 'get-index-entries
;; ;; when this happens, revise this code so
;; ;; ordering will always be deterministic
;; "internal error -- unordered entries: ~e ~e"
;; e1 e2)
;; Instead, just compare the tags
(string<? (format "~a" (car e1))
(format "~a" (car e2)))])])])))
(define l null)
(hash-for-each
(let ([parent (collected-info-parent (part-collected-info sec ri))])
(if parent
(collected-info-info (part-collected-info parent ri))
(collect-info-ext-ht (resolve-info-ci ri))))
(lambda (k v)
(when (and (pair? k) (eq? 'index-entry (car k)))
(set! l (cons (cons (cadr k) v) l)))))
(sort l entry<?))
(define (index-block)
(define alpha (string->list "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
(define (rows . rows)
(make-table (make-style 'index null)
(map (lambda (row)
(list (make-paragraph plain row)))
rows)))
(define contents
(lambda (renderer sec ri)
(define l (get-index-entries sec ri))
(define manual-newlines? (send renderer index-manual-newlines?))
(define alpha-starts (make-hasheq))
(define alpha-row
(let loop ([i l] [alpha alpha])
(define (add-letter let l)
(list* (make-element "nonavigation" (list (string let))) " " l))
(cond [(null? alpha) null]
[(null? i) (add-letter (car alpha) (loop i (cdr alpha)))]
[else
(let* ([strs (cadr (car i))]
[letter (if (or (null? strs) (string=? "" (car strs)))
#f
(char-upcase (string-ref (car strs) 0)))])
(cond [(not letter) (loop (cdr i) alpha)]
[(char-ci>? letter (car alpha))
(add-letter (car alpha) (loop i (cdr alpha)))]
[(char-ci=? letter (car alpha))
(hash-set! alpha-starts (car i) letter)
(list* (make-element
(make-style #f (list (make-target-url (format "#alpha:~a" letter))))
(list (string (car alpha))))
" "
(loop (cdr i) (cdr alpha)))]
[else (loop (cdr i) alpha)]))])))
(define body
(let ([br (if manual-newlines? (make-element 'newline '("\n")) "")])
(map (lambda (i)
(let ([e (make-link-element
"indexlink"
`(,@(add-between (caddr i) ", ") ,br)
(car i))])
(cond [(hash-ref alpha-starts i #f)
=> (lambda (let)
(make-element
(make-style #f (list
(make-url-anchor
(format "alpha:~a" (char-upcase let)))))
(list e)))]
[else e])))
l)))
(if manual-newlines?
(rows alpha-row '(nbsp) body)
(apply rows alpha-row '(nbsp) (map list body)))))
(make-delayed-block contents))
;; ----------------------------------------
(provide table-of-contents
local-table-of-contents)
(define (table-of-contents)
(make-delayed-block
(lambda (renderer part ri)
(send renderer table-of-contents part ri))))
(define (local-table-of-contents #:style [style plain])
(make-delayed-block
(lambda (renderer part ri)
(send renderer local-table-of-contents part ri style))))

View File

@ -0,0 +1,4 @@
#lang scheme
(require scribble/doclang scribble/base)
(provide (all-from-out scribble/doclang
scribble/base))

View File

@ -0,0 +1,10 @@
#lang s-exp syntax/module-reader
scribble/base/lang
#:read scribble:read-inside
#:read-syntax scribble:read-syntax-inside
#:whole-body-readers? #t
#:wrapper1 (lambda (t) (list* 'doc 'values '() (t)))
(require (prefix-in scribble: "../../reader.ss"))

View File

@ -1,443 +1,46 @@
#lang scheme/base
(require "decode.ss"
"struct.ss"
"config.ss"
"manual-struct.ss"
"decode-struct.ss"
scheme/list
scheme/class
setup/main-collects
syntax/modresolve
(for-syntax scheme/base))
(require "base.ss"
"core.ss"
"decode.ss")
(provide title
section
subsection
subsubsection
subsubsub*section
include-section)
include-section
(define (gen-tag content)
(regexp-replace* "[^-a-zA-Z0-9_=]" (content->string content) "_"))
author
author+email
(define (prefix->string p)
(and p (if (string? p) p (module-path-prefix->string p))))
(define (convert-tag tag content)
(if (list? tag)
(append-map (lambda (t) (convert-tag t content)) tag)
`((part ,(or tag (gen-tag content))))))
(define (title #:tag [tag #f] #:tag-prefix [prefix #f] #:style [style #f]
#:version [version #f] . str)
(let ([content (decode-content str)])
(make-title-decl (prefix->string prefix)
(convert-tag tag content)
version
style
content)))
(define (section #:tag [tag #f] #:tag-prefix [prefix #f] #:style [style #f]
. str)
(let ([content (decode-content str)])
(make-part-start 0 (prefix->string prefix)
(convert-tag tag content)
style
content)))
(define (subsection #:tag [tag #f] #:tag-prefix [prefix #f] #:style [style #f]
. str)
(let ([content (decode-content str)])
(make-part-start 1
(prefix->string prefix)
(convert-tag tag content)
style
content)))
(define (subsubsection #:tag [tag #f] #:tag-prefix [prefix #f]
#:style [style #f] . str)
(let ([content (decode-content str)])
(make-part-start 2
(prefix->string prefix)
(convert-tag tag content)
style
content)))
(define (subsubsub*section #:tag [tag #f] . str)
(let ([content (decode-content str)])
(make-paragraph (list (make-element 'bold content)))))
(define-syntax (include-section stx)
(syntax-case stx ()
[(_ mod)
(with-syntax ([mod (syntax-local-introduce #'mod)])
#'(begin
(require (only-in mod doc))
doc))]))
;; ----------------------------------------
(provide author
author+email)
(define (author . auths)
(make-styled-paragraph
(let ([nl (make-element 'newline '("\n"))])
(case (length auths)
[(1) auths]
[(2) (list (car auths) nl "and " (cadr auths))]
[else (let ([r (reverse auths)])
(append (add-between (reverse (cdr r))
(make-element #f (list "," nl)))
(list "," nl "and " (car r))))]))
"author"))
(define (author+email name email)
(make-element #f
(list
name
" <"
(regexp-replace* #rx"[.]"
(regexp-replace* #rx"@" email " at ")
" dot ")
">")))
;; ----------------------------------------
(provide intern-taglet
intern-taglet
module-path-index->taglet
module-path-prefix->string)
module-path-prefix->string
itemize item item?
(define interned (make-weak-hash))
(define (intern-taglet v)
(let ([v (if (list? v)
(map intern-taglet v)
v)])
(if (or (string? v)
(bytes? v)
(list? v))
(let ([b (hash-ref interned v #f)])
(if b
(or (weak-box-value b)
;; just in case the value is GCed before we extract it:
(intern-taglet v))
(begin
(hash-set! interned v (make-weak-box v))
v)))
v)))
(define (do-module-path-index->taglet mod)
;; Derive the name from the module path:
(let ([p (collapse-module-path-index
mod
(lambda () (build-path (current-directory) "dummy")))])
(if (path? p)
;; If we got a path back anyway, then it's best to use the resolved
;; name; if the current directory has changed since we
;; the path-index was resolved, then p might not be right. Also,
;; the resolved path might be a symbol instead of a path.
(let ([rp (resolved-module-path-name
(module-path-index-resolve mod))])
(if (path? rp)
(intern-taglet
(path->main-collects-relative rp))
rp))
(let ([p (if (and (pair? p)
(eq? (car p) 'planet))
;; Normalize planet verion number based on current
;; linking:
(let-values ([(path pkg)
(get-planet-module-path/pkg p #f #f)])
(list* 'planet
(cadr p)
(list (car (caddr p))
(cadr (caddr p))
(pkg-maj pkg)
(pkg-min pkg))
(cdddr p)))
;; Otherwise the path is fully normalized:
p)])
(intern-taglet p)))))
(define collapsed (make-weak-hasheq))
(define (module-path-index->taglet mod)
(or (hash-ref collapsed mod #f)
(let ([v (do-module-path-index->taglet mod)])
(hash-set! collapsed mod v)
v)))
(define (module-path-prefix->string p)
(format "~a" (module-path-index->taglet (module-path-index-join p #f))))
;; ----------------------------------------
(require syntax/modcollapse
;; Needed to normalize planet version numbers:
(only-in planet/resolver get-planet-module-path/pkg)
(only-in planet/private/data pkg-maj pkg-min))
(provide itemize item item?)
(define (itemize #:style [style #f] . items)
(let ([items (filter (lambda (v) (not (whitespace? v))) items)])
(for ([v items])
(unless (an-item? v)
(error 'itemize "expected an item, found something else: ~e" v)))
(let ([flows (map an-item-flow items)])
(if style
(make-styled-itemization flows style)
(make-itemization flows)))))
(define-struct an-item (flow))
(define (item? x) (an-item? x))
(define (item . str)
(make-an-item (decode-flow str)))
;; ----------------------------------------
(provide hspace
hspace
elem aux-elem
italic bold smaller
tt span-class
subscript superscript)
tt
subscript superscript
(define hspace-cache (make-vector 100 #f))
section-index index index* as-index index-section
get-index-entries index-block
(define (hspace n)
(if (n . < . (vector-length hspace-cache))
(or (vector-ref hspace-cache n)
(let ([h (make-element 'hspace (list (make-string n #\space)))])
(vector-set! hspace-cache n h)
h))
(make-element 'hspace (list (make-string n #\space)))))
table-of-contents
local-table-of-contents
(define (elem #:style [style #f] . str)
(make-element style (decode-content str)))
(define (aux-elem . s)
(make-aux-element #f (decode-content s)))
(define (italic . str)
(make-element 'italic (decode-content str)))
(define (bold . str)
(make-element 'bold (decode-content str)))
(define (smaller . str)
(make-element "smaller" (decode-content str)))
(define (tt . str)
(let* ([l (decode-content str)]
[l (let ([m (and (pair? l)
(string? (car l))
(regexp-match-positions #rx"^ +" (car l)))])
(if m
(list* (hspace (- (cdar m) (caar m)))
(substring (car l) (cdar m))
(cdr l))
l))])
(if (andmap string? l)
(make-element 'tt l)
(make-element #f (map (lambda (s)
(if (or (string? s) (symbol? s))
(make-element 'tt (list s))
s))
l)))))
span-class)
(define (span-class classname . str)
(make-element classname (decode-content str)))
(define (subscript . str)
(make-element 'subscript (decode-content str)))
(define (aux-elem . s)
(make-element (make-style #f (list 'aux)) (decode-content s)))
(define (superscript . str)
(make-element 'superscript (decode-content str)))
(define (itemize #:style [style #f] . items)
(let ([items (filter (lambda (v) (not (whitespace? v))) items)])
(apply itemlist #:style style items)))
;; ----------------------------------------
(provide section-index index index* as-index index-section
get-index-entries index-block)
(define (section-index . elems)
(make-part-index-decl (map element->string elems) elems))
(define (record-index word-seq element-seq tag content)
(make-index-element #f
(list (make-target-element #f content `(idx ,tag)))
`(idx ,tag)
word-seq
element-seq
#f))
(define (index* word-seq content-seq . s)
(let ([key (make-generated-tag)])
(record-index (map clean-up-index-string word-seq)
content-seq key (decode-content s))))
(define (index word-seq . s)
(let ([word-seq (if (string? word-seq) (list word-seq) word-seq)])
(apply index* word-seq word-seq s)))
(define (as-index . s)
(let ([key (make-generated-tag)]
[content (decode-content s)])
(record-index
(list (clean-up-index-string (content->string content)))
(if (= 1 (length content)) content (list (make-element #f content)))
key
content)))
(define (index-section #:title [title "Index"] #:tag [tag #f])
(make-unnumbered-part #f
`((part ,(or tag "doc-index")))
(list title)
'index
null
(make-flow (list (index-block)))
null))
;; returns an ordered list of (list tag (text ...) (element ...) index-desc)
(define (get-index-entries sec ri)
(define (compare-lists xs ys <?)
(let loop ([xs xs] [ys ys])
(cond [(and (null? xs) (null? ys)) '=]
[(null? xs) '<]
[(null? ys) '>]
[(<? (car xs) (car ys)) '<]
[(<? (car ys) (car xs)) '>]
[else (loop (cdr ys) (cdr xs))])))
;; string-ci<? as a major key, and string<? next, so "Foo" precedes "foo"
;; (define (string*<? s1 s2)
;; (or (string-ci<? s1 s2)
;; (and (not (string-ci<? s2 s1)) (string<? s1 s2))))
(define (get-desc entry)
(let ([desc (cadddr entry)])
(cond [(exported-index-desc? desc)
(cons 'libs (map (lambda (l)
(format "~s" l))
(exported-index-desc-from-libs desc)))]
[(module-path-index-desc? desc) '(mod)]
[(part-index-desc? desc) '(part)]
[(delayed-index-desc? desc) '(delayed)]
[else '(#f)])))
;; parts first, then modules, then bindings, delayed means it's not
;; the last round, and #f means no desc
(define desc-order '(part mod libs delayed #f))
;; this defines an imposed ordering for module names
(define lib-order '(#rx"^scheme(?:/|$)" #rx"^r.rs(?:/|$)" #rx"^lang(?:/|$)"))
(define (lib<? lib1 lib2)
(define (lib-level lib)
(let loop ([i 0] [rxs lib-order])
(if (or (null? rxs) (regexp-match? (car rxs) lib))
i (loop (add1 i) (cdr rxs)))))
(let ([l1 (lib-level lib1)] [l2 (lib-level lib2)])
(if (= l1 l2) (string<? lib1 lib2) (< l1 l2))))
(define (compare-desc e1 e2)
(let* ([d1 (get-desc e1)] [d2 (get-desc e2)]
[t1 (car d1)] [t2 (car d2)])
(cond [(memq t2 (cdr (memq t1 desc-order))) '<]
[(memq t1 (cdr (memq t2 desc-order))) '>]
[else (case t1 ; equal to t2
[(part) '=] ; will just compare tags
[(mod) '=] ; the text fields are the names of the modules
[(libs) (compare-lists (cdr d1) (cdr d2) lib<?)]
[(delayed) '>] ; dosn't matter, will run again
[(#f) '=])])))
(define (entry<? e1 e2)
(let ([text1 (cadr e1)] [text2 (cadr e2)])
(case (compare-lists text1 text2 string-ci<?)
[(<) #t] [(>) #f]
[else (case (compare-desc e1 e2)
[(<) #t] [(>) #f]
[else (case (compare-lists text1 text2 string<?)
[(<) #t] [(>) #f]
[else
;; (error 'get-index-entries
;; ;; when this happens, revise this code so
;; ;; ordering will always be deterministic
;; "internal error -- unordered entries: ~e ~e"
;; e1 e2)
;; Instead, just compare the tags
(string<? (format "~a" (car e1))
(format "~a" (car e2)))])])])))
(define l null)
(hash-for-each
(let ([parent (collected-info-parent (part-collected-info sec ri))])
(if parent
(collected-info-info (part-collected-info parent ri))
(collect-info-ext-ht (resolve-info-ci ri))))
(lambda (k v)
(when (and (pair? k) (eq? 'index-entry (car k)))
(set! l (cons (cons (cadr k) v) l)))))
(sort l entry<?))
(define (index-block)
(define alpha (string->list "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
(define (rows . rows)
(make-table 'index (map (lambda (row)
(list (make-flow (list (make-paragraph row)))))
rows)))
(define contents
(lambda (renderer sec ri)
(define l (get-index-entries sec ri))
(define manual-newlines? (send renderer index-manual-newlines?))
(define alpha-starts (make-hasheq))
(define alpha-row
(let loop ([i l] [alpha alpha])
(define (add-letter let l)
(list* (make-element "nonavigation" (list (string let))) " " l))
(cond [(null? alpha) null]
[(null? i) (add-letter (car alpha) (loop i (cdr alpha)))]
[else
(let* ([strs (cadr (car i))]
[letter (if (or (null? strs) (string=? "" (car strs)))
#f
(char-upcase (string-ref (car strs) 0)))])
(cond [(not letter) (loop (cdr i) alpha)]
[(char-ci>? letter (car alpha))
(add-letter (car alpha) (loop i (cdr alpha)))]
[(char-ci=? letter (car alpha))
(hash-set! alpha-starts (car i) letter)
(list* (make-element
(make-target-url (format "#alpha:~a" letter)
#f)
(list (string (car alpha))))
" "
(loop (cdr i) (cdr alpha)))]
[else (loop (cdr i) alpha)]))])))
(define body
(let ([br (if manual-newlines? (make-element 'newline '("\n")) "")])
(map (lambda (i)
(let ([e (make-link-element
"indexlink"
`(,@(add-between (caddr i) ", ") ,br)
(car i))])
(cond [(hash-ref alpha-starts i #f)
=> (lambda (let)
(make-element
(make-url-anchor
(format "alpha:~a" (char-upcase let)))
(list e)))]
[else e])))
l)))
(if manual-newlines?
(rows alpha-row '(nbsp) body)
(apply rows alpha-row '(nbsp) (map list body)))))
(make-delayed-block contents))
;; ----------------------------------------
(provide table-of-contents
local-table-of-contents)
(define (table-of-contents)
(make-delayed-block
(lambda (renderer part ri)
(send renderer table-of-contents part ri))))
(define (local-table-of-contents #:style [style #f])
(make-delayed-block
(lambda (renderer part ri)
(send renderer local-table-of-contents part ri style))))

532
collects/scribble/core.ss Normal file
View File

@ -0,0 +1,532 @@
#lang scheme/base
(require "private/provide-structs.ss"
scheme/serialize
scheme/contract)
;; ----------------------------------------
(define-struct collect-info (ht ext-ht parts tags gen-prefix relatives parents))
(define-struct resolve-info (ci delays undef searches))
(define (part-collected-info part ri)
(hash-ref (collect-info-parts (resolve-info-ci ri))
part))
(define (collect-put! ci key val)
(let ([ht (collect-info-ht ci)])
(let ([old-val (hash-ref ht key #f)])
(when old-val
(fprintf (current-error-port)
"WARNING: collected information for key multiple times: ~e; values: ~e ~e\n"
key old-val val))
(hash-set! ht key val))))
(define (resolve-get/where part ri key)
(let ([key (tag-key key ri)])
(let ([v (hash-ref (if part
(collected-info-info (part-collected-info part ri))
(collect-info-ht (resolve-info-ci ri)))
key
#f)])
(cond
[v (values v #f)]
[part (resolve-get/where
(collected-info-parent (part-collected-info part ri))
ri key)]
[else
(values (hash-ref (collect-info-ext-ht (resolve-info-ci ri)) key #f)
#t)]))))
(define (resolve-get/ext? part ri key)
(let-values ([(v ext?) (resolve-get/where part ri key)])
(when ext?
(hash-set! (resolve-info-undef ri) (tag-key key ri) #t))
(values v ext?)))
(define (resolve-get part ri key)
(let-values ([(v ext?) (resolve-get/ext? part ri key)])
v))
(define (resolve-get/tentative part ri key)
(let-values ([(v ext?) (resolve-get/where part ri key)])
v))
(define (resolve-search search-key part ri key)
(let ([s-ht (hash-ref (resolve-info-searches ri)
search-key
(lambda ()
(let ([s-ht (make-hash)])
(hash-set! (resolve-info-searches ri)
search-key s-ht)
s-ht)))])
(hash-set! s-ht key #t))
(resolve-get part ri key))
(define (resolve-get-keys part ri key-pred)
(let ([l null])
(hash-for-each
(collected-info-info (part-collected-info part ri))
(lambda (k v) (when (key-pred k) (set! l (cons k l)))))
l))
(provide (struct-out collect-info)
(struct-out resolve-info))
;; ----------------------------------------
(provide tag?)
(define (tag? s)
(and (pair? s)
(symbol? (car s))
(pair? (cdr s))
(or (string? (cadr s))
(generated-tag? (cadr s))
(and (pair? (cadr s))
(list? (cadr s))))
(null? (cddr s))))
(provide block?)
(define (block? p)
(or (paragraph? p)
(table? p)
(itemization? p)
(nested-flow? p)
(compound-paragraph? p)
(delayed-block? p)))
(define content-symbols
#hasheq([nbsp . #t]
[mdash . #t]
[ndash . #t]
[ldquo . #t]
[rdquo . #t]
[rsquo . #t]
[prime . #t]
[rarr . #t]
[larr . #t]
[alpha . #t]
[infin . #t]
[lang . #t]
[rang . #t]))
(provide content?)
(define (content? v)
(or (string? v)
(element? v)
(and (list? v) (andmap content? v))
(delayed-element? v)
(part-relative-element? v)
(multiarg-element? v)
(hash-ref content-symbols v #f)))
(provide element-style?)
(define (element-style? s)
(or (style? s) (not s) (string? s) (symbol? s)))
(define (string-without-newline? s)
(and (string? s)
(not (regexp-match? #rx"\n" s))))
(provide-structs
[part ([tag-prefix (or/c false/c string?)]
[tags (listof tag?)]
[title-content (or/c false/c content?)]
[style style?]
[to-collect list?]
[blocks (listof block?)]
[parts (listof part?)])]
[paragraph ([style style?]
[content content?])]
[table ([style style?]
[blockss (listof (listof (or/c block? (one-of/c 'cont))))])]
[delayed-block ([resolve (any/c part? resolve-info? . -> . block?)])]
[itemization ([style style?]
[blockss (listof (listof block?))])]
[nested-flow ([style style?]
[blocks (listof block?)])]
[compound-paragraph ([style style?]
[blocks (listof block?)])]
[element ([style element-style?]
[content content?])]
[(toc-element element) ([toc-content content?])]
[(target-element element) ([tag tag?])]
[(toc-target-element target-element) ()]
[(page-target-element target-element) ()]
[(redirect-target-element target-element) ([alt-path path-string?]
[alt-anchor string?])]
[(link-element element) ([tag tag?])]
[(index-element element) ([tag tag?]
[plain-seq (and/c pair? (listof string-without-newline?))]
[entry-seq (listof content?)]
[desc any/c])]
[(image-element element) ([path (or/c path-string?
(cons/c (one-of/c 'collects)
(listof bytes?)))]
[suffixes (listof #rx"^[.]")]
[scale real?])]
[multiarg-element ([style element-style?]
[contents (listof content?)])]
[style ([name (or/c string? symbol? #f)]
[variants list?])]
;; variants:
[document-version ([text (or/c string? false/c)])]
[target-url ([addr path-string?])]
[color-variant ([color (or/c string? (list/c byte? byte? byte?))])]
[background-color-variant ([color (or/c string? (list/c byte? byte? byte?))])]
[table-columns ([styles (listof style?)])]
[table-cells ([styless (listof (listof style?))])]
[collected-info ([number (listof (or/c false/c integer?))]
[parent (or/c false/c part?)]
[info any/c])])
(provide plain)
(define plain (make-style #f null))
;; ----------------------------------------
;; Delayed element has special serialization support:
(define-struct delayed-element (resolve sizer plain)
#:property
prop:serializable
(make-serialize-info
(lambda (d)
(let ([ri (current-serialize-resolve-info)])
(unless ri
(error 'serialize-delayed-element
"current-serialize-resolve-info not set"))
(with-handlers ([exn:fail:contract?
(lambda (exn)
(error 'serialize-delayed-element
"serialization failed (wrong resolve info? delayed element never rendered?); ~a"
(exn-message exn)))])
(vector
(let ([l (delayed-element-content d ri)])
l)))))
#'deserialize-delayed-element
#f
(or (current-load-relative-directory) (current-directory))))
(provide/contract
(struct delayed-element ([resolve (any/c part? resolve-info? . -> . list?)]
[sizer (-> any)]
[plain (-> any)])))
(provide deserialize-delayed-element)
(define deserialize-delayed-element
(make-deserialize-info values values))
(provide delayed-element-content)
(define (delayed-element-content e ri)
(hash-ref (resolve-info-delays ri) e))
(provide delayed-block-blocks)
(define (delayed-block-blocks p ri)
(hash-ref (resolve-info-delays ri) p))
(provide current-serialize-resolve-info)
(define current-serialize-resolve-info (make-parameter #f))
;; ----------------------------------------
;; part-relative element has special serialization support:
(define-struct part-relative-element (collect sizer plain)
#:property
prop:serializable
(make-serialize-info
(lambda (d)
(let ([ri (current-serialize-resolve-info)])
(unless ri
(error 'serialize-part-relative-element
"current-serialize-resolve-info not set"))
(with-handlers ([exn:fail:contract?
(lambda (exn)
(error 'serialize-part-relative-element
"serialization failed (wrong resolve info? part-relative element never rendered?); ~a"
(exn-message exn)))])
(vector
(part-relative-element-content d ri)))))
#'deserialize-part-relative-element
#f
(or (current-load-relative-directory) (current-directory))))
(provide/contract
(struct part-relative-element ([collect (collect-info? . -> . list?)]
[sizer (-> any)]
[plain (-> any)])))
(provide deserialize-part-relative-element)
(define deserialize-part-relative-element
(make-deserialize-info values values))
(provide part-relative-element-content)
(define (part-relative-element-content e ci/ri)
(hash-ref (collect-info-relatives
(if (resolve-info? ci/ri) (resolve-info-ci ci/ri) ci/ri))
e))
(provide collect-info-parents)
;; ----------------------------------------
;; Delayed index entry also has special serialization support.
;; It uses the same delay -> value table as delayed-element
(define-struct delayed-index-desc (resolve)
#:mutable
#:property
prop:serializable
(make-serialize-info
(lambda (d)
(let ([ri (current-serialize-resolve-info)])
(unless ri
(error 'serialize-delayed-index-desc
"current-serialize-resolve-info not set"))
(with-handlers ([exn:fail:contract?
(lambda (exn)
(error 'serialize-index-desc
"serialization failed (wrong resolve info?); ~a"
(exn-message exn)))])
(vector
(delayed-element-content d ri)))))
#'deserialize-delayed-index-desc
#f
(or (current-load-relative-directory) (current-directory))))
(provide/contract
(struct delayed-index-desc ([resolve (any/c part? resolve-info? . -> . any)])))
(provide deserialize-delayed-index-desc)
(define deserialize-delayed-index-desc
(make-deserialize-info values values))
;; ----------------------------------------
(define-struct (collect-element element) (collect)
#:mutable
#:property
prop:serializable
(make-serialize-info
(lambda (d)
(vector (make-element
(element-style d)
(element-content d))))
#'deserialize-collect-element
#f
(or (current-load-relative-directory) (current-directory))))
(provide deserialize-collect-element)
(define deserialize-collect-element
(make-deserialize-info values values))
(provide/contract
[struct collect-element ([style element-style?]
[content content?]
[collect (collect-info? . -> . any)])])
;; ----------------------------------------
(define-struct (render-element element) (render)
#:property
prop:serializable
(make-serialize-info
(lambda (d)
(vector (make-element
(element-style d)
(element-content d))))
#'deserialize-render-element
#f
(or (current-load-relative-directory) (current-directory))))
(provide deserialize-render-element)
(define deserialize-render-element
(make-deserialize-info values values))
(provide/contract
[struct render-element ([style element-style?]
[content content?]
[render (any/c part? resolve-info? . -> . any)])])
;; ----------------------------------------
(define-struct generated-tag ()
#:property
prop:serializable
(make-serialize-info
(lambda (g)
(let ([ri (current-serialize-resolve-info)])
(unless ri
(error 'serialize-generated-tag
"current-serialize-resolve-info not set"))
(let ([t (hash-ref (collect-info-tags (resolve-info-ci ri)) g #f)])
(if t
(vector t)
(error 'serialize-generated-tag
"serialization failed (wrong resolve info?)")))))
#'deserialize-generated-tag
#f
(or (current-load-relative-directory) (current-directory))))
(provide (struct-out generated-tag))
(provide deserialize-generated-tag)
(define deserialize-generated-tag
(make-deserialize-info values values))
(provide generate-tag tag-key
current-tag-prefixes
add-current-tag-prefix)
(define (generate-tag tg ci)
(if (generated-tag? (cadr tg))
(let ([t (cadr tg)])
(list (car tg)
(let ([tags (collect-info-tags ci)])
(or (hash-ref tags t #f)
(let ([key (list* 'gentag
(hash-count tags)
(collect-info-gen-prefix ci))])
(hash-set! tags t key)
key)))))
tg))
(define (tag-key tg ri)
(if (generated-tag? (cadr tg))
(list (car tg)
(hash-ref (collect-info-tags (resolve-info-ci ri)) (cadr tg)))
tg))
(define current-tag-prefixes (make-parameter null))
(define (add-current-tag-prefix t)
(let ([l (current-tag-prefixes)])
(if (null? l)
t
(cons (car t) (append l (cdr t))))))
;; ----------------------------------------
(provide content->string
strip-aux)
(define content->string
(case-lambda
[(c)
(cond
[(element? c) (content->string (element-content c))]
[(multiarg-element? c) (content->string (multiarg-element-contents c))]
[(list? c) (apply string-append (map content->string c))]
[(part-relative-element? c) (content->string ((part-relative-element-plain c)))]
[(delayed-element? c) (content->string ((delayed-element-plain c)))]
[(string? c) c]
[else (case c
[(mdash) "---"]
[(ndash) "--"]
[(ldquo rdquo) "\""]
[(rsquo) "'"]
[(rarr) "->"]
[(lang) "<"]
[(rang) ">"]
[else (format "~s" c)])])]
[(c renderer sec ri)
(cond
[(and (link-element? c)
(null? (element-content c)))
(let ([dest (resolve-get sec ri (link-element-tag c))])
;; FIXME: this is specific to renderer
(if dest
(content->string (strip-aux
(if (pair? dest) (cadr dest) (vector-ref dest 1)))
renderer sec ri)
"???"))]
[(element? c) (content->string (element-content c) renderer sec ri)]
[(multiarg-element? c) (content->string (multiarg-element-contents c) renderer sec ri)]
[(list? c) (apply string-append
(map(lambda (e) (content->string e renderer sec ri))
c))]
[(delayed-element? c)
(content->string (delayed-element-content c ri) renderer sec ri)]
[(part-relative-element? c)
(content->string (part-relative-element-content c ri) renderer sec ri)]
[else (content->string c)])]))
(define (aux-element? e)
(and (element? e)
(let ([s (element-style e)])
(and (style? e)
(memq 'aux (style-variants s))))))
(define (strip-aux content)
(cond
[(null? content) null]
[(aux-element? content) null]
[(list? content) (map strip-aux content)]
[else content]))
;; ----------------------------------------
(provide block-width
content-width)
(define (content-width s)
(cond
[(string? s) (string-length s)]
[(list? s) (for/fold ([v 0]) ([s (in-list s)]) (+ v (content-width s)))]
[(element? s) (content-width (element-content s))]
[(multiarg-element? s) (content-width (multiarg-element-contents s))]
[(delayed-element? s) (content-width ((delayed-element-sizer s)))]
[(part-relative-element? s) (content-width ((part-relative-element-sizer s)))]
[else 1]))
(define (paragraph-width s)
(content-width (paragraph-content s)))
(define (flow-width f)
(apply max 0 (map block-width f)))
(define (block-width p)
(cond
[(paragraph? p) (paragraph-width p)]
[(table? p) (table-width p)]
[(itemization? p) (itemization-width p)]
[(nested-flow? p) (nested-flow-width p)]
[(compound-paragraph? p) (compound-paragraph-width p)]
[(delayed-block? p) 1]
[(eq? p 'cont) 0]))
(define (table-width p)
(let ([blocks (table-blockss p)])
(if (null? blocks)
0
(let loop ([blocks blocks])
(if (null? (car blocks))
0
(+ (apply max 0 (map block-width (map car blocks)))
(loop (map cdr blocks))))))))
(define (itemization-width p)
(apply max 0 (map flow-width (itemization-blockss p))))
(define (nested-flow-width p)
(+ 4 (apply max 0 (map block-width (nested-flow-blocks p)))))
(define (compound-paragraph-width p)
(apply max 0 (map block-width (compound-paragraph-blocks p))))
;; ----------------------------------------
(define (info-key? l)
(and (pair? l)
(symbol? (car l))
(pair? (cdr l))))
(provide info-key?)
(provide/contract
[part-collected-info (part? resolve-info? . -> . collected-info?)]
[collect-put! (collect-info? info-key? any/c . -> . any)]
[resolve-get ((or/c part? false/c) resolve-info? info-key? . -> . any)]
[resolve-get/tentative ((or/c part? false/c) resolve-info? info-key? . -> . any)]
[resolve-get/ext? ((or/c part? false/c) resolve-info? info-key? . -> . any)]
[resolve-search (any/c (or/c part? false/c) resolve-info? info-key? . -> . any)]
[resolve-get-keys ((or/c part? false/c) resolve-info? (info-key? . -> . any/c) . -> . any/c)])

View File

@ -1,6 +1,7 @@
#lang scheme/base
(require "struct.ss")
(require "core.ss"
"private/provide-structs.ss")
(provide-structs
[part-index-desc ()])

View File

@ -1,5 +1,6 @@
#lang scheme/base
(require "struct.ss"
(require "core.ss"
"private/provide-structs.ss"
"decode-struct.ss"
scheme/contract
scheme/class
@ -14,19 +15,36 @@
(rename-out [decode-content decode-elements])
decode-string
whitespace?
clean-up-index-string)
clean-up-index-string
pre-content?
pre-flow?)
(define (pre-content? i)
(or (string? i)
(and (content? i)
(not (list? i)))
(and (splice? i)
(andmap pre-content? (splice-run i)))))
(define (pre-flow? i)
(or (string? i)
(and (content? i)
(not (list? i)))
(block? i)
(and (splice? i)
(andmap pre-flow? (splice-run i)))))
(provide-structs
[title-decl ([tag-prefix (or/c false/c string?)]
[tags (listof tag?)]
[version (or/c string? false/c)]
[style any/c]
[content list?])]
[style style?]
[content content?])]
[part-start ([depth integer?]
[tag-prefix (or/c false/c string?)]
[tags (listof tag?)]
[style any/c]
[title list?])]
[style style?]
[title content?])]
[splice ([run list?])]
[part-index-decl ([plain-seq (listof string?)]
[entry-seq list?])]
@ -67,11 +85,6 @@
null
(list (decode-compound-paragraph (reverse (skip-whitespace accum))))))
(define (part-version p)
(if (versioned-part? p)
(versioned-part-version p)
#f))
(define (decode-flow* l keys colls tag-prefix tags vers style title part-depth)
(let loop ([l l] [next? #f] [keys keys] [colls colls] [accum null]
[title title] [tag-prefix tag-prefix] [tags tags] [vers vers]
@ -82,11 +95,15 @@
[tags (if (null? tags)
(list `(part ,(make-generated-tag)))
tags)])
(make-versioned-part
(make-part
tag-prefix
(append tags k-tags)
title
style
(if vers
(make-style (style-name style)
(cons (make-document-version vers)
(style-variants style)))
style)
(let ([l (append
(map (lambda (k tag)
(make-index-element #f null tag
@ -95,8 +112,8 @@
#f))
keys k-tags)
colls)])
(if (and title (not (or (eq? 'hidden style)
(and (list? style) (memq 'hidden style)))))
(if (and title
(not (memq 'hidden (style-variants style))))
(cons (make-index-element
#f null (car tags)
(list (clean-up-index-string
@ -106,9 +123,8 @@
(make-part-index-desc))
l)
l))
(make-flow (decode-accum-para accum))
null
vers))]
(decode-accum-para accum)
null))]
[(title-decl? (car l))
(cond [(not part-depth) (error 'decode "misplaced title: ~e" (car l))]
[title (error 'decode "found extra title: ~v" (car l))]
@ -124,29 +140,26 @@
(let ([para (decode-accum-para accum)]
[part (decode-flow* (cdr l) keys colls tag-prefix tags vers style
title part-depth)])
(make-versioned-part
(make-part
(part-tag-prefix part)
(part-tags part)
(part-title-content part)
(part-style part)
(part-to-collect part)
(make-flow (append para (list (car l))
(flow-paragraphs (part-flow part))))
(part-parts part)
(part-version part)))]
(append para (list (car l)) (part-flow part))
(part-parts part)))]
[(part? (car l))
(let ([para (decode-accum-para accum)]
[part (decode-flow* (cdr l) keys colls tag-prefix tags vers style
title part-depth)])
(make-versioned-part
(make-part
(part-tag-prefix part)
(part-tags part)
(part-title-content part)
(part-style part)
(part-to-collect part)
(make-flow (append para (flow-paragraphs (part-flow part))))
(cons (car l) (part-parts part))
(part-version part)))]
(append para (part-blocks part))
(cons (car l) (part-parts part))))]
[(and (part-start? (car l))
(or (not part-depth)
((part-start-depth (car l)) . <= . part-depth)))
@ -166,14 +179,13 @@
(add1 part-depth))]
[part (decode-flow* l keys colls tag-prefix tags vers style
title part-depth)])
(make-versioned-part (part-tag-prefix part)
(part-tags part)
(part-title-content part)
(part-style part)
(part-to-collect part)
(make-flow para)
(cons s (part-parts part))
(part-version part)))
(make-part (part-tag-prefix part)
(part-tags part)
(part-title-content part)
(part-style part)
(part-to-collect part)
para
(cons s (part-parts part))))
(if (splice? (car l))
(loop (append (splice-run (car l)) (cdr l)) s-accum)
(loop (cdr l) (cons (car l) s-accum))))))]
@ -205,29 +217,28 @@
(if m
(let ([part (loop m #t keys colls null title tag-prefix tags vers
style)])
(make-versioned-part
(make-part
(part-tag-prefix part)
(part-tags part)
(part-title-content part)
(part-style part)
(part-to-collect part)
(make-flow (append (decode-accum-para accum)
(flow-paragraphs (part-flow part))))
(part-parts part)
(part-version part)))
(append (decode-accum-para accum)
(part-blocks part))
(part-parts part)))
(loop (cdr l) #f keys colls (cons (car l) accum) title tag-prefix
tags vers style))))]
[else (loop (cdr l) #f keys colls (cons (car l) accum) title tag-prefix
tags vers style)])))
(define (decode-part l tags title depth)
(decode-flow* l null null #f tags #f #f title depth))
(decode-flow* l null null #f tags #f plain title depth))
(define (decode-styled-part l tag-prefix tags style title depth)
(decode-flow* l null null tag-prefix tags #f style title depth))
(define (decode-flow l)
(part-flow (decode-flow* l null null #f null #f #f #f #f)))
(part-blocks (decode-flow* l null null #f null #f plain #f #f)))
(define (match-newline-whitespace l)
(cond [(null? l) #f]
@ -246,7 +257,7 @@
(decode-part l null #f 0))
(define (decode-paragraph l)
(make-paragraph (decode-content l)))
(make-paragraph plain (decode-content l)))
(define (decode-content l)
(append-map (lambda (s) (if (string? s) (decode-string s) (list s)))
@ -256,7 +267,7 @@
(define (finish-accum para-accum)
(if (null? para-accum)
null
(list (make-paragraph (skip-whitespace (apply append (reverse para-accum)))))))
(list (make-paragraph plain (skip-whitespace (apply append (reverse para-accum)))))))
(let ([r (let loop ([l (skip-whitespace l)]
[para-accum null])
(cond
@ -274,7 +285,7 @@
(cons (list (car l)) para-accum))]))]))])
(cond
[(null? r)
(make-paragraph null)]
(make-paragraph plain null)]
[(null? (cdr r))
(car r)]
[(make-compound-paragraph #f r)])))
[(make-compound-paragraph plain r)])))

View File

@ -5,6 +5,6 @@ scribble/doclang
#:read scribble:read-inside
#:read-syntax scribble:read-syntax-inside
#:whole-body-readers? #t
#:wrapper1 (lambda (t) (list* 'doc '() (t)))
#:wrapper1 (lambda (t) (list* 'doc 'values '() (t)))
(require (prefix-in scribble: "../reader.ss"))

View File

@ -12,17 +12,17 @@
(define-syntax (*module-begin stx)
(syntax-case stx ()
[(_ id exprs . body)
[(_ id post-process exprs . body)
#'(#%module-begin
(doc-begin id exprs . body))]))
(doc-begin id post-process exprs . body))]))
(define-syntax (doc-begin stx)
(syntax-case stx ()
[(_ m-id (expr ...))
[(_ m-id post-process (expr ...))
#`(begin
(define m-id (decode (list . #,(reverse (syntax->list #'(expr ...))))))
(define m-id (post-process (decode (list . #,(reverse (syntax->list #'(expr ...)))))))
(provide m-id))]
[(_ m-id exprs . body)
[(_ m-id post-process exprs . body)
;; `body' probably starts with lots of string constants; it's
;; slow to trampoline on every string, so do them in a batch
;; here:
@ -34,7 +34,7 @@
(loop #'rest (cons #'s accum))]
[()
(with-syntax ([(accum ...) accum])
#`(doc-begin m-id (accum ... . exprs)))]
#`(doc-begin m-id post-process (accum ... . exprs)))]
[(body1 . body)
(with-syntax ([exprs (append accum #'exprs)])
(let ([expanded (local-expand
@ -46,7 +46,7 @@
#%require))))])
(syntax-case expanded (begin)
[(begin body1 ...)
#`(doc-begin m-id exprs body1 ... . body)]
#`(doc-begin m-id post-process exprs body1 ... . body)]
[(id . rest)
(and (identifier? #'id)
(ormap (lambda (kw) (free-identifier=? #'id kw))
@ -57,6 +57,6 @@
define-values-for-syntax
#%require
#%provide))))
#`(begin #,expanded (doc-begin m-id exprs . body))]
#`(begin #,expanded (doc-begin m-id post-process exprs . body))]
[_else
#`(doc-begin m-id (#,expanded . exprs) . body)])))]))]))
#`(doc-begin m-id post-process (#,expanded . exprs) . body)])))]))]))

View File

@ -90,13 +90,13 @@
(if (flow? p)
p
(make-flow (list p))))))
(format-output (cadar val-list+outputs) "schemestdout")
(format-output (caddar val-list+outputs) "schemeerror")
(format-output (cadar val-list+outputs) output-color)
(format-output (caddar val-list+outputs) error-color)
(if (string? (caar val-list+outputs))
;; Error result case:
(map
(lambda (s)
(car (format-output s "schemeerror")))
(car (format-output s error-color)))
(let sloop ([s (caar val-list+outputs)])
(if ((string-length s) . > . maxlen)
;; break the error message into multiple lines:
@ -117,8 +117,8 @@
(list (make-flow (list (make-paragraph
(list
(hspace 2)
(span-class "schemeresult"
(to-element/no-color v))))))))
(elem #:style result-color
(to-element/no-color v))))))))
val-list))))
(loop (cdr expr-paras)
(cdr val-list+outputs)
@ -313,8 +313,8 @@
(define (show-val v)
(span-class "schemeresult"
(to-element/no-color v)))
(elem #:style result-color
(to-element/no-color v)))
(define (do-interaction-eval-show ev e)
(parameterize ([current-command-line-arguments #()])

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
#lang scheme/base
(require "private/provide-structs.ss"
scheme/contract)
(provide-structs
[body-id ([value string?])]
[hover-variant ([text string?])]
[script-variant ([type string?]
[script (or/c path-string? (listof string?))])]
[css-addition ([path (or/c path-string? (cons/c 'collects (listof bytes?)))])]
[html-defaults ([prefix-path (or/c bytes? path-string? (cons/c 'collects (listof bytes?)))]
[style-path (or/c bytes? path-string? (cons/c 'collects (listof bytes?)))]
[extra-files (listof (or/c path-string? (cons/c 'collects (listof bytes?))))])]
[url-anchor ([name string?])]
[attributes ([assoc (listof (cons/c symbol? string?))])])

View File

@ -1,6 +1,8 @@
#lang scheme/base
(require "struct.ss"
(require "core.ss"
"latex-variants.ss"
"private/render-utils.ss"
scheme/class
scheme/runtime-path
scheme/port
@ -20,11 +22,15 @@
(define-runtime-path scribble-prefix-tex "scribble-prefix.tex")
(define-runtime-path scribble-tex "scribble.tex")
(define-runtime-path scribble-style-tex "scribble-style.tex")
(define (gif-to-png p)
(if (equal? (filename-extension p) #"gif")
(path-replace-suffix p #".png")
p))
(define (color->string c)
(if (string? c)
c
(format "~a,~a,~a"
(/ (car c) 255.0)
(/ (cadr c) 255.0)
(/ (caddr c) 255.0))))
(define (render-mixin %)
(class %
@ -33,48 +39,76 @@
(define/override (get-suffix) #".tex")
(inherit render-block
render-content
render-part
install-file
format-number
extract-part-style-files)
extract-part-style-files
extract-version
extract-authors
extract-pretitle)
(define/override (auto-extra-files? v) (latex-defaults? v))
(define/override (auto-extra-files-paths v) (latex-defaults-extra-files v))
(define/override (render-one d ri fn)
(let ([style-file (or style-file scribble-tex)]
[prefix-file (or prefix-file scribble-prefix-tex)])
(let* ([defaults (ormap (lambda (v) (and (latex-defaults? v) v))
(style-variants (part-style d)))]
[prefix-file (or prefix-file
(and defaults
(let ([v (latex-defaults-prefix defaults)])
(cond
[(bytes? v) v]
[else (main-collects-relative->path v)])))
scribble-prefix-tex)]
[style-file (or style-file
(and defaults
(let ([v (latex-defaults-style defaults)])
(cond
[(bytes? v) v]
[else (main-collects-relative->path v)])))
scribble-style-tex)])
(for-each
(lambda (style-file)
(with-input-from-file style-file
(lambda ()
(copy-port (current-input-port) (current-output-port)))))
(list* prefix-file style-file
(append style-extra-files
(extract-part-style-files
(if (bytes? style-file)
(display style-file)
(with-input-from-file style-file
(lambda ()
(copy-port (current-input-port) (current-output-port))))))
(list* prefix-file
scribble-tex
(append (extract-part-style-files
d
ri
'tex
(lambda (p) #f)))))
(lambda (p) #f)
tex-addition?
tex-addition-path)
(list style-file)
style-extra-files)))
(printf "\\begin{document}\n\\preDoc\n")
(when (part-title-content d)
(let ([m (ormap (lambda (v)
(and (styled-paragraph? v)
(equal? "author" (styled-paragraph-style v))
v))
(flow-paragraphs (part-flow d)))])
(when m
(do-render-paragraph m d ri #t)))
(let ([vers (or (and (versioned-part? d) (versioned-part-version d))
(version))])
(printf "\\titleAnd~aVersion{" (if (equal? vers "") "Empty" ""))
(let ([vers (extract-version d)]
[pres (extract-pretitle d)]
[auths (extract-authors d)])
(for ([pre (in-list pres)])
(do-render-paragraph pre d ri #t))
(printf "\\titleAnd~aVersionAnd~aAuthors{"
(if (equal? vers "") "Empty" "")
(if (null? auths) "Empty" ""))
(render-content (part-title-content d) d ri)
(printf "}{~a}\n" vers)))
(printf "}{~a}{" vers)
(for/fold ([first? #t]) ([auth (in-list auths)])
(unless first? (printf "\\SAuthorSep{}"))
(do-render-paragraph auth d ri #t)
#f)
(printf "}\n")))
(render-part d ri)
(printf "\n\n\\postDoc\n\\end{document}\n")))
(define/override (render-part-content d ri)
(let ([number (collected-info-number (part-collected-info d ri))])
(when (and (part-title-content d) (pair? number))
(when (part-style? d 'index)
(when (eq? (style-name (part-style d)) 'index)
(printf "\\twocolumn\n\\parskip=0pt\n\\addcontentsline{toc}{section}{Index}\n"))
(let ([no-number? (and (pair? number)
(or (not (car number))
@ -96,38 +130,32 @@
(printf "{")
(render-content (part-title-content d) d ri)
(printf "}")
(when (part-style? d 'index) (printf "\n\n")))
(when (eq? (style-name (part-style d)) 'index) (printf "\n\n")))
(for ([t (part-tags d)])
(printf "\\label{t:~a}\n\n" (t-encode (add-current-tag-prefix (tag-key t ri)))))
(render-flow (part-flow d) d ri #f)
(render-flow (part-blocks d) d ri #f)
(for ([sec (part-parts d)]) (render-part sec ri))
(when (part-style? d 'index) (printf "\\onecolumn\n\n"))
(when (eq? (style-name (part-style d)) 'index) (printf "\\onecolumn\n\n"))
null))
(define/override (render-paragraph p part ri)
(do-render-paragraph p part ri #f))
(define/private (do-render-paragraph p part ri author?)
(let ([style (and (styled-paragraph? p)
(let ([s (flatten-style
(styled-paragraph-style p))])
(if (with-attributes? s)
(let ([base (with-attributes-style s)])
(if (eq? base 'div)
(let ([a (assq 'class (with-attributes-assoc s))])
(if a
(cdr a)
base))
base))
s)))])
(unless (and (not author?)
(equal? style "author"))
(when (string? style)
(printf "\\~a{" style))
(if (toc-paragraph? p)
(printf "\\newpage \\tableofcontents \\newpage")
(super render-paragraph p part ri))
(when (string? style) (printf "}"))))
(define/private (do-render-paragraph p part ri show-pre?)
(let* ([sn (style-name (paragraph-style p))]
[style (if (eq? sn 'author)
"SAuthor"
sn)])
(unless (and (not show-pre?)
(or (eq? sn 'author)
(eq? sn 'pretitle)))
(let ([use-style? (string? style)])
(when use-style?
(printf "\\~a{" style))
(if (toc-paragraph? p)
(printf "\\newpage \\tableofcontents \\newpage")
(super render-paragraph p part ri))
(when use-style? (printf "}")))))
null)
(define/override (render-intrapara-block p part ri first? last? starting-item?)
@ -136,91 +164,131 @@
(begin0
(super render-intrapara-block p part ri first? last? starting-item?)))
(define/override (render-element e part ri)
(define/override (render-content e part ri)
(when (render-element? e)
((render-element-render e) this part ri))
(let ([part-label? (and (link-element? e)
(pair? (link-element-tag e))
(eq? 'part (car (link-element-tag e)))
(null? (element-content e)))])
(empty-content? (element-content e)))])
(parameterize ([done-link-page-numbers (or (done-link-page-numbers)
(link-element? e))])
(when (target-element? e)
(printf "\\label{t:~a}"
(t-encode (add-current-tag-prefix (tag-key (target-element-tag e) ri)))))
(when part-label?
(printf "\\SecRef{")
(render-content
(let ([dest (resolve-get part ri (link-element-tag e))])
(let ([dest (resolve-get part ri (link-element-tag e))])
(printf "\\~aRef~a{"
(case (and dest (length (cadr dest)))
[(0) "Book"]
[(1) "Chap"]
[else "Sec"])
(if (let ([s (element-style e)])
(and (style? s) (memq 'uppercase (style-variants s))))
"UC"
""))
(render-content
(if dest
(if (list? (cadr dest))
(format-number (cadr dest) null)
(begin (fprintf (current-error-port)
"Internal tag error: ~s -> ~s\n"
(link-element-tag e)
dest)
'("!!!")))
(list "???")))
part ri)
(printf "}{"))
(let ([style (and (element? e)
(let ([s (flatten-style (element-style e))])
(if (with-attributes? s)
(with-attributes-style s)
s)))]
[wrap (lambda (e s tt?)
(printf "\\~a{" s)
(parameterize ([rendering-tt (or tt? (rendering-tt))])
(super render-element e part ri))
(printf "}"))])
(cond
[(symbol? style)
(case style
[(italic) (wrap e "textit" #f)]
[(bold) (wrap e "textbf" #f)]
[(tt) (wrap e "Scribtexttt" #t)]
[(url) (wrap e "nolinkurl" 'exact)]
[(no-break) (super render-element e part ri)]
[(sf) (wrap e "textsf" #f)]
[(subscript) (wrap e "textsub" #f)]
[(superscript) (wrap e "textsuper" #f)]
[(hspace)
(let ([s (content->string (element-content e))])
(case (string-length s)
[(0) (void)]
[else
(printf "\\mbox{\\hphantom{\\Scribtexttt{~a}}}"
(regexp-replace* #rx"." s "x"))]))]
[(newline) (printf "\\\\")]
[else (error 'latex-render
"unrecognzied style symbol: ~s" style)])]
[(target-url? style)
(wrap e (format "href{~a}" (target-url-addr style)) #f)]
[(string? style)
(wrap e style (regexp-match? #px"^scheme(?!error)" style))]
[(and (pair? style) (memq (car style) '(bg-color color)))
(wrap e (format
"~a{~a}"
(format (if (eq? (car style) 'bg-color)
"in~acolorbox" "intext~acolor")
(if (= (length style) 2) "" "rgb"))
(if (= (length style) 2)
(cadr style)
(format "~a,~a,~a"
(/ (cadr style) 255.0)
(/ (caddr style) 255.0)
(/ (cadddr style) 255.0))))
#f)]
[(image-file? style)
(if (disable-images)
(void)
(let ([fn (install-file
(gif-to-png
(main-collects-relative->path
(image-file-path style))))])
(printf "\\includegraphics[scale=~a]{~a}"
(image-file-scale style) fn)))]
[else (super render-element e part ri)])))
(if (list? (cadr dest))
(format-number (cadr dest) null)
(begin (fprintf (current-error-port)
"Internal tag error: ~s -> ~s\n"
(link-element-tag e)
dest)
'("!!!")))
(list "???"))
part ri)
(printf "}{")))
(let* ([es (cond
[(element? e) (element-style e)]
[(multiarg-element? e) (multiarg-element-style e)]
[else #f])]
[style-name (if (style? es)
(style-name es)
es)]
[style (and (style? es) es)]
[core-render (lambda (e tt?)
(if (and (image-element? e)
(not (disable-images)))
(let ([fn (install-file
(select-suffix
(main-collects-relative->path
(image-element-path e))
(image-element-suffixes e)
'(".pdf" ".ps" ".png")))])
(printf "\\includegraphics[scale=~a]{~a}"
(image-element-scale e) fn))
(parameterize ([rendering-tt (or tt? (rendering-tt))])
(super render-content e part ri))))]
[wrap (lambda (e s tt?)
(printf "\\~a{" s)
(core-render e tt?)
(printf "}"))])
(define (finish tt?)
(cond
[(symbol? style-name)
(case style-name
[(italic) (wrap e "textit" tt?)]
[(bold) (wrap e "textbf" tt?)]
[(tt) (wrap e "Scribtexttt" #t)]
[(url) (wrap e "nolinkurl" 'exact)]
[(no-break) (core-render e tt?)]
[(sf) (wrap e "textsf" #f)]
[(subscript) (wrap e "textsub" #f)]
[(superscript) (wrap e "textsuper" #f)]
[(smaller) (wrap e "Smaller" #f)]
[(larger) (wrap e "Larger" #f)]
[(hspace)
(let ([s (content->string e)])
(case (string-length s)
[(0) (void)]
[else
(printf "\\mbox{\\hphantom{\\Scribtexttt{~a}}}"
(regexp-replace* #rx"." s "x"))]))]
[(newline) (printf "\\\\")]
[else (error 'latex-render
"unrecognzied style symbol: ~s" style)])]
[(string? style-name)
(let* ([v (if style (style-variants style) null)]
[tt? (cond
[(memq 'tt-chars v) #t]
[(memq 'exact-chars v) 'exact]
[else tt?])])
(cond
[(multiarg-element? e)
(printf "\\~a" style-name)
(if (null? (multiarg-element-contents e))
(printf "{}")
(for ([i (in-list (multiarg-element-contents e))])
(printf "{")
(render-content i part ri)
(printf "}")))]
[else
(wrap e style-name tt?)]))]
[else
(core-render e tt?)]))
(let loop ([l (if style (style-variants style) null)] [tt? #f])
(if (null? l)
(finish tt?)
(let ([v (car l)])
(cond
[(target-url? v)
(printf "\\href{~a}{" (target-url-addr v))
(loop (cdr l) #t)
(printf "}")]
[(color-variant? v)
(printf "\\intext~acolor{~a}{"
(if (string? (color-variant-color v)) "" "rgb")
(color->string (color-variant-color v)))
(loop (cdr l) tt?)
(printf "}")]
[(background-color-variant? v)
(printf "\\in~acolorbox{~a}{"
(if (string? (background-color-variant-color v)) "" "rgb")
(color->string (background-color-variant-color v)))
(loop (cdr l) tt?)
(printf "}")]
[else (loop (cdr l) tt?)]))))))
(when part-label?
(printf "}"))
(when (and (link-element? e)
@ -244,60 +312,70 @@
(string->list (format "~s" s)))))
(define/override (render-flow p part ri starting-item?)
(if (null? (flow-paragraphs p))
(if (null? p)
null
(begin
(render-block (car (flow-paragraphs p)) part ri starting-item?)
(for ([b (in-list (cdr (flow-paragraphs p)))])
(render-block (car p) part ri starting-item?)
(for ([b (in-list (cdr p))])
(printf "\n\n")
(render-block b part ri #f))
null)))
(define/override (render-table t part ri starting-item?)
(let* ([boxed? (eq? 'boxed (table-style t))]
[index? (eq? 'index (table-style t))]
(render-table* t part ri starting-item? "[t]"))
(define/private (render-table* t part ri starting-item? alignment)
(let* ([s-name (style-name (table-style t))]
[boxed? (eq? 'boxed s-name)]
[index? (eq? 'index s-name)]
[tableform
(cond [index? "list"]
[(not (current-table-mode)) "bigtabular"]
[else "tabular"])]
[opt (cond [(equal? tableform "bigtabular") ""]
[(equal? tableform "tabular") "[t]"]
[(equal? tableform "tabular") alignment]
[else ""])]
[flowss (if index? (cddr (table-flowss t)) (table-flowss t))]
[row-styles (cdr (or (and (list? (table-style t))
(assoc 'row-styles (table-style t)))
(cons #f (map (lambda (x) #f) flowss))))]
[twidth (if (null? (table-flowss t))
[blockss (if index? (cddr (table-blockss t)) (table-blockss t))]
[cell-styless (extract-table-cell-styles t)]
[twidth (if (null? (table-blockss t))
1
(length (car (table-flowss t))))]
(length (car (table-blockss t))))]
[single-column? (and (= 1 twidth)
(or (not (table-style t))
(string? (table-style t)))
(or (not s-name) (string? s-name))
(not (ormap (lambda (cell-styles)
(ormap (lambda (s)
(or (string? (style-name s))
(let ([l (style-variants s)])
(or (memq 'right l)
(memq 'center l)))))
cell-styles))
cell-styless))
(not (current-table-mode)))]
[inline?
(and (not single-column?)
(not boxed?)
(not index?)
(ormap (lambda (rs) (equal? rs "inferencetop")) row-styles)
(ormap (lambda (rs)
(ormap (lambda (cs) (style-name cs)) rs))
cell-styless)
(= 1 twidth)
(let ([m (current-table-mode)])
(and m
(equal? "bigtabular" (car m))
(= 1 (length (car (table-flowss (cadr m))))))))]
(= 1 (length (car (table-blockss (cadr m))))))))]
[boxline "{\\setlength{\\unitlength}{\\linewidth}\\begin{picture}(1,0)\\put(0,0){\\line(1,0){1}}\\end{picture}}"])
(if single-column?
(begin
(when (string? (table-style t))
(printf "\\begin{~a}" (table-style t)))
(do-render-blockquote
(make-blockquote "SingleColumn"
(apply append (map flow-paragraphs (map car (table-flowss t)))))
(when (string? s-name)
(printf "\\begin{~a}" s-name))
(do-render-nested-flow
(make-nested-flow (make-style "SingleColumn" null) (map car (table-blockss t)))
part
ri
#t)
(when (string? (table-style t))
(printf "\\end{~a}" (table-style t))))
(unless (or (null? flowss) (null? (car flowss)))
(when (string? s-name)
(printf "\\end{~a}" s-name)))
(unless (or (null? blockss) (null? (car blockss)))
(parameterize ([current-table-mode
(if inline? (current-table-mode) (list tableform t))]
[show-link-page-numbers
@ -311,8 +389,8 @@
(if (and starting-item? (equal? tableform "bigtabular"))
"\\bigtableinlinecorrect"
"")
(if (string? (table-style t))
(format "\\begin{~a}" (table-style t))
(if (string? s-name)
(format "\\begin{~a}" s-name)
"")
tableform
opt
@ -320,36 +398,27 @@
"\\bigtableleftpad"
"")
(string-append*
(map (lambda (i align)
(map (lambda (i cell-style)
(format "~a@{}"
(case align
[(center) "c"]
[(right) "r"]
[else "l"])))
(car flowss)
(cdr (or (and (list? (table-style t))
(assoc 'alignment
(or (table-style t) null)))
(cons #f (map (lambda (x) #f)
(car flowss)))))))
(cond
[(memq 'center (style-variants cell-style)) "c"]
[(memq 'right (style-variants cell-style)) "r"]
[else "l"])))
(car blockss)
(car cell-styless)))
(if boxed?
(if (equal? tableform "bigtabular")
(format "~a \\SEndFirstHead\n" boxline)
(format "\\multicolumn{~a}{@{}l@{}}{~a} \\\\\n"
(length (car flowss))
(length (car blockss))
boxline))
""))])
(let loop ([flowss flowss]
[row-styles row-styles])
(let ([flows (car flowss)]
[row-style (car row-styles)])
(let loop ([blockss blockss]
[cell-styless cell-styless])
(let ([flows (car blockss)]
[cell-styles (car cell-styless)])
(let loop ([flows flows]
[col-v-styles (or (and (list? row-style)
(let ([p (assoc 'valignment row-style)])
(and p (cdr p))))
(let ([p (and (list? (table-style t))
(assoc 'valignment (table-style t)))])
(and p (cdr p))))])
[cell-styles cell-styles])
(unless (null? flows)
(when index? (printf "\n\\item "))
(unless (eq? 'cont (car flows))
@ -359,110 +428,103 @@
(loop (cdr flows) (add1 n))]
[else n]))])
(unless (= cnt 1) (printf "\\multicolumn{~a}{l}{" cnt))
(render-table-flow (car flows) part ri twidth (and col-v-styles
(car col-v-styles)))
(render-table-cell (car flows) part ri twidth (car cell-styles))
(unless (= cnt 1) (printf "}"))
(unless (null? (list-tail flows cnt)) (printf " &\n"))))
(unless (null? (cdr flows)) (loop (cdr flows)
(and col-v-styles (cdr col-v-styles))))))
(unless (or index? (null? (cdr flowss)))
(printf " \\\\\n")
(when (equal? row-style "inferencetop") (printf "\\hline\n")))
(unless (null? (cdr flowss))
(loop (cdr flowss) (cdr row-styles)))))
(cdr cell-styles)))))
(unless (or index? (null? (cdr blockss)))
(printf " \\\\\n"))
(unless (null? (cdr blockss))
(loop (cdr blockss) (cdr cell-styless)))))
(unless inline?
(printf "\\end{~a}~a"
tableform
(if (string? (table-style t))
(format "\\end{~a}" (table-style t))
(if (string? s-name)
(format "\\end{~a}" s-name)
"")))))))
null)
(define/private (render-table-flow p part ri twidth vstyle)
;; Emit a \\ between blocks in single-column mode,
;; used a nested table otherwise for multiple elements.
(let ([in-table? (or (and (not (= twidth 1))
((length (flow-paragraphs p)) . > . 1))
(eq? vstyle 'top))])
(when in-table?
(printf "\\begin{tabular}~a{@{}l@{}}\n"
(cond
[(eq? vstyle 'top) "[t]"]
[(eq? vstyle 'center) "[c]"]
[else ""])))
(let loop ([ps (flow-paragraphs p)])
(cond
[(null? ps) (void)]
[else
(let ([minipage? (or (not (or (paragraph? (car ps))
(table? (car ps))))
(eq? vstyle 'center))])
(define/private (render-table-cell p part ri twidth vstyle)
(let ([top? (memq 'top (style-variants vstyle))]
[center? (memq 'vcenter (style-variants vstyle))])
(when (style-name vstyle)
(printf "\\~a{" (style-name vstyle)))
(let ([minipage? (and (not (table? p))
(or (not (paragraph? p))
top?
center?))])
(when minipage?
(printf "\\begin{minipage}~a{~a\\linewidth}\n"
(cond
[(eq? vstyle 'top) "[t]"]
[(eq? vstyle 'center) "[c]"]
[top? "[t]"]
[center? "[c]"]
[else ""])
(/ 1.0 twidth)))
(render-block (car ps) part ri #f)
(if (table? p)
(render-table* p part ri #f (cond
[center? "[c]"]
[else "[t]"]))
(render-block p part ri #f))
(when minipage?
(printf " \\end{minipage}\n"))
(unless (null? (cdr ps))
(printf " \\\\\n")
(when in-table?
(printf " ~ \\\\\n"))
(loop (cdr ps))))]))
(when in-table?
(printf "\n\\end{tabular}"))
(printf " \\end{minipage}\n")))
(when (style-name vstyle)
(printf "}"))
null))
(define/override (render-itemization t part ri)
(let* ([style-str (and (styled-itemization? t)
(string? (styled-itemization-style t))
(styled-itemization-style t))]
[mode (or style-str
(if (and (styled-itemization? t)
(eq? (styled-itemization-style t) 'ordered))
(let* ([style-str (let ([s (style-name (itemization-style t))])
(if (eq? s 'compact)
"compact"
s))]
[mode (or (and (string? style-str)
style-str)
(if (eq? 'ordered style-str)
"enumerate"
"itemize"))])
(printf "\\begin{~a}\\atItemizeStart" mode)
(for ([flow (itemization-flows t)])
(printf "\n\n\\~a" (if style-str
(for ([flow (in-list (itemization-blockss t))])
(printf "\n\n\\~a" (if (string? style-str)
(format "~aItem{" style-str)
"item "))
(render-flow flow part ri #t)
(when style-str
(when (string? style-str)
(printf "}")))
(printf "\\end{~a}" mode)
null))
(define/private (do-render-blockquote t part ri single-column?)
(let ([kind (or (blockquote-style t) "quote")])
(if (regexp-match #rx"^[\\]" kind)
(printf "~a{" kind)
(define/private (do-render-nested-flow t part ri single-column?)
(let ([kind (or (let ([s (style-name (nested-flow-style t))])
(or (and (string? s) s)
(and (eq? s 'inset) "quote")))
"Subflow")]
[command? (memq 'command (style-variants (nested-flow-style t)))])
(if command?
(printf "\\~a{" kind)
(printf "\\begin{~a}" kind))
(parameterize ([current-table-mode (if (or single-column?
(not (current-table-mode)))
(current-table-mode)
(list "blockquote" t))])
(render-flow (make-flow (blockquote-paragraphs t)) part ri #f))
(if (regexp-match #rx"^[\\]" kind)
(list "nested-flow" t))])
(render-flow (nested-flow-blocks t) part ri #f))
(if command?
(printf "}")
(printf "\\end{~a}" kind))
null))
(define/override (render-blockquote t part ri)
(do-render-blockquote t part ri #f))
(define/override (render-nested-flow t part ri)
(do-render-nested-flow t part ri #f))
(define/override (render-compound-paragraph t part ri starting-item?)
(let ([kind (compound-paragraph-style t)])
(let ([kind (style-name (compound-paragraph-style t))]
[command? (memq 'command (style-variants (compound-paragraph-style t)))])
(when kind
(if (regexp-match #rx"^[\\]" kind)
(printf "~a{" kind)
(if command?
(printf "\\~a{" kind)
(printf "\\begin{~a}" kind)))
(super render-compound-paragraph t part ri starting-item?)
(when kind
(if (regexp-match #rx"^[\\]" kind)
(if command?
(printf "}")
(printf "\\end{~a}" kind)))
null))
@ -480,6 +542,7 @@
[(rsquo) "'"]
[(prime) "$'$"]
[(rarr) "$\\rightarrow$"]
[(larr) "$\\leftarrow$"]
[(alpha) "$\\alpha$"]
[(infin) "$\\infty$"]
[(lang) "$\\langle$"]
@ -674,10 +737,10 @@
(define/override (table-of-contents sec ri)
;; FIXME: isn't local to the section
(make-toc-paragraph null))
(make-toc-paragraph plain null))
(define/override (local-table-of-contents part ri style)
(make-paragraph null))
(make-paragraph plain null))
;; ----------------------------------------

View File

@ -0,0 +1,9 @@
#lang scheme/base
(require "private/provide-structs.ss"
scheme/contract)
(provide-structs
[tex-addition ([path (or/c path-string? (cons/c 'collects (listof bytes?)))])]
[latex-defaults ([prefix (or/c bytes? path-string? (cons/c 'collects (listof bytes?)))]
[style (or/c bytes? path-string? (cons/c 'collects (listof bytes?)))]
[extra-files (listof (or/c path-string? (cons/c 'collects (listof bytes?))))])])

View File

@ -0,0 +1,12 @@
% This is the prefix for PLT Scheme manuals
\documentclass{article}
\parskip=10pt
\parindent=0pt
\partopsep=0pt
% Adjust margins to match HTML width for
% fixed-width font
\advance \oddsidemargin by -0.15in
\advance \evensidemargin by -0.15in
\advance \textwidth by 0.3in

View File

@ -1,6 +1,7 @@
#lang scheme/base
(require "struct.ss"
(require "core.ss"
"private/provide-structs.ss"
scheme/contract)
(provide-structs

View File

@ -0,0 +1,11 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Re-definitions for the PLT Scheme manual style
\renewcommand{\sectionNewpage}{\newpage}
\renewcommand{\preDoc}{\sloppy}
\renewcommand{\ChapRef}[2]{\SecRef{#1}{#2}}
\renewcommand{\SecRef}[2]{\S#1 ``#2''}
\renewcommand{\ChapRefUC}[2]{\SecRefUC{#1}{#2}}
\renewcommand{\SecRefUC}[2]{\SecRef{#1}{#2}}

View File

@ -1,5 +1,5 @@
#lang scheme/base
(require "basic.ss"
(require "base.ss"
"private/manual-style.ss"
"private/manual-scheme.ss"
"private/manual-mod.ss"
@ -15,7 +15,7 @@
(provide unsyntax
make-binding-redirect-elements
defidentifier
(all-from-out "basic.ss"
(all-from-out "base.ss"
"private/manual-style.ss"
"private/manual-scheme.ss"
"private/manual-mod.ss"

View File

@ -1,4 +1,17 @@
#lang scheme
(require scribble/doclang scribble/manual)
(provide (all-from-out scribble/doclang
scribble/manual))
#lang scheme/base
(require scribble/doclang
scribble/manual
"../private/defaults.ss")
(provide (except-out (all-from-out scribble/doclang) #%module-begin)
(all-from-out scribble/manual)
(rename-out [module-begin #%module-begin]))
(define-syntax-rule (module-begin id . body)
(#%module-begin id post-process () . body))
(define (post-process doc)
(add-defaults doc
(scribble-file "manual-prefix.tex")
(scribble-file "manual-style.tex")
null
#t))

View File

@ -5,6 +5,6 @@ scribble/manual/lang
#:read scribble:read-inside
#:read-syntax scribble:read-syntax-inside
#:whole-body-readers? #t
#:wrapper1 (lambda (t) (list* 'doc '() (t)))
#:wrapper1 (lambda (t) (cons 'doc (t)))
(require (prefix-in scribble: "../../reader.ss"))

View File

@ -0,0 +1,28 @@
#lang scheme/base
(require scribble/core
scribble/latex-variants
setup/main-collects)
(provide scribble-file
add-defaults)
(define (add-variant variants pred new)
(if (ormap pred variants)
variants
(cons new variants)))
(define (scribble-file s)
(path->main-collects-relative (build-path (collection-path "scribble") s)))
(define (add-defaults doc pfx styl extras version?)
(struct-copy part doc [style (make-style (style-name (part-style doc))
((if version? add-variant (lambda (x y z) x))
(add-variant
(style-variants (part-style doc))
latex-defaults?
(make-latex-defaults
pfx
styl
extras))
document-version?
(make-document-version (version))))]))

View File

@ -3,7 +3,6 @@
"../struct.ss"
"../scheme.ss"
"../search.ss"
"../config.ss"
"../basic.ss"
"../manual-struct.ss"
"manual-ex.ss"
@ -52,10 +51,10 @@
[sd (and stag (resolve-get/tentative sec ri stag))])
(list
(make-element
"schemesymbol"
symbol-color
(list
(cond [sd (make-link-element "schemesyntaxlink" (list s) stag)]
[vtag (make-link-element "schemevaluelink" (list s) vtag)]
(cond [sd (make-link-element syntax-link-color (list s) stag)]
[vtag (make-link-element value-link-color (list s) vtag)]
[else s]))))))
(lambda () s)
(lambda () s))))
@ -232,12 +231,12 @@
(list (symbol->string id))
(list
(make-element
"schemesymbol"
symbol-color
(list
(make-element
(if form?
"schemesyntaxlink"
"schemevaluelink")
syntax-link-color
value-link-color)
(list (symbol->string id))))))
((if form?
make-form-index-desc

View File

@ -3,7 +3,6 @@
"../struct.ss"
"../scheme.ss"
"../search.ss"
"../config.ss"
"../basic.ss"
"../manual-struct.ss"
"qsloc.ss"
@ -134,9 +133,9 @@
`(cls/intf ,(cadr tag))
(make-cls/intf
(make-element
"schemesymbol"
symbol-color
(list (make-link-element
"schemevaluelink"
value-link-color
(list (symbol->string (syntax-e (decl-name decl))))
tag)))
(map id-info (decl-app-mixins decl))

View File

@ -3,7 +3,6 @@
"../struct.ss"
"../scheme.ss"
"../search.ss"
"../config.ss"
"../basic.ss"
"../manual-struct.ss"
"qsloc.ss"

View File

@ -34,8 +34,8 @@
(lambda (c mk) (mk id/tag)))
content
(lambda (tag)
(make-element "schemesymbol"
(list (make-link-element "schemevaluelink" content
(make-element symbol-color
(list (make-link-element value-link-color content
(method-tag tag sym))))))))
(define (method-tag vtag sym)

View File

@ -3,7 +3,6 @@
"../struct.ss"
"../scheme.ss"
"../search.ss"
"../config.ss"
"../basic.ss"
"../manual-struct.ss"
"qsloc.ss"
@ -27,9 +26,9 @@
*defthing)
(define dots0
(make-element "schememeta" (list "...")))
(make-element meta-color (list "...")))
(define dots1
(make-element "schememeta" (list "...+")))
(make-element meta-color (list "...+")))
(define (make-openers n)
(schemeparenfont
@ -772,7 +771,7 @@
(list content)
tag
(list name)
(list (schemeidfont (make-element "schemevaluelink"
(list (schemeidfont (make-element value-link-color
(list name))))
(with-exporting-libraries
(lambda (libs)

View File

@ -57,9 +57,9 @@
(syntax/loc stx (schememod #:file #f lang rest ...))]))
(define (to-element/result s)
(make-element "schemeresult" (list (to-element/no-color s))))
(make-element result-color (list (to-element/no-color s))))
(define (to-element/id s)
(make-element "schemesymbol" (list (to-element/no-color s))))
(make-element symbol-color (list (to-element/no-color s))))
(define-syntax (keep-s-expr stx)
(syntax-case stx ()
@ -106,7 +106,7 @@
(define (as-modname-link s e)
(if (symbol? s)
(make-link-element "schememodlink"
(make-link-element module-link-color
(list e)
`(mod-path ,(symbol->string s)))
e))

View File

@ -1,30 +1,34 @@
#lang scheme/base
(require "../decode.ss"
"../struct.ss"
"../basic.ss"
"../base.ss"
(only-in "../basic.ss" aux-elem itemize)
"../scheme.ss"
(only-in "../core.ss" make-style plain)
"manual-utils.ss"
scheme/list
scheme/string)
(provide PLaneT etc
litchar verbatim
image image/plain onscreen menuitem defterm emph
litchar
image (rename-out [image image/plain]) onscreen menuitem defterm
schemefont schemevalfont schemeresultfont schemeidfont schemevarfont
schemeparenfont schemekeywordfont schememetafont schememodfont
schemeerror
schemeerror schemeoutput
filepath exec envvar Flag DFlag PFlag DPFlag
indexed-file indexed-envvar
link procedure
(rename-out [hyperlink link])
(rename-out [other-doc other-manual])
(rename-out [centered centerline])
itemize
procedure
idefterm
t inset-flow
pidefterm
hash-lang
centerline
commandline
elemtag elemref
secref seclink other-manual
margin-note
commandline
void-const undefined-const
aux-elem
math)
(define PLaneT (make-element "planetName" '("PLaneT")))
@ -37,51 +41,20 @@
(let ([s (string-append* (map (lambda (s) (regexp-replace* "\n" s " "))
strs))])
(if (regexp-match? #rx"^ *$" s)
(make-element "schemeinputbg" (list (hspace (string-length s))))
(make-element input-background-color (list (hspace (string-length s))))
(let ([^spaces (car (regexp-match-positions #rx"^ *" s))]
[$spaces (car (regexp-match-positions #rx" *$" s))])
(make-element
"schemeinputbg"
input-background-color
(list (hspace (cdr ^spaces))
(make-element "schemeinput"
(make-element input-color
(list (substring s (cdr ^spaces) (car $spaces))))
(hspace (- (cdr $spaces) (car $spaces)))))))))
(define (verbatim #:indent [i 0] s . more)
(define indent
(if (zero? i)
values
(let ([hs (hspace i)]) (lambda (x) (cons hs x)))))
(define strs (regexp-split #rx"\n" (string-append* s more)))
(define (str->elts str)
(let ([spaces (regexp-match-positions #rx"(?:^| ) +" str)])
(if spaces
(list* (substring str 0 (caar spaces))
(hspace (- (cdar spaces) (caar spaces)))
(str->elts (substring str (cdar spaces))))
(list (make-element 'tt (list str))))))
(define (make-line str)
(let* ([line (indent (str->elts str))]
[line (list (make-element 'tt line))])
(list (make-flow (list (make-omitable-paragraph line))))))
(make-table #f (map make-line strs)))
;; String String *-> Element
;; an in-lined image, relative to the current directory
(define (image #:scale [scale 1.0] filename-relative-to-source . alt)
(make-element (make-image-file filename-relative-to-source scale)
(decode-content alt)))
(define (image/plain filename-relative-to-source . alt)
(make-element (make-image-file filename-relative-to-source 1.0)
(decode-content alt)))
(define (onscreen . str)
(make-element 'sf (decode-content str)))
(define (menuitem menu item)
(make-element 'sf (list menu "|" item)))
(define (emph . str)
(make-element 'italic (decode-content str)))
(define (defterm . str)
(make-element 'italic (decode-content str)))
(define (idefterm . str)
@ -90,21 +63,21 @@
(define (schemefont . str)
(apply tt str))
(define (schemevalfont . str)
(make-element "schemevalue" (decode-content str)))
(make-element value-color (decode-content str)))
(define (schemeresultfont . str)
(make-element "schemeresult" (decode-content str)))
(make-element result-color (decode-content str)))
(define (schemeidfont . str)
(make-element "schemesymbol" (decode-content str)))
(make-element symbol-color (decode-content str)))
(define (schemevarfont . str)
(make-element "schemevariable" (decode-content str)))
(make-element variable-color (decode-content str)))
(define (schemeparenfont . str)
(make-element "schemeparen" (decode-content str)))
(make-element paren-color (decode-content str)))
(define (schememetafont . str)
(make-element "schememeta" (decode-content str)))
(make-element meta-color (decode-content str)))
(define (schememodfont . str)
(make-element "schememod" (decode-content str)))
(make-element module-color (decode-content str)))
(define (schemekeywordfont . str)
(make-element "schemekeyword" (decode-content str)))
(make-element keyword-color (decode-content str)))
(define (filepath . str)
(make-element 'tt (append (list "\"") (decode-content str) (list "\""))))
(define (indexed-file . str)
@ -141,17 +114,12 @@
[s (element->string f)])
(index* (list s) (list f) f)))
(define (procedure . str)
(make-element "schemeresult" `("#<procedure:" ,@(decode-content str) ">")))
(define (link url
#:underline? [underline? #t]
#:style [style (if underline? #f "plainlink")]
. str)
(make-element (make-target-url url style)
(decode-content str)))
(make-element result-color `("#<procedure:" ,@(decode-content str) ">")))
(define (schemeoutput . str)
(make-element output-color (decode-content str)))
(define (schemeerror . str)
(make-element "schemeerror" (decode-content str)))
(make-element error-color (decode-content str)))
(define (t . str)
(decode-paragraph str))
@ -159,11 +127,6 @@
(define (inset-flow . c)
(make-blockquote "insetpara" (flow-paragraphs (decode-flow c))))
(define (centerline . s)
(make-blockquote "SCentered" (flow-paragraphs (decode-flow s))))
(define (commandline . s)
(make-paragraph (cons (hspace 2) (map (lambda (s)
(if (string? s)
@ -171,20 +134,6 @@
s))
s))))
(define (elemtag t . body)
(make-target-element #f (decode-content body) `(elem ,t)))
(define (elemref #:underline? [u? #t] t . body)
(make-link-element (if u? #f "plainlink") (decode-content body) `(elem ,t)))
(define (secref s #:underline? [u? #t] #:doc [doc #f] #:tag-prefixes [prefix #f])
(make-link-element (if u? #f "plainlink") null `(part ,(doc-prefix doc prefix s))))
(define (seclink tag #:underline? [u? #t] #:doc [doc #f] #:tag-prefixes [prefix #f] . s)
(make-link-element (if u? #f "plainlink") (decode-content s)
`(part ,(doc-prefix doc prefix tag))))
(define (other-manual #:underline? [u? #t] doc)
(secref #:doc doc #:underline? u? "top"))
(define (pidefterm . s)
(let ([c (apply defterm s)])
(index (string-append (content->string (element-content c)) "s")
@ -192,26 +141,21 @@
(define (hash-lang)
(make-link-element
"schememodlink"
module-link-color
(list (schememodfont "#lang"))
`(part ,(doc-prefix '(lib "scribblings/guide/guide.scrbl") "hash-lang"))))
(define (margin-note . c)
(make-blockquote
"\\refpara"
(list
(make-blockquote
"refcolumn"
(list
(make-blockquote
"refcontent"
(flow-paragraphs (decode-flow c))))))))
(define void-const
(schemeresultfont "#<void>"))
(define undefined-const
(schemeresultfont "#<undefined>"))
(define (link url
#:underline? [underline? #t]
#:style [style (if underline? #f "plainlink")]
. str)
(apply hyperlink url #:style (if style (make-style style null) plain) str))
(define (math . s)
(let ([c (decode-content s)])
(make-element
@ -243,4 +187,4 @@
(list (make-element 'italic (list i)))])]
[(eq? i 'rsquo) (list 'prime)]
[else (list i)])))
c))))
c))))

View File

@ -1,7 +1,7 @@
#lang scheme/base
(require "../struct.ss"
"../decode.ss"
"../basic.ss"
"../base.ss"
scheme/list)
(provide spacer doc-prefix
@ -12,17 +12,6 @@
(define spacer (hspace 1))
(define doc-prefix
(case-lambda
[(doc s)
(if doc
(list (module-path-prefix->string doc) s)
s)]
[(doc prefix s)
(doc-prefix doc (if prefix
(append prefix (list s))
s))]))
(define (to-flow e)
(make-flow (list (make-omitable-paragraph (list e)))))
(define flow-spacer (to-flow spacer))

View File

@ -2,6 +2,7 @@
(require "../decode.ss"
"../scheme.ss"
"../struct.ss"
(only-in "../core.ss" style-name)
(for-syntax scheme/base
syntax/kerncase
syntax/boundmap)
@ -108,7 +109,7 @@
(unless (and (box-splice? box)
(= 1 (length (splice-run box)))
(table? (car (splice-run box)))
(eq? 'boxed (table-style (car (splice-run box)))))
(eq? 'boxed (style-name (table-style (car (splice-run box))))))
(error 'deftogether
"element is not a boxing splice containing a single table: ~e"
box))

View File

@ -0,0 +1,37 @@
#lang scheme/base
(require scheme/serialize
scheme/contract
(for-syntax scheme/base))
(provide provide-structs)
(define-syntax (provide-structs stx)
(syntax-case stx ()
[(_ (id ([field ct] ...)) ...)
#`(begin
(define-serializable-struct id (field ...)) ...
(provide/contract
#,@(let ([ids (syntax->list #'(id ...))]
[fields+cts (syntax->list #'(([field ct] ...) ...))])
(define (get-fields super-id)
(ormap (lambda (id fields+cts)
(if (identifier? id)
(and (free-identifier=? id super-id)
fields+cts)
(syntax-case id ()
[(my-id next-id)
(free-identifier=? #'my-id super-id)
#`[#,@(get-fields #'next-id)
#,@fields+cts]]
[_else #f])))
ids fields+cts))
(map (lambda (id fields+cts)
(if (identifier? id)
#`[struct #,id #,fields+cts]
(syntax-case id ()
[(id super)
#`[struct id (#,@(get-fields #'super)
#,@fields+cts)]])))
ids
fields+cts))))]))

View File

@ -0,0 +1,55 @@
#lang scheme/base
(require "../core.ss")
(provide part-style?
select-suffix
extract-table-cell-styles
empty-content?)
(define (part-style? p s)
(memq s (style-variants (part-style p))))
(define (select-suffix path suggested-suffixes accepted-suffixes)
(or (ormap (lambda (suggested)
(and (member suggested accepted-suffixes)
(let ([p (bytes->path
(bytes-append (path->bytes (if (string? path)
(string->path path)
path))
(string->bytes/utf-8 suggested)))])
(and (file-exists? p)
p))))
suggested-suffixes)
path))
(define (extract-table-cell-styles t)
(let ([vars (style-variants (table-style t))])
(or (let ([l (ormap (lambda (v)
(and (table-cells? v)
(table-cells-styless v)))
vars)])
(and l
(unless (= (length l) (length (table-blockss t)))
(error 'table
"table-cells variant list's length does not match row count: ~e vs. ~e"
l (length (table-blockss t))))
(for-each (lambda (l row)
(unless (= (length l) (length row))
(error 'table
"table-cells variant list contains a row whose length does not match the content: ~e vs. ~e"
l (length row))))
l (table-blockss t))
l))
(let ([cols (ormap (lambda (v) (and (table-columns? v) v)) vars)])
(and cols
(let ([cols (table-columns-styles cols)])
(map (lambda (row)
(unless (= (length cols) (length row))
(error 'table
"table-columns variant list's length does not match a row length: ~e vs. ~e"
cols (length row)))
cols)
(table-blockss t)))))
(map (lambda (row) (map (lambda (c) plain) row)) (table-blockss t)))))
(define (empty-content? c) (null? c))

View File

@ -1,6 +1,6 @@
#lang scheme/base
(require "struct.ss"
(require "core.ss"
"base-render.ss"
"xref.ss"
scheme/cmdline
@ -64,7 +64,7 @@
#:multi
[("++extra") file "add given file"
(current-extra-files (cons file (current-extra-files)))]
[("++style") file "add given .css/.tex file"
[("++style") file "add given .css/.tex file after others"
(current-style-extra-files (cons file (current-style-extra-files)))]
[("++info-in") file "load format-specific link information from <file>"
(current-info-input-files

View File

@ -0,0 +1,166 @@
/* See the beginning of "scribble.css". */
/* Monospace: */
.ScmIn, .ScmRdr, .ScmPn, .ScmMeta,
.ScmMod, .ScmKw, .ScmVar, .ScmSym,
.ScmRes, .ScmOut, .ScmCmt, .ScmVal {
font-family: monospace;
}
/* Serif: */
.inheritedlbl {
font-family: serif;
}
/* ---------------------------------------- */
/* Inherited methods, left margin */
.inherited {
width: 100%;
margin-top: 0.5em;
text-align: left;
background-color: #ECF5F5;
}
.inherited td {
font-size: 82%;
padding-left: 1em;
text-indent: -0.8em;
padding-right: 0.2em;
}
.inheritedlbl {
font-style: italic;
}
/* ---------------------------------------- */
/* Scheme text styles */
.ScmIn {
color: #cc6633;
background-color: #eeeeee;
}
.ScmInBG {
background-color: #eeeeee;
}
.ScmRdr {
}
.ScmPn {
color: #843c24;
}
.ScmMeta {
color: #262680;
}
.ScmMod {
color: black;
}
.ScmOpt {
color: black;
}
.ScmKw {
color: black;
font-weight: bold;
}
.ScmErr {
color: red;
font-style: italic;
}
.ScmVar {
color: #262680;
font-style: italic;
}
.ScmSym {
color: #262680;
}
.ScmValLink {
text-decoration: none;
color: blue;
}
.ScmModLink {
text-decoration: none;
color: blue;
}
.ScmStxLink {
text-decoration: none;
color: black;
font-weight: bold;
}
.ScmRes {
color: #0000af;
}
.ScmOut {
color: #960096;
}
.ScmCmt {
color: #c2741f;
}
.ScmVal {
color: #228b22;
}
/* ---------------------------------------- */
/* Some inline styles */
.together {
width: 100%;
}
.prototype td {
vertical-align: text-top;
}
.longprototype td {
vertical-align: bottom;
}
.ScmBlk td {
vertical-align: baseline;
}
.argcontract td {
vertical-align: text-top;
}
.highlighted {
background-color: #ddddff;
}
.defmodule {
width: 100%;
background-color: #F5F5DC;
}
.specgrammar {
float: right;
}
.SBibliography td {
vertical-align: text-top;
}
.leftindent {
margin-left: 1em;
margin-right: 0em;
}
.insetpara {
margin-left: 1em;
margin-right: 1em;
}

View File

@ -1,7 +1,9 @@
(module scheme scheme/base
(require "struct.ss"
(require "core.ss"
"basic.ss"
"search.ss"
"html-variants.ss"
"latex-variants.ss"
mzlib/class
mzlib/for
setup/main-collects
@ -20,6 +22,28 @@
current-variable-list
current-meta-list
input-color
output-color
input-background-color
no-color
reader-color
result-color
keyword-color
comment-color
paren-color
meta-color
value-color
symbol-color
variable-color
opt-color
error-color
syntax-link-color
value-link-color
module-color
module-link-color
block-color
highlighted-color
(struct-out var-id)
(struct-out shaped-parens)
(struct-out just-context)
@ -29,16 +53,38 @@
make-element-id-transformer
element-id-transformer?))
(define no-color "schemeplain")
(define reader-color "schemereader")
(define keyword-color "schemekeyword")
(define comment-color "schemecomment")
(define paren-color "schemeparen")
(define meta-color "schememeta")
(define value-color "schemevalue")
(define symbol-color "schemesymbol")
(define variable-color "schemevariable")
(define opt-color "schemeopt")
(define scheme-variants
(let ([abs (lambda (s)
(path->main-collects-relative (build-path (collection-path "scribble") s)))])
(list (make-css-addition (abs "scheme.css"))
(make-tex-addition (abs "scheme.tex")))))
(define (make-scheme-style s #:tt? [tt? #t])
(make-style s (if tt?
(cons 'tt-chars scheme-variants)
scheme-variants)))
(define output-color (make-scheme-style "ScmOut"))
(define input-color (make-scheme-style "ScmIn"))
(define input-background-color (make-scheme-style "ScmInBG"))
(define no-color (make-scheme-style "ScmPlain"))
(define reader-color (make-scheme-style "ScmRdr"))
(define result-color (make-scheme-style "ScmRes"))
(define keyword-color (make-scheme-style "ScmKw"))
(define comment-color (make-scheme-style "ScmCmt"))
(define paren-color (make-scheme-style "ScmPn"))
(define meta-color (make-scheme-style "ScmMeta"))
(define value-color (make-scheme-style "ScmVal"))
(define symbol-color (make-scheme-style "ScmSym"))
(define variable-color (make-scheme-style "ScmVar"))
(define opt-color (make-scheme-style "ScmOpt"))
(define error-color (make-scheme-style "ScmErr" #:tt? #f))
(define syntax-link-color (make-scheme-style "ScmStxLink"))
(define value-link-color (make-scheme-style "ScmValLink"))
(define module-color (make-scheme-style "ScmMod"))
(define module-link-color (make-scheme-style "ScmModLink"))
(define block-color (make-scheme-style "ScmBlk"))
(define highlighted-color (make-scheme-style "highlighted" #:tt? #f))
(define current-keyword-list
(make-parameter null))
@ -66,7 +112,7 @@
i)))
(define line-breakable-space (make-element 'tt (list " ")))
(define line-breakable-space (make-element 'tt " "))
;; These caches intentionally record a key with the value.
;; That way, when the value is no longer used, the key
@ -96,12 +142,12 @@
(list
(case (car tag)
[(form)
(make-link-element "schemesyntaxlink" (list s) tag)]
(make-link-element syntax-link-color (list s) tag)]
[else
(make-link-element "schemevaluelink" (list s) tag)]))
(make-link-element value-link-color (list s) tag)]))
(list
(make-element "badlink"
(list (make-element "schemevaluelink" (list s))))))))
(make-element value-link-color s))))))
(lambda () s)
(lambda () s)
key)])
@ -111,10 +157,8 @@
(define (make-element/cache style content)
(if (and element-cache
(pair? content)
(string? (car content))
(null? (cdr content)))
(let ([key (vector style (car content))])
(string? content))
(let ([key (vector style content)])
(let ([b (hash-ref element-cache key #f)])
(or (and b (weak-box-value b))
(let ([e (make-cached-element style content key)])
@ -184,6 +228,8 @@
[else paren-color])
(string-length s))))))
(define omitable (make-style #f '(omitable)))
(define (gen-typeset c multi-line? prefix1 prefix suffix color?)
(let* ([c (syntax-ize c 0)]
[content null]
@ -200,7 +246,7 @@
[line (or (syntax-line first) 0)])
(define (finish-line!)
(when multi-line?
(set! docs (cons (make-flow (list (make-omitable-paragraph (reverse content))))
(set! docs (cons (make-paragraph omitable (reverse content))
docs))
(set! content null)))
(define out
@ -209,16 +255,14 @@
(out v cls (let sz-loop ([v v])
(cond
[(string? v) (string-length v)]
[(list? v) (for/fold ([s 0]) ([v (in-list v)]) (+ s (sz-loop v)))]
[(sized-element? v) (sized-element-length v)]
[(and (element? v)
(= 1 (length (element-content v))))
(sz-loop (car (element-content v)))]
[(element? v)
(element-width v)]
(sz-loop (element-content v))]
[(delayed-element? v)
(element-width v)]
(content-width v)]
[(part-relative-element? v)
(element-width v)]
(content-width v)]
[(spaces? v)
(+ (sz-loop (car (element-content v)))
(spaces-cnt v)
@ -240,10 +284,10 @@
[else
(set! content (cons ((if highlight?
(lambda (c)
(make-element "highlighted" (list c)))
(make-element highlighted-color c))
values)
(if (and color? cls)
(make-element/cache cls (list v))
(make-element/cache cls v)
v))
content))
(set! dest-col (+ dest-col len))]))]))
@ -300,9 +344,9 @@
(make-sized-element
(if val? value-color #f)
(list
(make-element/cache (if val? value-color paren-color) '(". "))
(make-element/cache (if val? value-color paren-color) '". ")
(typeset a #f "" "" "" (not val?))
(make-element/cache (if val? value-color paren-color) '(" .")))
(make-element/cache (if val? value-color paren-color) '" ."))
(+ (syntax-span a) 4)))
(list (syntax-source a)
(syntax-line a)
@ -564,8 +608,8 @@
(finish-line!))
(if multi-line?
(if (= 1 (length docs))
(car (flow-paragraphs (car docs)))
(make-table "schemeblock" (map list (reverse docs))))
(car docs)
(make-table block-color (map list (reverse docs))))
(make-sized-element #f (reverse content) dest-col))))
(define (typeset c multi-line? prefix1 prefix suffix color?)
@ -590,8 +634,8 @@
[(elem color len)
(if (and (string? elem)
(= len (string-length elem)))
(make-element/cache (and color? color) (list elem))
(make-sized-element (and color? color) (list elem) len))])])
(make-element/cache (and color? color) elem)
(make-sized-element (and color? color) elem len))])])
mk)
color? 0))))

View File

@ -1,12 +1,2 @@
% This is the default prefix for Scribble-generated Latex
\documentclass{article}
\parskip=10pt
\parindent=0pt
\partopsep=0pt
% Adjust margins to match HTML width for
% fixed-width font
\advance \oddsidemargin by -0.15in
\advance \evensidemargin by -0.15in
\advance \textwidth by 0.3in

View File

View File

View File

@ -8,20 +8,17 @@
see if any font is set. */
/* Monospace: */
.maincolumn, .refpara, .tocset, .stt, .hspace,
.schemeinput, .schemereader, .schemeparen, .schememeta,
.schememod, .schemekeyword, .schemevariable, .schemesymbol,
.schemeresult, .schemestdout, .schemecomment, .schemevalue {
.maincolumn, .refpara, .tocset, .stt, .hspace {
font-family: monospace;
}
/* Serif: */
.main, .refcontent, .tocview, .tocsub, .inheritedlbl, i {
.main, .refcontent, .tocview, .tocsub, i {
font-family: serif;
}
/* Sans-serif: */
.version {
.version, .versionNoNav {
font-family: sans-serif;
}
@ -136,6 +133,9 @@ table td {
.version {
font-size: small;
}
.versionNoNav {
font-size: xx-small; /* avoid overlap with author */
}
/* ---------------------------------------- */
/* Margin notes */
@ -292,122 +292,9 @@ table td {
font-size: 70%;
}
/* ---------------------------------------- */
/* Inherited methods, left margin */
.inherited {
width: 100%;
margin-top: 0.5em;
text-align: left;
background-color: #ECF5F5;
}
.inherited td {
font-size: 82%;
padding-left: 1em;
text-indent: -0.8em;
padding-right: 0.2em;
}
.inheritedlbl {
font-style: italic;
}
/* ---------------------------------------- */
/* Scheme text styles */
.schemeinput {
color: #cc6633;
background-color: #eeeeee;
}
.schemeinputbg {
background-color: #eeeeee;
}
.schemereader {
}
.schemeparen {
color: #843c24;
}
.schememeta {
color: #262680;
}
.schememod {
color: black;
}
.schemeopt {
color: black;
}
.schemekeyword {
color: black;
font-weight: bold;
}
.schemeerror {
color: red;
font-style: italic;
}
.schemevariable {
color: #262680;
font-style: italic;
}
.schemesymbol {
color: #262680;
}
.schemevaluelink {
text-decoration: none;
color: blue;
}
.schememodlink {
text-decoration: none;
color: blue;
}
.schemesyntaxlink {
text-decoration: none;
color: black;
font-weight: bold;
}
.schemeresult {
color: #0000af;
}
.schemestdout {
color: #960096;
}
.schemecomment {
color: #c2741f;
}
.schemevalue {
color: #228b22;
}
/* ---------------------------------------- */
/* Some inline styles */
.leftindent {
margin-left: 1em;
margin-right: 0em;
}
.insetpara {
margin-left: 1em;
margin-right: 1em;
}
.indexlink {
text-decoration: none;
}
@ -437,52 +324,15 @@ ol ol ol ol { list-style-type: upper-alpha; }
i {
}
.SubFlow {
display: block;
}
.boxed {
width: 100%;
background-color: #E8E8FF;
}
.inlinetop{
display: inline;
vertical-align: text-top;
}
.together {
width: 100%;
}
.prototype td {
vertical-align: text-top;
}
.longprototype td {
vertical-align: bottom;
}
.schemeblock td {
vertical-align: baseline;
}
.argcontract td {
vertical-align: text-top;
}
.ghost {
color: white;
}
.highlighted {
background-color: #ddddff;
}
.defmodule {
width: 100%;
background-color: #F5F5DC;
}
.specgrammar {
float: right;
}
.hspace {
}
@ -490,14 +340,6 @@ i {
font-style: oblique;
}
.inferencetop td {
border-bottom: 1px solid black;
text-align: center;
}
.inferencebottom td {
text-align: center;
}
.badlink {
text-decoration: underline;
color: red;
@ -518,10 +360,6 @@ i {
.techinside:hover { color: blue; }
.techoutside:hover>.techinside { color: inherit; }
.SBibliography td {
vertical-align: text-top;
}
.SCentered {
text-align: center;
}
@ -531,10 +369,14 @@ i {
margin-right: 0.3em;
}
.smaller{
.Smaller{
font-size: 82%;
}
.Larger{
font-size: 122%;
}
/* A hack, inserted to break some Scheme ids: */
.mywbr {
width: 0;
@ -550,16 +392,22 @@ i {
border: 0;
}
.author {
.SAuthorListBox {
position: relative;
float: right;
left: 2em;
top: -3em;
top: -2.5em;
height: 0em;
width: 23em; /* very wide to keep author names on separate lines */
margin: 0em -23em 0em 0em;
width: 13em;
margin: 0em -13em 0em 0em;
}
.SAuthorList {
font-size: 82%;
}
.author:before {
.SAuthorList:before {
content: "by ";
}
.author {
display: inline;
white-space: nowrap;
}

View File

@ -11,47 +11,36 @@
\usepackage[usenames,dvipsnames]{color}
\hypersetup{bookmarks=true,bookmarksopen=true,bookmarksnumbered=true}
\newcommand{\SColorize}[2]{\color{#1}{#2}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Configuration that is especially meant to be overridden:
\newcommand{\inColor}[2]{{\Scribtexttt{\SColorize{#1}{#2}}}}
\definecolor{CommentColor}{rgb}{0.76,0.45,0.12}
\definecolor{ParenColor}{rgb}{0.52,0.24,0.14}
\definecolor{IdentifierColor}{rgb}{0.15,0.15,0.50}
\definecolor{ResultColor}{rgb}{0.0,0.0,0.69}
\definecolor{ValueColor}{rgb}{0.13,0.55,0.13}
\definecolor{OutputColor}{rgb}{0.59,0.00,0.59}
\definecolor{PaleBlue}{rgb}{0.90,0.90,1.0}
\definecolor{LightGray}{rgb}{0.90,0.90,0.90}
% Inserted before every ``chapter'', useful for starting each one on a new page:
\newcommand{\sectionNewpage}{}
% Hooks for actions within the `document' environment:
\newcommand{\preDoc}{}
\newcommand{\postDoc}{}
% Generated by `secref'; first arg is section number, second is section title:
\newcommand{\BookRef}[2]{\emph{#2}}
\newcommand{\ChapRef}[2]{\SecRef{#1}{#2}}
\newcommand{\SecRef}[2]{section~#1}
% Generated by `Secref':
\newcommand{\BookRefUC}[2]{\BookRef{#1}{#2}}
\newcommand{\ChapRefUC}[2]{\SecRefUC{#1}{#2}}
\newcommand{\SecRefUC}[2]{Section~#1}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Fonts
% Font commands used by generated text:
\newcommand{\Scribtexttt}[1]{{\texttt{#1}}}
\newcommand{\schemeplain}[1]{\inColor{black}{#1}}
\newcommand{\schemekeyword}[1]{{\SColorize{black}{\Scribtexttt{\textbf{#1}}}}}
\newcommand{\schemesyntaxlink}[1]{\schemekeyword{#1}}
\newcommand{\schemecomment}[1]{\inColor{CommentColor}{#1}}
\newcommand{\schemeparen}[1]{\inColor{ParenColor}{#1}}
\newcommand{\schemeinputbg}[1]{\inColor{ParenColor}{#1}}
\newcommand{\schemesymbol}[1]{\inColor{IdentifierColor}{#1}}
\newcommand{\schemevalue}[1]{\inColor{ValueColor}{#1}}
\newcommand{\schemevaluelink}[1]{\inColor{blue}{#1}}
\newcommand{\schememodlink}[1]{\inColor{blue}{#1}}
\newcommand{\schemeresult}[1]{\inColor{ResultColor}{#1}}
\newcommand{\schemestdout}[1]{\inColor{OutputColor}{#1}}
\newcommand{\schememeta}[1]{\inColor{IdentifierColor}{#1}}
\newcommand{\schememod}[1]{\inColor{black}{#1}}
\newcommand{\schemereader}[1]{\inColor{black}{#1}}
\newcommand{\schemevariablecol}[1]{\inColor{IdentifierColor}{#1}}
\newcommand{\schemevariable}[1]{{\schemevariablecol{\textsl{#1}}}}
\newcommand{\schemeerrorcol}[1]{\inColor{red}{#1}}
\newcommand{\schemeerror}[1]{{\schemeerrorcol{\textrm{\textit{#1}}}}}
\newcommand{\schemeopt}[1]{#1}
\newcommand{\textsub}[1]{$_{\hbox{\textsmaller{#1}}}$}
\newcommand{\textsuper}[1]{$^{\hbox{\textsmaller{#1}}}$}
\newcommand{\intextcolor}[2]{\textcolor{#1}{#2}}
\newcommand{\intextrgbcolor}[2]{\textcolor[rgb]{#1}{#2}}
\newcommand{\incolorbox}[2]{{\fboxrule=0pt\fboxsep=0pt\colorbox{#1}{#2}}}
\newcommand{\inrgbcolorbox}[2]{{\fboxrule=0pt\fboxsep=0pt\colorbox[rgb]{#1}{#2}}}
\newcommand{\schemeinput}[1]{\incolorbox{LightGray}{\schemeinputbg{#1}}}
\newcommand{\highlighted}[1]{\colorbox{PaleBlue}{\hspace{-0.5ex}\schemeinputbg{#1}\hspace{-0.5ex}}}
\newcommand{\plainlink}[1]{#1}
\newcommand{\techoutside}[1]{#1}
\newcommand{\techinside}[1]{#1}
@ -59,65 +48,75 @@
\newcommand{\indexlink}[1]{#1}
\newcommand{\noborder}[1]{#1}
\newcommand{\imageleft}[1]{} % drop it
\renewcommand{\smaller}[1]{\textsmaller{#1}}
\newcommand{\Smaller}[1]{\textsmaller{#1}}
\newcommand{\Larger}[1]{\textlarger{#1}}
\newcommand{\planetName}[1]{PLane\hspace{-0.1ex}T}
\newcommand{\refpara}[1]{\marginpar{\raggedright \footnotesize #1}}
\newenvironment{refcolumn}{}{}
\newenvironment{refcontent}{}{}
\newcommand{\titleAndEmptyVersion}[2]{\title{#1}\maketitle}
\newcommand{\titleAndVersion}[2]{\title{#1\\{\normalsize Version #2}}\maketitle}
\newcommand{\sectionNewpage}{\newpage}
\newcommand{\preDoc}{\sloppy}
\newcommand{\postDoc}{}
\newcommand{\slant}[1]{{\textsl{#1}}}
\newenvironment{leftindent}{\begin{quote}}{\end{quote}}
\newenvironment{insetpara}{\begin{quote}}{\end{quote}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Tables
\newcommand{\bibentry}[1]{\parbox[t]{0.8\linewidth}{#1}}
% stabular seems to be the lesser of all page-breaking table evironments
% The `stabular' environment seems to be the lesser of evils among
% page-breaking table environments:
\newenvironment{bigtabular}{\begin{stabular}}{\end{stabular}}
% used to keep the horizontal line for a definition on the same page:
% Used to keep the horizontal line for a definition on the same page:
\newcommand{\SEndFirstHead}[0]{ \nopagebreak \\ }
% attempts to correct weirdness when a table is the first thing in
% Corrects weirdness when a table is the first thing in
% an itemization:
\newcommand{\bigtableinlinecorrect}[0]{~
\vspace{-\baselineskip}\vspace{\parskip}}
% used to indent the table correctly in an itemization, since that's
% one of the things stabular gets wrong
% Used to indent the table correctly in an itemization, since that's
% one of the things stabular gets wrong:
\newlength{\stabLeft}
\newcommand{\bigtableleftpad}{\hspace{\stabLeft}}
\newcommand{\atItemizeStart}[0]{\addtolength{\stabLeft}{\labelsep}
\addtolength{\stabLeft}{\labelwidth}}
% For a single-column table in simple environments, it's better to
% use the `list' environment instead of `stabular'.
\newenvironment{SingleColumn}{\begin{list}{}{\topsep=0pt\partopsep=0pt%
\listparindent=0pt\itemindent=0pt\labelwidth=0pt\leftmargin=0pt\rightmargin=0pt%
\itemsep=0pt\parsep=0pt}\item}{\end{list}}
\newenvironment{schemeblock}{}{}
\newenvironment{defmodule}{}{}
\newenvironment{prototype}{}{}
\newenvironment{argcontract}{}{}
\newenvironment{together}{}{}
\newenvironment{SBibliography}{}{}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Etc.
% Default style for a nested flow:
\newenvironment{Subflow}{\begin{list}{}{\topsep=0pt\partopsep=0pt%
\listparindent=0pt\itemindent=0pt\labelwidth=0pt\leftmargin=0pt\rightmargin=0pt%
\itemsep=0pt}\item}{\end{list}}
% The 'inset neested-flow style uses the `quote' environment
% The 'compact itemization style:
\newenvironment{compact}{\begin{itemize}}{\end{itemize}}
\newcommand{\compactItem}[1]{\item #1}
\newcommand{\SecRef}[2]{\S#1 ``#2''}
% The nested-flow style for `centerline':
\newenvironment{SCentered}{\begin{trivlist}\item \centering}{\end{trivlist}}
% The \refpara command corresponds to `margin-note'. The
% refcolumn and refcontent environments also wrap the note,
% because they simplify the CSS side.
\newcommand{\refpara}[1]{\marginpar{\raggedright \footnotesize #1}}
\newenvironment{refcolumn}{}{}
\newenvironment{refcontent}{}{}
% Macros used by `title' and `author':
\newcommand{\titleAndVersionAndAuthors}[3]{\title{#1\\{\normalsize Version #2}}\author{#3}\maketitle}
\newcommand{\titleAndVersionAndEmptyAuthors}[3]{\title{#1\\{\normalsize Version #2}}#3\maketitle}
\newcommand{\titleAndEmptyVersionAndAuthors}[3]{\title{#1}\author{#3}\maketitle}
\newcommand{\titleAndEmptyVersionAndEmptyAuthors}[3]{\title{#1}\maketitle}
\newcommand{\SAuthor}[1]{#1}
\newcommand{\SAuthorSep}[1]{\qquad}
% Used for parts with the 'hidden style variant:
\newcommand{\sectionhidden}[1]{\section{#1}}
\newcommand{\subsectionhidden}[1]{\subsection{#1}}
\newcommand{\subsubsectionhidden}[1]{\subsubsection{#1}}
\newenvironment{SCentered}{\begin{trivlist}\item \centering}{\end{trivlist}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Scribble then generates the following:
%

View File

@ -0,0 +1,109 @@
#lang scheme/base
(require setup/main-collects
scribble/core
scribble/base
scribble/decode
scribble/html-variants
scribble/latex-variants
(for-syntax scheme/base))
(provide preprint
abstract include-abstract
authorinfo
conferenceinfo copyrightyear copyrightdata
category terms keywords)
(define-syntax (preprint stx)
(raise-syntax-error #f
"option must appear on the same line as `#lang scribble/sigplan'"
stx))
(define sigplan-extras
(let ([abs (lambda (s)
(path->main-collects-relative
(build-path (collection-path "scribble") "sigplan" s)))])
(list
(make-css-addition (abs "sigplan.css"))
(make-tex-addition (abs "sigplan.tex")))))
;; ----------------------------------------
;; Abstracts:
(define abstract-style (make-style "abstract" sigplan-extras))
(define (abstract . strs)
(make-nested-flow
abstract-style
(decode-flow strs)))
(define (extract-abstract p)
(unless (part? p)
(error 'include-abstract "doc binding is not a part: ~e" p))
(unless (null? (part-parts p))
(error 'include-abstract "abstract part has sub-parts: ~e" (part-parts p)))
(when (part-title-content p)
(error 'include-abstract "abstract part has title content: ~e" (part-title-content p)))
(part-blocks p))
(define-syntax-rule (include-abstract mp)
(begin
(require (only-in mp [doc abstract-doc]))
(make-nested-flow abstract-style (extract-abstract abstract-doc))))
;; ----------------------------------------
;; Authors and conference info:
(define (authorinfo name affiliation e-mail)
(author
(make-multiarg-element
(make-style "SAuthorinfo"sigplan-extras)
(list
(make-element #f (decode-content (list name)))
(make-element (make-style "SAuthorPlace" sigplan-extras)
(decode-content (list affiliation)))
(make-element (make-style "SAuthorEmail" sigplan-extras)
(decode-content (list e-mail)))))))
(define (conferenceinfo what where)
(make-paragraph
(make-style 'pretitle null)
(make-multiarg-element
(make-style "SConferenceInfo" sigplan-extras)
(list
(make-element #f (decode-content (list what)))
(make-element #f (decode-content (list where)))))))
(define (copyrightyear . when)
(make-paragraph
(make-style 'pretitle null)
(make-element
(make-style "SCopyrightYear" sigplan-extras)
(decode-content when))))
(define (copyrightdata . what)
(make-paragraph
(make-style 'pretitle null)
(make-element
(make-style "SCopyrightData" sigplan-extras)
(decode-content what))))
;; ----------------------------------------
;; Categories, terms, and keywords:
(define (category sec title sub [more #f])
(make-multiarg-element
(make-style (format "SCategory~a" (if more "Plus" "")) sigplan-extras)
(append
(list
(make-element #f (decode-content (list sec)))
(make-element #f (decode-content (list title)))
(make-element #f (decode-content (list sub))))
(if more
(list (make-element #f (decode-content (list more))))
null))))
(define (terms . str)
(make-element (make-style "STerms" sigplan-extras) (decode-content str)))
(define (keywords . str)
(make-element (make-style "SKeywords" sigplan-extras) (decode-content str)))

View File

@ -0,0 +1,41 @@
#lang scheme/base
(require scribble/doclang
scribble/core
scribble/base
scribble/decode
scribble/sigplan
"../private/defaults.ss"
(for-syntax scheme/base))
(provide (except-out (all-from-out scribble/doclang) #%module-begin)
(all-from-out scribble/sigplan)
(all-from-out scribble/base)
(rename-out [module-begin #%module-begin]))
(define-syntax (module-begin stx)
(syntax-case* stx (preprint) (lambda (a b) (eq? (syntax-e a) (syntax-e b)))
[(_ id ws . body)
;; Skip intraline whitespace to find options:
(and (string? (syntax-e #'ws))
(regexp-match? #rx"^ *$" (syntax-e #'ws)))
#'(module-begin id . body)]
[(_ id preprint . body)
#'(#%module-begin id (post-process #t) () . body)]
[(_ id . body)
#'(#%module-begin id (post-process #f) () . body)]))
(define ((post-process preprint?) doc)
(add-sigplan-styles
(add-defaults doc
(string->bytes/utf-8
(format "\\documentclass~a{sigplanconf}\n\\usepackage{times}\n\\usepackage{qcourier}\n"
(if preprint? "[preprint]" "")))
(scribble-file "sigplan/style.tex")
(list (scribble-file "sigplan/sigplanconf.cls"))
#f)))
(define (add-sigplan-styles doc)
;; Ensure that "sigplan.tex" is used, since "style.tex"
;; re-defines commands.
(struct-copy part doc [to-collect
(cons (terms)
(part-to-collect doc))]))

View File

@ -0,0 +1,10 @@
#lang s-exp syntax/module-reader
scribble/sigplan/lang
#:read scribble:read-inside
#:read-syntax scribble:read-syntax-inside
#:whole-body-readers? #t
#:wrapper1 (lambda (t) (cons 'doc (t)))
(require (prefix-in scribble: "../../reader.ss"))

View File

@ -0,0 +1,8 @@
/* Support for styles in scribble/sigplan */
.SAuthorPlace, .SAuthorEmail,
.SConferenceInfo, .SCopyrightYear, .SCopyrightData,
.SCategory, .SCategoryPlus, .STerms, .SKeywords {
display: none;
}

View File

@ -0,0 +1,18 @@
% Support for styles in scribble/sigplan
% These are replaced by scribble/sigplan/style.tex,
% which is used in combination with sigplanconf.sty
\newcommand{\SAuthorinfo}[3]{#1}
\newcommand{\SAuthorPlace}[1]{#1}
\newcommand{\SAuthorEmail}[1]{#1}
\newcommand{\SConferenceInfo}[2]{}
\newcommand{\SCopyrightYear}[1]{}
\newcommand{\SCopyrightData}[1]{}
\newcommand{\SCategory}[3]{}
\newcommand{\SCategoryPlus}[4]{}
\newcommand{\STerms}[1]{}
\newcommand{\SKeywords}[1]{}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,20 @@
\renewcommand{\titleAndVersionAndAuthors}[3]{\title{#1}#3\maketitle}
\renewcommand{\titleAndEmptyVersionAndAuthors}[3]{\titleAndVersionAndAuthors{#1}{#2}{#3}}
\renewcommand{\titleAndVersionAndEmptyAuthors}[3]{\title{#1}\authorinfo{Anonymous}{}{}\maketitle}
\renewcommand{\titleAndEmptyVersionAndEmptyAuthors}[3]{\titleAndVersionAndEmptyAuthors{#1}{#2}{#3}}
% Disable plain `author', enable `authorinfo:'
\renewcommand{\SAuthor}[1]{#1}
\renewcommand{\SAuthorinfo}[3]{\authorinfo{#1}{#2}{#3}}
\renewcommand{\SAuthorSep}[1]{}
\renewcommand{\SConferenceInfo}[2]{\conferenceinfo{#1}{#2}}
\renewcommand{\SCopyrightYear}[1]{\copyrightyear{#1}}
\renewcommand{\SCopyrightData}[1]{\copyrightdata{#1}}
\renewcommand{\SCategory}[3]{\category{#1}{#2}{#3}}
\renewcommand{\SCategoryPlus}[4]{\category{#1}{#2}{#3}[#4]}
\renewcommand{\STerms}[1]{\terms{#1}}
\renewcommand{\SKeywords}[1]{\keywords{#1}}

View File

@ -1,544 +1,401 @@
#lang scheme/base
(require scheme/serialize
(require (rename-in (except-in "core.ss"
target-url struct:target-url target-url? target-url-addr
deserialize-info:target-url-v0)
[make-target-url core:make-target-url])
"private/provide-structs.ss"
"html-variants.ss"
scheme/provide-syntax
scheme/struct-info
scheme/contract
(for-syntax scheme/base))
;; ----------------------------------------
(define-provide-syntax (compat**-out stx)
(syntax-case stx ()
[(_ struct-out o)
(let ([id (syntax-case #'o ()
[(id (field-id ...)) #'id]
[id #'id])])
(with-syntax ([make-id (datum->syntax id
(string->symbol (format "make-~a" (syntax-e id)))
id)]
[make-id/compat (datum->syntax id
(string->symbol (format "make-~a/compat" (syntax-e id)))
id)])
#'(combine-out
(except-out (struct-out o) make-id)
(rename-out [make-id/compat make-id]))))]
[(_ struct-out o ...) #'(combine-out (compat**-out struct-out o) ...)]))
(define-struct collect-info (ht ext-ht parts tags gen-prefix relatives parents))
(define-struct resolve-info (ci delays undef searches))
(define-provide-syntax (compat-out stx)
(syntax-case stx ()
[(_ . outs) #'(compat**-out struct-out . outs)]))
(define (part-collected-info part ri)
(hash-ref (collect-info-parts (resolve-info-ci ri))
part))
(define-provide-syntax (compat*-out stx)
(syntax-case stx ()
[(_ . outs) #'(compat**-out struct*-out . outs)]))
(define (collect-put! ci key val)
(let ([ht (collect-info-ht ci)])
(let ([old-val (hash-ref ht key #f)])
(when old-val
(fprintf (current-error-port)
"WARNING: collected information for key multiple times: ~e; values: ~e ~e\n"
key old-val val))
(hash-set! ht key val))))
(define (resolve-get/where part ri key)
(let ([key (tag-key key ri)])
(let ([v (hash-ref (if part
(collected-info-info (part-collected-info part ri))
(collect-info-ht (resolve-info-ci ri)))
key
#f)])
(cond
[v (values v #f)]
[part (resolve-get/where
(collected-info-parent (part-collected-info part ri))
ri key)]
[else
(values (hash-ref (collect-info-ext-ht (resolve-info-ci ri)) key #f)
#t)]))))
(define (resolve-get/ext? part ri key)
(let-values ([(v ext?) (resolve-get/where part ri key)])
(when ext?
(hash-set! (resolve-info-undef ri) (tag-key key ri) #t))
(values v ext?)))
(define (resolve-get part ri key)
(let-values ([(v ext?) (resolve-get/ext? part ri key)])
v))
(define (resolve-get/tentative part ri key)
(let-values ([(v ext?) (resolve-get/where part ri key)])
v))
(define (resolve-search search-key part ri key)
(let ([s-ht (hash-ref (resolve-info-searches ri)
search-key
(lambda ()
(let ([s-ht (make-hash)])
(hash-set! (resolve-info-searches ri)
search-key s-ht)
s-ht)))])
(hash-set! s-ht key #t))
(resolve-get part ri key))
(define (resolve-get-keys part ri key-pred)
(let ([l null])
(hash-for-each
(collected-info-info (part-collected-info part ri))
(lambda (k v) (when (key-pred k) (set! l (cons k l)))))
l))
(define-provide-syntax (struct*-out stx)
(syntax-case stx ()
[(_ [id (field-id ...)])
(with-syntax ([id? (datum->syntax #'id
(string->symbol (format "~a?" (syntax-e #'id)))
#'id)]
[struct:id (datum->syntax #'id
(string->symbol (format "struct:~a" (syntax-e #'id)))
#'id)]
[make-id (datum->syntax #'id
(string->symbol (format "make-~a" (syntax-e #'id)))
#'id)]
[(sel-id ...)
(map (lambda (field-id)
(datum->syntax field-id
(string->symbol (format "~a-~a" (syntax-e #'id) (syntax-e field-id)))
field-id))
(syntax->list #'(field-id ...)))])
#'(combine-out
id struct:id make-id id? sel-id ...))]
[(_ [id (field-id ...)]...)
#'(combine-out (struct*-out [id (field-id ...)]) ...)]))
(provide (struct-out collect-info)
(struct-out resolve-info))
(struct-out resolve-info)
tag? block?
make-flow flow? flow-paragraphs
;; ----------------------------------------
(except-out (compat-out part) part-title-content)
(rename-out [part-blocks part-flow]
[part-title-content/compat part-title-content])
make-versioned-part versioned-part?
make-unnumbered-part unnumbered-part?
(provide provide-structs)
(except-out (compat-out paragraph) paragraph-content)
(rename-out [paragraph-content/compat paragraph-content])
make-styled-paragraph
(rename-out [paragraph? styled-paragraph?]
[paragraph-style styled-paragraph-style])
make-omitable-paragraph omitable-paragraph?
(define-syntax (provide-structs stx)
(syntax-case stx ()
[(_ (id ([field ct] ...)) ...)
#`(begin
(define-serializable-struct id (field ...)) ...
(provide/contract
#,@(let ([ids (syntax->list #'(id ...))]
[fields+cts (syntax->list #'(([field ct] ...) ...))])
(define (get-fields super-id)
(ormap (lambda (id fields+cts)
(if (identifier? id)
(and (free-identifier=? id super-id)
fields+cts)
(syntax-case id ()
[(my-id next-id)
(free-identifier=? #'my-id super-id)
#`[#,@(get-fields #'next-id)
#,@fields+cts]]
[_else #f])))
ids fields+cts))
(map (lambda (id fields+cts)
(if (identifier? id)
#`[struct #,id #,fields+cts]
(syntax-case id ()
[(id super)
#`[struct id (#,@(get-fields #'super)
#,@fields+cts)]])))
ids
fields+cts))))]))
(compat-out table)
table-flowss
make-auxiliary-table auxiliary-table?
(provide tag?)
(define (tag? s)
(and (pair? s)
(symbol? (car s))
(pair? (cdr s))
(or (string? (cadr s))
(generated-tag? (cadr s))
(and (pair? (cadr s))
(list? (cadr s))))
(null? (cddr s))))
(struct-out delayed-block)
(provide block?)
(define (block? p)
(or (paragraph? p)
(table? p)
(itemization? p)
(blockquote? p)
(compound-paragraph? p)
(delayed-block? p)))
(compat-out itemization)
(rename-out [itemization-blockss itemization-flows]
[itemization? styled-itemization?]
[itemization-style styled-itemization-style])
make-styled-itemization
(define (string-without-newline? s)
(and (string? s)
(not (regexp-match? #rx"\n" s))))
make-blockquote
(compat-out compound-paragraph)
(except-out (compat-out element) element? element-style element-content)
(rename-out [element?/compat element?]
[element-style/compat element-style]
[element-content/compat element-content])
(except-out (compat*-out [toc-element (toc-content)])
toc-element-toc-content)
(rename-out [toc-element-toc-content/compat toc-element-toc-content])
(compat*-out [target-element (tag)]
[toc-target-element ()]
[page-target-element ()]
[redirect-target-element (alt-path alt-anchor)]
[link-element (tag)]
[index-element (tag plain-seq entry-seq desc)])
make-aux-element aux-element?
make-hover-element hover-element? hover-element-text
make-script-element script-element? script-element-type script-element-script
(struct-out collected-info)
(struct-out delayed-element)
; delayed-element-content delayed-block-blocks current-serialize-resolve-info
(struct-out part-relative-element)
; part-relative-element-content collect-info-parents
(struct-out delayed-index-desc)
(struct*-out [collect-element (collect)])
(struct*-out [render-element (render)])
(struct-out generated-tag)
; generate-tag tag-key current-tag-prefixes add-current-tag-prefix
content->string
(rename-out [content->string element->string]
[content-width element-width])
; strip-aux
block-width
info-key? part-collected-info collect-put!
resolve-get resolve-get/tentative resolve-get/ext? resolve-search resolve-get-keys)
(provide-structs
[part ([tag-prefix (or/c false/c string?)]
[tags (listof tag?)]
[title-content (or/c false/c list?)]
[style any/c]
[to-collect list?]
[flow flow?]
[parts (listof part?)])]
[(unnumbered-part part) ()]
[(versioned-part part) ([version (or/c string? false/c)])]
[flow ([paragraphs (listof block?)])]
[paragraph ([content list?])]
[(styled-paragraph paragraph) ([style any/c])]
[(omitable-paragraph paragraph) ()]
[table ([style any/c]
[flowss (listof (listof (or/c flow? (one-of/c 'cont))))])]
[(auxiliary-table table) ()]
[delayed-block ([resolve (any/c part? resolve-info? . -> . block?)])]
[itemization ([flows (listof flow?)])]
[(styled-itemization itemization) ([style any/c])]
[blockquote ([style any/c]
[paragraphs (listof block?)])]
[compound-paragraph ([style any/c]
[blocks (listof block?)])]
;; content = list of elements
[element ([style any/c]
[content list?])]
[(toc-element element) ([toc-content list?])]
[(target-element element) ([tag tag?])]
[(toc-target-element target-element) ()]
[(page-target-element target-element) ()]
[(redirect-target-element target-element) ([alt-path path-string?]
[alt-anchor string?])]
[(link-element element) ([tag tag?])]
[(index-element element) ([tag tag?]
[plain-seq (and/c pair? (listof string-without-newline?))]
[entry-seq list?]
[desc any/c])]
[(aux-element element) ()]
[(hover-element element) ([text string?])]
[(script-element element) ([type string?]
[script (or/c path-string? (listof string?))])]
;; specific renders support other elements, especially strings
[with-attributes ([style any/c]
[assoc (listof (cons/c symbol? string?))])]
[collected-info ([number (listof (or/c false/c integer?))]
[parent (or/c false/c part?)]
[info any/c])]
[target-url ([addr path-string?] [style any/c])]
[url-anchor ([name string?])]
[image-file ([path (or/c path-string?
(cons/c (one-of/c 'collects)
(listof bytes?)))]
[scale real?])])
[scale real?])]
[target-url ([addr path-string?] [style any/c])])
;; ----------------------------------------
(define (make-flow l) l)
(define (flow? l) (and (list? l) (andmap block? l)))
(define (flow-paragraphs l) l)
;; Delayed element has special serialization support:
(define-struct delayed-element (resolve sizer plain)
#:property
prop:serializable
(make-serialize-info
(lambda (d)
(let ([ri (current-serialize-resolve-info)])
(unless ri
(error 'serialize-delayed-element
"current-serialize-resolve-info not set"))
(with-handlers ([exn:fail:contract?
(lambda (exn)
(error 'serialize-delayed-element
"serialization failed (wrong resolve info? delayed element never rendered?); ~a"
(exn-message exn)))])
(vector
(let ([l (delayed-element-content d ri)])
(if (and (pair? l) (null? (cdr l)))
(car l)
(make-element #f l)))))))
#'deserialize-delayed-element
#f
(or (current-load-relative-directory) (current-directory))))
(define (list->content l)
(if (and (pair? l) (null? (cdr l)))
(car l)
l))
(provide/contract
(struct delayed-element ([resolve (any/c part? resolve-info? . -> . list?)]
[sizer (-> any)]
[plain (-> any)])))
(define (content->list v)
(if (list? v)
v
(list v)))
(provide deserialize-delayed-element)
(define deserialize-delayed-element
(make-deserialize-info values values))
(define (make-part/compat tag-prefix tags title-content orig-style to-collect flow parts)
(make-part tag-prefix
tags
(list->content title-content)
(convert-style orig-style)
to-collect
(flow-paragraphs flow)
parts))
(provide delayed-element-content)
(define (delayed-element-content e ri)
(hash-ref (resolve-info-delays ri) e))
(define (part-title-content/compat p)
(list (part-title-content p)))
(provide delayed-block-blocks)
(define (delayed-block-blocks p ri)
(hash-ref (resolve-info-delays ri) p))
(define (make-versioned-part tag-prefix tags title-content orig-style to-collect flow parts version)
(make-part tag-prefix
tags
(list->content title-content)
(let ([s (convert-style orig-style)])
(make-style (style-name s)
(cons
(make-document-version version)
(style-variants s))))
to-collect
(flow-paragraphs flow)
parts))
(define (versioned-part? p)
(and (part? p) (ormap document-version? (style-variants (part-style p)))))
(provide current-serialize-resolve-info)
(define current-serialize-resolve-info (make-parameter #f))
(define (make-unnumbered-part tag-prefix tags title-content orig-style to-collect flow parts)
(make-part tag-prefix
tags
(list->content title-content)
(let ([s (convert-style orig-style)])
(make-style (style-name s)
(cons 'unnumbered (style-variants s))))
to-collect
(flow-paragraphs flow)
parts))
(define (unnumbered-part? p)
(and (part? p) (memq 'unnumbered (style-variants (part-style p)))))
;; ----------------------------------------
(define (make-paragraph/compat content)
(make-paragraph plain (list->content content)))
(define (paragraph-content/compat p)
(content->list (paragraph-content p)))
(define (make-styled-paragraph content style)
(make-paragraph (convert-style style) (list->content content)))
;; part-relative element has special serialization support:
(define-struct part-relative-element (collect sizer plain)
#:property
prop:serializable
(make-serialize-info
(lambda (d)
(let ([ri (current-serialize-resolve-info)])
(unless ri
(error 'serialize-part-relative-element
"current-serialize-resolve-info not set"))
(with-handlers ([exn:fail:contract?
(lambda (exn)
(error 'serialize-part-relative-element
"serialization failed (wrong resolve info? part-relative element never rendered?); ~a"
(exn-message exn)))])
(vector
(make-element #f (part-relative-element-content d ri))))))
#'deserialize-part-relative-element
#f
(or (current-load-relative-directory) (current-directory))))
(define (make-omitable-paragraph content)
(make-paragraph (make-style #f '(omitable)) (list->content content)))
(define (omitable-paragraph? p)
(and (paragraph? p) (memq 'omitable (style-variants (paragraph-style p)))))
(provide/contract
(struct part-relative-element ([collect (collect-info? . -> . list?)]
[sizer (-> any)]
[plain (-> any)])))
(define (make-table/compat style cellss)
(make-table (convert-style style)
(map (lambda (cells)
(map (lambda (cell)
(cond
[(eq? cell 'cont) 'cont]
[(= 1 (length cell)) (car cell)]
[else (make-nested-flow plain cell)]))
cells))
cellss)))
(define (table-flowss t)
(map (lambda (row) (map (lambda (c) (make-flow (list c))) row))
(table-blockss t)))
(provide deserialize-part-relative-element)
(define deserialize-part-relative-element
(make-deserialize-info values values))
(define (make-auxiliary-table style cells)
(let ([t (make-table/compat style cells)])
(make-table (make-style (style-name (table-style t))
(cons 'aux
(style-variants (table-style t))))
(table-blockss t))))
(provide part-relative-element-content)
(define (part-relative-element-content e ci/ri)
(hash-ref (collect-info-relatives
(if (resolve-info? ci/ri) (resolve-info-ci ci/ri) ci/ri))
e))
(define (auxiliary-table? t)
(ormap (lambda (v) (eq? v 'aux) (style-variants (table-style t)))))
(provide collect-info-parents)
(define (make-itemization/compat flows)
(make-itemization plain flows))
(define (make-styled-itemization style flows)
(make-itemization (convert-style style) flows))
;; ----------------------------------------
(define (make-blockquote style blocks)
(make-nested-flow (convert-style (or style 'inset)) blocks))
;; Delayed index entry also has special serialization support.
;; It uses the same delay -> value table as delayed-element
(define-struct delayed-index-desc (resolve)
#:mutable
#:property
prop:serializable
(make-serialize-info
(lambda (d)
(let ([ri (current-serialize-resolve-info)])
(unless ri
(error 'serialize-delayed-index-desc
"current-serialize-resolve-info not set"))
(with-handlers ([exn:fail:contract?
(lambda (exn)
(error 'serialize-index-desc
"serialization failed (wrong resolve info?); ~a"
(exn-message exn)))])
(vector
(delayed-element-content d ri)))))
#'deserialize-delayed-index-desc
#f
(or (current-load-relative-directory) (current-directory))))
(define (make-compound-paragraph/compat style blocks)
(make-compound-paragraph (convert-style style) blocks))
(provide/contract
(struct delayed-index-desc ([resolve (any/c part? resolve-info? . -> . any)])))
(define (element-style-name s)
(if (style? s)
(style-name s)
s))
(define (element-style-variants s)
(if (style? s)
(style-variants s)
null))
(provide deserialize-delayed-index-desc)
(define deserialize-delayed-index-desc
(make-deserialize-info values values))
(define (add-element-variant v e)
(make-element (make-style (element-style-name (element-style e))
(cons v
(element-style-variants (element-style e))))
(element-content e)))
(define (check-element-style e pred)
(ormap pred (style-variants (element-style e))))
;; ----------------------------------------
(define (handle-image-style ctr style . args)
(if (image-file? style)
(make-image-element #f (list (apply ctr #f args))
(image-file-path style)
null
(image-file-scale style))
(apply ctr (convert-element-style style) args)))
(define-struct (collect-element element) (collect)
#:mutable
#:property
prop:serializable
(make-serialize-info
(lambda (d)
(vector (make-element
(element-style d)
(element-content d))))
#'deserialize-collect-element
#f
(or (current-load-relative-directory) (current-directory))))
(provide deserialize-collect-element)
(define deserialize-collect-element
(make-deserialize-info values values))
(provide/contract
[struct collect-element ([style any/c]
[content list?]
[collect (collect-info? . -> . any)])])
;; ----------------------------------------
(define-struct (render-element element) (render)
#:property
prop:serializable
(make-serialize-info
(lambda (d)
(vector (make-element
(element-style d)
(element-content d))))
#'deserialize-render-element
#f
(or (current-load-relative-directory) (current-directory))))
(provide deserialize-render-element)
(define deserialize-render-element
(make-deserialize-info values values))
(provide/contract
[struct render-element ([style any/c]
[content list?]
[render (any/c part? resolve-info? . -> . any)])])
;; ----------------------------------------
(define-struct generated-tag ()
#:property
prop:serializable
(make-serialize-info
(lambda (g)
(let ([ri (current-serialize-resolve-info)])
(unless ri
(error 'serialize-generated-tag
"current-serialize-resolve-info not set"))
(let ([t (hash-ref (collect-info-tags (resolve-info-ci ri)) g #f)])
(if t
(vector t)
(error 'serialize-generated-tag
"serialization failed (wrong resolve info?)")))))
#'deserialize-generated-tag
#f
(or (current-load-relative-directory) (current-directory))))
(provide (struct-out generated-tag))
(provide deserialize-generated-tag)
(define deserialize-generated-tag
(make-deserialize-info values values))
(provide generate-tag tag-key
current-tag-prefixes
add-current-tag-prefix)
(define (generate-tag tg ci)
(if (generated-tag? (cadr tg))
(let ([t (cadr tg)])
(list (car tg)
(let ([tags (collect-info-tags ci)])
(or (hash-ref tags t #f)
(let ([key (list* 'gentag
(hash-count tags)
(collect-info-gen-prefix ci))])
(hash-set! tags t key)
key)))))
tg))
(define (tag-key tg ri)
(if (generated-tag? (cadr tg))
(list (car tg)
(hash-ref (collect-info-tags (resolve-info-ci ri)) (cadr tg)))
tg))
(define current-tag-prefixes (make-parameter null))
(define (add-current-tag-prefix t)
(let ([l (current-tag-prefixes)])
(if (null? l)
t
(cons (car t) (append l (cdr t))))))
;; ----------------------------------------
(provide content->string
element->string
strip-aux)
(define content->string
(case-lambda
[(c) (c->s c element->string)]
[(c renderer sec ri)
(c->s c (lambda (e) (element->string e renderer sec ri)))]))
(define (c->s c do-elem)
(apply string-append (map do-elem c)))
(define element->string
(case-lambda
[(c)
(cond
[(element? c) (content->string (element-content c))]
[(part-relative-element? c) (element->string ((part-relative-element-plain c)))]
[(delayed-element? c) (element->string ((delayed-element-plain c)))]
[(string? c) c]
[else (case c
[(mdash) "---"]
[(ndash) "--"]
[(ldquo rdquo) "\""]
[(rsquo) "'"]
[(rarr) "->"]
[(lang) "<"]
[(rang) ">"]
[else (format "~s" c)])])]
[(c renderer sec ri)
(cond
[(and (link-element? c)
(null? (element-content c)))
(let ([dest (resolve-get sec ri (link-element-tag c))])
;; FIXME: this is specific to renderer
(if dest
(content->string (strip-aux
(if (pair? dest) (cadr dest) (vector-ref dest 1)))
renderer sec ri)
"???"))]
[(element? c) (content->string (element-content c) renderer sec ri)]
[(delayed-element? c)
(content->string (delayed-element-content c ri) renderer sec ri)]
[(part-relative-element? c)
(content->string (part-relative-element-content c ri) renderer sec ri)]
[else (element->string c)])]))
(define (strip-aux content)
(define (convert-element-style style)
(cond
[(null? content) null]
[(aux-element? (car content)) (strip-aux (cdr content))]
[else (cons (car content) (strip-aux (cdr content)))]))
[(not style) style]
[(string? style) style]
[(symbol? style) style]
[else (convert-style style)]))
;; ----------------------------------------
(provide block-width
element-width)
(define (element-width s)
(define (element?/compat e)
(or (element? e) (and (list? e) (content? e))))
(define (element-content/compat e)
(cond
[(string? s) (string-length s)]
[(element? s) (apply + (map element-width (element-content s)))]
[(delayed-element? s) (element-width ((delayed-element-sizer s)))]
[(part-relative-element? s) (element-width ((part-relative-element-sizer s)))]
[else 1]))
(define (paragraph-width s)
(apply + (map element-width (paragraph-content s))))
(define (flow-width f)
(apply max 0 (map block-width (flow-paragraphs f))))
(define (block-width p)
[(element? e) (content->list (element-content e))]
[else e]))
(define (element-style/compat e)
(cond
[(paragraph? p) (paragraph-width p)]
[(table? p) (table-width p)]
[(itemization? p) (itemization-width p)]
[(blockquote? p) (blockquote-width p)]
[(compound-paragraph? p) (compound-paragraph-width p)]
[(delayed-block? p) 1]))
[(element? e) (element-style e)]
[else #f]))
(define (table-width p)
(let ([flowss (table-flowss p)])
(if (null? flowss)
0
(let loop ([flowss flowss])
(if (null? (car flowss))
0
(+ (apply max 0 (map flow-width (map car flowss)))
(loop (map cdr flowss))))))))
(define (make-element/compat style content)
(handle-image-style make-element style (list->content content)))
(define (make-toc-element/compat style content toc-content)
(handle-image-style make-toc-element style (list->content content) (list->content toc-content)))
(define (toc-element-toc-content/compat e)
(content->list (toc-element-toc-content e)))
(define (make-target-element/compat style content tag)
(handle-image-style make-target-element style (list->content content) tag))
(define (make-toc-target-element/compat style content tag)
(handle-image-style make-toc-target-element style (list->content content) tag))
(define (make-page-target-element/compat style content tag)
(handle-image-style make-page-target-element style (list->content content) tag))
(define (make-redirect-target-element/compat style content tag alt-path alt-anchor)
(handle-image-style make-redirect-target-element style (list->content content) tag alt-path alt-anchor))
(define (make-link-element/compat style content tag)
(handle-image-style make-link-element style (list->content content) tag))
(define (make-index-element/compat style content tag plain-seq etry-seq desc)
(handle-image-style make-index-element style (list->content content) tag plain-seq etry-seq desc))
(define (itemization-width p)
(apply max 0 (map flow-width (itemization-flows p))))
(define (make-aux-element style content)
(add-element-variant 'aux (make-element/compat style content)))
(define (aux-element? e)
(check-element-style e (lambda (v) (eq? v 'aux))))
(define (blockquote-width p)
(+ 4 (apply max 0 (map block-width (blockquote-paragraphs p)))))
(define (make-hover-element style content text)
(add-element-variant (make-hover-variant text)
(make-element/compat style content)))
(define (hover-element? e)
(check-element-style e hover-variant?))
(define (hover-element-text e)
(ormap (lambda (v)
(and (hover-variant? v) (hover-variant-text e)))
(style-variants (element-style e))))
(define (compound-paragraph-width p)
(apply max 0 (map block-width (compound-paragraph-blocks p))))
(define (make-script-element style content type script)
(add-element-variant (make-script-variant type script)
(make-element/compat style content)))
(define (script-element? e)
(check-element-style e script-variant?))
(define (script-element-type e)
(ormap (lambda (v)
(and (script-variant? v) (script-variant-type e)))
(style-variants (element-style e))))
(define (script-element-script e)
(ormap (lambda (v)
(and (script-variant? v) (script-variant-script e)))
(style-variants (element-style e))))
;; ----------------------------------------
(provide part-style?)
(define (part-style? p s)
(let ([st (part-style p)])
(or (eq? s st)
(and (list? st) (memq s st)))))
;; ----------------------------------------
(define (info-key? l)
(and (pair? l)
(symbol? (car l))
(pair? (cdr l))))
(provide info-key?)
(provide/contract
[part-collected-info (part? resolve-info? . -> . collected-info?)]
[collect-put! (collect-info? info-key? any/c . -> . any)]
[resolve-get ((or/c part? false/c) resolve-info? info-key? . -> . any)]
[resolve-get/tentative ((or/c part? false/c) resolve-info? info-key? . -> . any)]
[resolve-get/ext? ((or/c part? false/c) resolve-info? info-key? . -> . any)]
[resolve-search (any/c (or/c part? false/c) resolve-info? info-key? . -> . any)]
[resolve-get-keys ((or/c part? false/c) resolve-info? (info-key? . -> . any/c) . -> . any/c)])
;; ----------------------------------------
(define (convert-style s)
(cond
[(not s) plain]
[(style? s) s]
[(string? s) (make-style s null)]
[(symbol? s) (make-style s null)]
[(and (list? s) (andmap symbol? s)) (make-style #f s)]
[(with-attributes? s) (let* ([wa (flatten-style s)]
[s (convert-style (with-attributes-style wa))])
(make-style (style-name s)
(cons
(make-attributes (with-attributes-assoc wa))
(style-variants s))))]
[(target-url? s) (let ([s (convert-style (target-url-style s))])
(make-style (style-name s)
(cons
(core:make-target-url (target-url-addr s))
(style-variants s))))]
[(image-file? s) (make-style #f null)]
[(and (list? s) (pair? s) (eq? (car s) 'color))
(make-style #f (list (make-color-variant
(if (string? (cadr s)) (cadr s) (cdr s)))))]
[(and (list? s) (pair? s) (eq? (car s) 'bg-color))
(make-style #f (list (make-background-color-variant
(if (string? (cadr s)) (cadr s) (cdr s)))))]
[(and (pair? s)
(list? s)
(andmap (lambda (v) (and (pair? v)
(memq (car v) '(alignment valignment row-styles style))))
s))
(let ([gen-columns (lambda (sn a va)
(map (lambda (sn a va)
(make-style sn
(append (if a (list a) null)
(if va (list va) null))))
(cdr (or sn (map (lambda (x) #f) (or va a))))
(cdr (or a (map (lambda (x) #f) (or va sn))))
(cdr (or va (map (lambda (x) #f) (or a sn))))))])
(make-style (let ([s (assq 'style s)])
(and s (cadr s)))
(let ([a (assq 'alignment s)]
[va (assq 'valignment s)])
(if (or a va)
(list (make-table-columns (gen-columns #f a va)))
(let ([l (cdr (assq 'row-styles s))])
(list
(make-table-cells
(map (lambda (row)
(let ([sn (assq 'style row)]
[a (assq 'alignment row)]
[va (assq 'valignment row)])
(if (or sn a va)
(gen-columns sn a va)
(error 'convert-style "no row style found"))))
l))))))))]
[else (error 'convert-style "unrecognized style: ~e" s)]))
(define (flatten-style s)
(cond
@ -568,5 +425,3 @@
(target-url-addr s)
rest)))]
[else s]))
(provide flatten-style)

View File

@ -1,6 +1,6 @@
(module text-render mzscheme
(require "struct.ss"
(require "core.ss"
mzlib/class)
(provide render-mixin)
@ -35,7 +35,7 @@
(part-title-content d))
(newline))
(newline)
(render-flow (part-flow d) d ht #f)
(render-flow (part-blocks d) d ht #f)
(let loop ([pos 1]
[secs (part-parts d)])
(unless (null? secs)
@ -44,31 +44,30 @@
(loop (add1 pos) (cdr secs))))))
(define/override (render-flow f part ht starting-item?)
(let ([f (flow-paragraphs f)])
(if (null? f)
null
(apply
append
(render-block (car f) part ht starting-item?)
(map (lambda (p)
(newline) (newline)
(render-block p part ht #f))
(cdr f))))))
(if (null? f)
null
(apply
append
(render-block (car f) part ht starting-item?)
(map (lambda (p)
(newline) (newline)
(render-block p part ht #f))
(cdr f)))))
(define/override (render-table i part ht inline?)
(let ([flowss (table-flowss i)])
(let ([flowss (table-blockss i)])
(if (null? flowss)
null
(apply
append
(map (lambda (d) (unless (eq? d 'cont) (render-flow d part ht #f))) (car flowss))
(map (lambda (d) (unless (eq? d 'cont) (render-block d part ht #f))) (car flowss))
(map (lambda (flows)
(newline)
(map (lambda (d) (unless (eq? d 'cont) (render-flow d part ht #f))) flows))
(cdr flowss))))))
(define/override (render-itemization i part ht)
(let ([flows (itemization-flows i)])
(let ([flows (itemization-blockss i)])
(if (null? flows)
null
(apply append

View File

@ -0,0 +1,494 @@
#lang scribble/doc
@(require scribble/manual
"utils.ss"
(for-syntax scheme/base)
(for-label setup/main-collects))
@(define-syntax def-section-like
(syntax-rules ()
[(_ id result/c x ...)
(defproc (id [#:tag tag (or/c false/c string? (listof string?)) #f]
[#:tag-prefix tag-prefix (or/c false/c string? module-path?) #f]
[#:style style (or/c style? #f string? symbol? (listof symbol?)) #f]
[pre-content pre-content?] (... ...+))
result/c
x ...)]))
@(define-syntax def-elem-proc
(syntax-rules ()
[(_ id x ...)
(defproc (id [pre-content pre-content?] (... ...))
element?
x ...)]))
@(define-syntax def-style-proc
(syntax-rules ()
[(_ id)
@def-elem-proc[id]{Like @scheme[elem], but with style @scheme['id].}]))
@title[#:tag "base"]{Base Document Forms}
@defmodule[scribble/base]{The @schememodname[scribble/base] library
provides functions and forms that can be used from code written either
in Scheme or with @elem["@"] expressions.
The @schememodname[scribble/base] name can also be used as a
language with @hash-lang[]. It acts like the
@schememodname[scribble/doc] language, except that the
@schememodname[scribble/base] library is also required into
the module.}
Functions provided by this library, such as @scheme[title] and
@scheme[italic], might be called from Scheme as
@schemeblock[
(title #:tag "how-to"
"How to Design " (italic "Great") " Programs")
]
They can also be called with @elem["@"] notation as
@verbatim[#:indent 2]|{
@title[#:tag "how-to"]{How to Design @italic{Great} Programs}
}|
Although the procedures are mostly design to be used from @elem["@"]
mode, they are easier to document in Scheme mode (partly because we
have @schememodname[scribble/manual]).
@; ------------------------------------------------------------------------
@section{Document Structure}
@defproc[(title [#:tag tag (or/c false/c string? (listof string?)) #f]
[#:tag-prefix tag-prefix (or/c false/c string? module-path?) #f]
[#:style style (or/c style? #f string? symbol? (listof symbol?)) #f]
[#:version vers (or/c string? false/c) #f]
[pre-content pre-content?] ...+)
title-decl?]{
Generates a @scheme[title-decl] to be picked up by @scheme[decode] or
@scheme[decode-part]. The @tech{decode}d @scheme[pre-content] (i.e.,
parsed with @scheme[decode-content]) supplies the title content. If
@scheme[tag] is @scheme[#f], a tag string is generated automatically
from the content. The tag string is combined with the symbol
@scheme['part] to form the full tag.
The @scheme[style] argument can be a style structure, or it can be one
of the following: a @scheme[#f] that corresponds to a ``plain'' style,
a string that is used as a @tech{style name}, a symbol that is used as
a @tech{variant}, or a list of symbols to be used as @tech{variants}.
For information on styles, see @scheme[part]. For example, a style of
@scheme['toc] causes sub-sections to be generated as separate pages in
multi-page HTML output.
The @scheme[tag-prefix] argument is propagated to the generated
structure (see @secref["tags"]). If @scheme[tag-prefix] is a module
path, it is converted to a string using
@scheme[module-path-prefix->string].
The @scheme[vers] argument is propagated to the @scheme[title-decl]
structure. Use @scheme[""] as @scheme[vers] to suppress version
rendering in the output.
The section title is automatically indexed by
@scheme[decode-part]. For the index key, leading whitespace and a
leading ``A'', ``An'', or ``The'' (followed by more whitespace) is
removed.}
@def-section-like[section part-start?]{ Like @scheme[title], but
generates a @scheme[part-start] of depth @scheme[0] to be by
@scheme[decode] or @scheme[decode-part].}
@def-section-like[subsection part-start?]{ Like @scheme[section], but
generates a @scheme[part-start] of depth @scheme[1].}
@def-section-like[subsubsection part-start?]{ Like @scheme[section], but
generates a @scheme[part-start] of depth @scheme[2].}
@def-section-like[subsubsub*section paragraph?]{ Similar to
@scheme[section], but merely generates a paragraph that looks like an
unnumbered section heading (for when the nesting gets too deep to
include in a table of contents).}
@defform[(include-section module-path)]{ Requires @scheme[module-path]
and returns its @scheme[doc] export (without making any imports
visible to the enclosing context). Since this form expands to
@scheme[require], it must be used in a module or top-level context.}
@defproc[(author [auth content?] ...) block?]{
Generates a @scheme[paragraph] with style name @scheme['author] to
show the author(s) of a document, where each author is represented by
@tech{content}. Normally, this function is used after
@scheme[title] for the beginning of a document. See also
@scheme[author+email].}
@defproc[(author+email [author elem] [email string?]) element?]{
Combines an author name with an e-mail address, obscuring the e-mail
address slightly to avoid address-harvesting robots.}
@; ------------------------------------------------------------------------
@section{Blocks}
@defproc[(para [#:style style (or/c style? string? symbol? #f)]
[pre-content pre-content?] ...) paragraph?]{
Creates a @tech{paragraph} containing the @tech{decode}d
@scheme[pre-content] (i.e., parsed with @scheme[decode-paragraph]).
The @scheme[style] argument can be a style, @scheme[#f] to indicate a
``plain'' style, a string that is used as a @tech{style name}, or a
symbol that is used as a @tech{style name}. (Note that
@scheme[section] and @scheme[para] treat symbols differently as
@scheme[style] arguments.)}
@defproc[(nested [#:style style (or/c style? string? symbol? #f)]
[pre-flow pre-flow?] ...) nested-flow?]{
Creates a @tech{nested flow} containing the @tech{decode}d
@scheme[pre-flow] (i.e., parsed with @scheme[decode-flow]).
The @scheme[style] argument is handled the same as @scheme[para].
The @scheme['inset] style causes the nested flow to be inset compared
to surrounding text.}
@defproc[(centered [pre-flow pre-flow?] ...) nested-flow?]{
Produces a @tech{nested flow} whose content is centered.}
@defproc[(margin-note [pre-content pre-content?] ...) blockquote?]{
Produces a @tech{nested flow} that is typeset in the margin, instead
of inlined.}
@defproc[(itemlist [itm item?] ...
[#:style style (or/c style? string? symbol? #f) #f])
itemization?]{
Constructs an @scheme[itemization] given a sequence of items
constructed by @scheme[item].
The @scheme[style] argument is handled the same as @scheme[para]. The
@scheme['ordered] style numbers items, instead of just using a
bullet.}
@defproc[(item [pre-flow pre-flow?] ...) item?]{
Creates an item for use with @scheme[itemlist]. The @tech{decode}d
@scheme[pre-flow] (i.e., parsed with @scheme[decode-flow]) is the item
content.}
@defproc[(item? [v any/c]) boolean?]{
Returns @scheme[#t] if @scheme[v] is an item produced by
@scheme[item], @scheme[#f] otherwise.}
@defproc[(tabular [cells (listof (listof (or/c block? content? 'cont)))]
[#:style style (or/c style? string? symbol? #f) #f])
table?]{
Creates a @tech{table} with the given content, which is supplies as a
list of rows, where each row has a list of cells. The length of all
rows must match.
Use @scheme['cont] as a cell to continue the content of the preceding
cell in a row in the space that would otherwise be used for a new
cell. A @scheme['cont] must not appear as the first cell in a row.
The @scheme[style] argument is handled the same as @scheme[para].}
@defproc[(verbatim [#:indent indent exact-nonnegative-integer? 0] [str string?] ...+)
block?]{
Typesets @scheme[str]s in typewriter font with the linebreaks
specified by newline characters in @scheme[str]. Consecutive spaces in
the @scheme[str]s are converted to @scheme[hspace] to ensure that they
are all preserved in the output. Additional space (via
@scheme[hspace]) as specified by @scheme[indent] is added to the
beginning of each line.
The @scheme[str]s are @emph{not} decoded with @scheme[decode-content],
so @scheme[(verbatim "---")] renders with three hyphens instead of an
em-dash. Beware, however, that @litchar["@"] for a @scheme[verbatim]
call performs some processing before delivering arguments to
@scheme[verbatim]. The @scheme[verbatim] form is typically used with
@litchar["|{"]...@litchar["}|"] or similar brackets to disable
@litchar["@"] notation within the @scheme[verbatim] argument, like
this:
@verbatim[#:indent 2]|{
@verbatim|{
Use @bold{---} like this...
}|
}|
which renders as
@verbatim[#:indent 2]|{
Use @bold{---} like this...
}|
Even with @litchar["|{"]...@litchar["}|"], beware that consistent
leading whitespace is removed; see @secref["alt-body-syntax"] for more
information.
See also @scheme[literal].}
@; ------------------------------------------------------------------------
@section{Text Styles and Content}
@defproc[(elem [pre-content pre-content?] ...
[#:style style (or style? string? symbol? #f) #f])
element?]{
Wraps the @tech{decode}d @scheme[pre-content] as an element with style
@scheme[style].}
@def-style-proc[italic]
@def-style-proc[bold]
@def-style-proc[tt]
@def-style-proc[subscript]
@def-style-proc[superscript]
@def-elem-proc[smaller]{Like @scheme[elem], but with style
@scheme['smaller]. When uses of @scheme[smaller] are nested, text
gets progressively smaller.}
@def-elem-proc[larger]{Like @scheme[elem], but with style
@scheme['larger]. When uses of @scheme[larger] are nested, text
gets progressively larger.}
@defproc[(emph [pre-content pre-content?] ...) element?]{
The same as @scheme[italic].}
@defproc[(hspace [n exact-nonnegative-integer?]) element?]{
Produces an element containing @scheme[n] spaces and style
@scheme['hspace].}
@defproc[(literal [str string?] ...+) element?]{
Produces an element containing literally @scheme[str]s with no
decoding via @scheme[decode-content].
Beware that @litchar["@"] for a @scheme[literal] call performs some
processing before delivering arguments to @scheme[literal]. The
@scheme[literal] form can be used with @litchar["|{"]...@litchar["}|"]
or similar brackets to disable @litchar["@"] notation within the
@scheme[literal] argument, like this:
@verbatim[#:indent 2]|{
@literal|{@bold{---}}|
}|
which renders as
@verbatim[#:indent 2]|{
@literal|{@bold{---}}|
}|
See also @scheme[verbatim].}
@defproc[(image [path (or/c path-string? (cons/c 'collects (listof bytes?)))]
[#:scale scale real? 1.0]
[#:suffixes suffixes (listof #rx"^[.]") null]
[pre-content pre-content?] ...)
element?]{
Creates an image element from the given path. The @tech{decode}d
@scheme[pre-content] serves as the alternate text for contexts where
the image cannot be displayed.
The path is relative to the current directory, which is set by
@exec{setup-plt} and @exec{scribble} to the directory of the main
document file. The @scheme[path] argument also can be a result of
@scheme[path->main-collects-relative].
The strings in @scheme[suffixes] are filtered to those supported by
given renderer, and then the acceptable suffixes are tried in
order. The HTML renderer supports @scheme[".png"] and
@scheme[".gif"], while the Latex renderer supports @scheme[".png"],
@scheme[".pdf"], and @scheme[".ps"] (but @scheme[".ps"] works only
when converting Latex output to DVI, and @scheme[".png"] and
@scheme[".pdf"] work only for converting Latex output to PDF).}
@; ------------------------------------------------------------------------
@section[#:tag "base-links"]{Links}
@defproc[(hyperlink [url string?] [pre-content pre-content?] ...
[#:underline? underline? any/c #t]
[#:style style (or/c style? string? symbol? #f) (if underline? #f "plainlink")])
element?]{
The @tech{decode}d @scheme[pre-content] is hyperlinked to
@scheme[url]. If @scheme[style] is not supplied, then
@scheme[underline?] determines how the link is rendered.}
@defproc[(url [dest string?]) element?]{
Generates a literal hyperlinked URL.}
@defproc[(secref [tag string?]
[#:doc module-path (or/c module-path? false/c) #f]
[#:tag-prefixes prefixes (or/c (listof string?) false/c) #f]
[#:underline? underline? any/c #t])
element?]{
Inserts the hyperlinked title of the section tagged @scheme[tag], but
elements in the title content with the @scheme['aux] @tech{variant}
are omitted in the hyperlink label.
If @scheme[#:doc module-path] is provided, the @scheme[tag] refers to
a tag with a prefix determined by @scheme[module-path]. When
@exec{setup-plt} renders documentation, it automatically adds a tag
prefix to the document based on the source module. Thus, for example,
to refer to a section of the PLT Scheme reference,
@scheme[module-path] would be @scheme['(lib
"scribblings/reference/reference.scrbl")].
The @scheme[#:tag-prefixes prefixes] argument similarly supports
selecting a particular section as determined by a path of tag
prefixes. When a @scheme[#:doc] argument is provided, then
@scheme[prefixes] should trace a path of tag-prefixed subsections to
reach the @scheme[tag] section. When @scheme[#:doc] is not provided,
the @scheme[prefixes] path is relative to any enclosing section (i.e.,
the youngest ancestor that produces a match).
If @scheme[underline?] is @scheme[#f], then the hyperlink is rendered
in HTML without an underline.}
@defproc[(seclink [tag string?]
[#:doc module-path (or/c module-path? false/c) #f]
[#:tag-prefixes prefixes (or/c (listof string?) false/c) #f]
[#:underline? underline? any/c #t]
[pre-content pre-content?] ...) element?]{
Like @scheme[secref], but the link label is the @tech{decode}d
@scheme[pre-content] instead of the target section's name.}
@defproc[(other-doc [module-path module-path?]
[#:underline? underline? any/c #t])
element?]{
Like @scheme[secref] for the document's implicit @scheme["top"]
tag. Use this function to refer to a whole manual instead of
@scheme[secref], in case a special style in the future is used for
manual titles.}
@defproc[(elemtag [t (or/c tag? string?)] [pre-content pre-content?] ...) element?]{
The tag @scheme[t] refers to the content form of
@scheme[pre-content].}
@defproc[(elemref [t (or/c tag? string?)] [pre-content pre-content?] ...
[#:underline? underline? any/c #t]) element?]{
The @tech{decode}d @scheme[pre-content] is hyperlinked to @scheme[t],
which is normally defined using @scheme[elemtag].}
@defproc[(module-path-prefix->string [mod-path module-path?])
string?]{
Converts a module path to a string by resolving it to a path, and
using @scheme[path->main-collects-relative].}
@; ------------------------------------------------------------------------
@section[#:tag "base-indexing"]{Indexing}
@defproc[(index [words (or/c string? (listof string?))]
[pre-content pre-content?] ...)
index-element?]{
Creates an index element given a plain-text string---or list of
strings for a hierarchy, such as @scheme['("strings" "plain")] for a
``plain'' entry below a more general ``strings'' entry. As index keys,
the strings are ``cleaned'' using @scheme[clean-up-index-strings]. The
strings (without clean-up) also serve as the text to render in the
index. The @tech{decode}d @scheme[pre-content] is the text to appear
inline as the index target.
Use @scheme[index] when an index entry should point to a specific word
or phrase within the typeset document (i.e., the
@scheme[pre-content]). Use @scheme[section-index], instead, to create
an index entry that leads to a section, instead of a specific word or
phrase within the section.}
@defproc[(index* [words (listof string?)]
[word-contents (listof list?)]
[pre-content pre-content?] ...)
index-element?]{
Like @scheme[index], except that @scheme[words] must be a list, and
the list of contents render in the index (in parallel to
@scheme[words]) is supplied as @scheme[word-contents].
}
@defproc[(as-index [pre-content pre-content?] ...)
index-element?]{
Like @scheme[index], but the word to index is determined by applying
@scheme[content->string] on the @tech{decode}d @scheme[pre-content].}
@defproc[(section-index [word string?] ...)
part-index-decl?]{
Creates a @scheme[part-index-decl] to be associated with the enclosing
section by @scheme[decode]. The @scheme[word]s serve as both the keys
and as the rendered forms of the keys within the index.}
@defproc[(index-section [#:tag tag (or/c false/c string?) "doc-index"])
part?]{
Produces a part that shows the index the enclosing document. The
optional @scheme[tag] argument is used as the index section's tag.}
@; ------------------------------------------------------------------------
@section{Tables of Contents}
@defproc[(table-of-contents) delayed-block?]{
Returns a delayed flow element that expands to a table of contents for
the enclosing section. For Latex output, however, the table of
contents currently spans the entire enclosing document.}
@defproc[(local-table-of-contents [#:style style (or/c symbol? #f) #f])
delayed-block?]{
Returns a delayed flow element that may expand to a table of contents
for the enclosing section, depending on the output type. For
multi-page HTML output, the flow element is a table of contents; for
Latex output, the flow element is empty.
The meaning of the @scheme[style] argument depends on the output type,
but @scheme['immediate-only] normally creates a table of contents that
contains only immediate sub-sections of the enclosing section. See
also the @scheme['quiet] style of @scheme[part] (i.e., in a
@scheme[part] structure, not supplied as the @scheme[style] argument
to @scheme[local-table-of-contents]), which normally suppresses
sub-part entries in a table of contents.}

View File

@ -1,265 +1,27 @@
#lang scribble/doc
@(require scribble/manual
"utils.ss"
(for-syntax scheme/base)
(for-label setup/main-collects))
#lang scribble/manual
@(require "utils.ss"
(for-label (only-in scribble/basic span-class)))
@(define-syntax def-section-like
(syntax-rules ()
[(_ id result/c x ...)
(defproc (id [#:tag tag (or/c false/c string?) #f]
[#:tag-prefix tag-prefix (or/c false/c string? module-path?) #f]
[#:style style any/c #f]
[pre-content any/c] (... ...+))
result/c
x ...)]))
@(define (compat)
@italic{For backward compatibility.})
@(define-syntax def-elem-proc
(syntax-rules ()
[(_ id x ...)
(defproc (id [pre-content any/c] (... ...))
element?
x ...)]))
@(define-syntax def-style-proc
(syntax-rules ()
[(_ id)
@def-elem-proc[id]{Like @scheme[elem], but with style @scheme['id].}]))
@title[#:tag "basic"]{Basic Document Forms}
@defmodule[scribble/basic]{The @schememodname[scribble/basic] library
provides functions and forms that can be used from code written either
in Scheme or with @elem["@"] expressions.}
For example, the @scheme[title] and @scheme[italic] functions might be
called from Scheme as
@schemeblock[
(title #:tag "how-to"
"How to Design " (italic "Great") " Programs")
]
or with an @elem["@"] expression as
@verbatim[#:indent 2]|{
@title[#:tag "how-to"]{How to Design @italic{Great} Programs}
}|
Although the procedures are mostly design to be used from @elem["@"]
mode, they are easier to document in Scheme mode (partly because we
have @schememodname[scribble/manual]).
@; ------------------------------------------------------------------------
@section{Document Structure}
@defproc[(title [#:tag tag (or/c false/c string?) #f]
[#:tag-prefix tag-prefix (or/c false/c string? module-path?) #f]
[#:style style any/c #f]
[#:version vers (or/c string? false/c) #f]
[pre-content any/c] ...+)
title-decl?]{
Generates a @scheme[title-decl] to be picked up by @scheme[decode] or
@scheme[decode-part]. The @tech{decode}d @scheme[pre-content] (i.e.,
parsed with @scheme[decode-content]) supplies the title content. If
@scheme[tag] is @scheme[#f], a tag string is generated automatically
from the content. The tag string is combined with the symbol
@scheme['part] to form the full tag.
A style of @scheme['toc] causes sub-sections to be generated as
separate pages in multi-page HTML output. A style of @scheme['index]
indicates an index section whose body is rendered in two columns for
Latex output.
The @scheme[tag-prefix] argument is propagated to the generated
structure (see @secref["tags"]). If @scheme[tag-prefix] is a module
path, it is converted to a string using
@scheme[module-path-prefix->string].
The @scheme[vers] argument is propagated to the @scheme[title-decl]
structure. Use @scheme[""] as @scheme[vers] to suppress version
rendering in the output.
The section title is automatically indexed by
@scheme[decode-part]. For the index key, leading whitespace and a
leading ``A'', ``An'', or ``The'' (followed by more whitespace) is
removed.}
@def-section-like[section part-start?]{ Like @scheme[title], but
generates a @scheme[part-start] of depth @scheme[0] to be by
@scheme[decode] or @scheme[decode-part].}
@def-section-like[subsection part-start?]{ Like @scheme[section], but
generates a @scheme[part-start] of depth @scheme[1].}
@def-section-like[subsubsection part-start?]{ Like @scheme[section], but
generates a @scheme[part-start] of depth @scheme[2].}
@def-section-like[subsubsub*section paragraph?]{ Similar to
@scheme[section], but merely generates a paragraph that looks like an
unnumbered section heading (for when the nesting gets too deep to
include in a table of contents).}
@defproc[(itemize [itm (or/c whitespace? an-item?)] ...
[#:style style any/c #f]) itemization?]{
Constructs an @scheme[itemization] or (when @scheme[style] is not
@scheme[#f]) @scheme[styled-itemization] given a sequence of items
constructed by @scheme[item]. Whitespace strings among the
@scheme[itm]s are ignored.
}
@defproc[(item [pre-flow any/c] ...) item?]{
Creates an item for use with @scheme[itemize]. The @tech{decode}d
@scheme[pre-flow] (i.e., parsed with @scheme[decode-flow]) is the item
content.}
@defproc[(item? [v any/c]) boolean?]{
Returns @scheme[#t] if @scheme[v] is an item produced by
@scheme[item], @scheme[#f] otherwise.}
@defform[(include-section module-path)]{ Requires @scheme[module-path]
and returns its @scheme[doc] export (without making any imports
visible to the enclosing context). Since this form expands to
@scheme[require], it must be used in a module or top-level context.}
@defproc[(author [auth any/c] ...) block?]{
Generates a @scheme[styled-paragraph] to show the author(s) of a
document, where each author is represented by an
@tech{element}. Normally, this function is used after @scheme[title]
for the beginning of a document. See also @scheme[author+email].}
@defproc[(author+email [author elem] [email string?]) element?]{
Combines an author name with an e-mail address, obscuring the e-mail
address slightly to avoid address-harvesting robots.}
@defproc[(module-path-prefix->string [mod-path module-path?])
string?]{
Converts a module path to a string by resolving it to a path, and
using @scheme[path->main-collects-relative].}
@; ------------------------------------------------------------------------
@section{Text Styles}
@defproc[(elem [pre-content any/c] ...
[#:style style any/c #f])
element?]{
Wraps the @tech{decode}d @scheme[pre-content] as an element with style
@scheme[style].}
@def-elem-proc[aux-elem]{Like @scheme[elem], but creates an
@scheme[aux-element].}
@def-style-proc[italic]
@def-style-proc[bold]
@def-style-proc[tt]
@def-style-proc[subscript]
@def-style-proc[superscript]
@def-elem-proc[smaller]{Like @scheme[elem], but with style
@scheme["smaller"]. When uses of @scheme[smaller] are nested, text
gets progressively smaller.}
@defproc[(hspace [n exact-nonnegative-integer?]) element?]{
Produces an element containing @scheme[n] spaces and style
@scheme['hspace].}
@title[#:tag "basic"]{Compatibility Basic Functions}
@defmodule[scribble/basic]{The @schememodname[scribble/basic]
compatibility library mostly just re-exports
@schememodname[scribble/base].}
@defproc[(span-class [style-name string?] [pre-content any/c] ...)
element?]{
Wraps the @tech{decode}d @scheme[pre-content] as an element with style
@scheme[style-name].}
@; ------------------------------------------------------------------------
@section{Indexing}
@defproc[(index [words (or/c string? (listof string?))]
[pre-content any/c] ...)
index-element?]{
Creates an index element given a plain-text string---or list of
strings for a hierarchy, such as @scheme['("strings" "plain")] for a
``plain'' entry below a more general ``strings'' entry. As index keys,
the strings are ``cleaned'' using @scheme[clean-up-index-strings]. The
strings (without clean-up) also serve as the text to render in the
index. The @tech{decode}d @scheme[pre-content] is the text to appear
inline as the index target.
Use @scheme[index] when an index entry should point to a specific word
or phrase within the typeset document (i.e., the
@scheme[pre-content]). Use @scheme[section-index], instead, to create
an index entry that leads to a section, instead of a specific word or
phrase within the section.}
@compat[] Wraps the @tech{decode}d
@scheme[pre-content] as an element with style @scheme[style-name].}
@defproc[(index* [words (listof string?)]
[word-contents (listof list?)]
[pre-content any/c] ...)
index-element?]{
Like @scheme[index], except that @scheme[words] must be a list, and
the list of contents render in the index (in parallel to
@scheme[words]) is supplied as @scheme[word-contents].
}
@defproc[(as-index [pre-content any/c] ...)
index-element?]{
@defproc[(itemize [itm (or/c whitespace? an-item?)] ...
[#:style style (or/c style? string? symbol? #f) #f])
itemization?]{
Like @scheme[index], but the word to index is determined by applying
@scheme[content->string] on the @tech{decode}d @scheme[pre-content].}
@defproc[(section-index [word string?] ...)
part-index-decl?]{
Creates a @scheme[part-index-decl] to be associated with the enclosing
section by @scheme[decode]. The @scheme[word]s serve as both the keys
and as the rendered forms of the keys within the index.}
@defproc[(index-section [#:tag tag (or/c false/c string?) "doc-index"])
part?]{
Produces a part that shows the index the enclosing document. The
optional @scheme[tag] argument is used as the index section's tag.}
@; ------------------------------------------------------------------------
@section{Tables of Contents}
@defproc[(table-of-contents) delayed-block?]{
Returns a delayed flow element that expands to a table of contents for
the enclosing section. For LaTeX output, however, the table of
contents currently spans the entire enclosing document.}
@defproc[(local-table-of-contents [#:style style any/c #f])
delayed-block?]{
Returns a delayed flow element that may expand to a table of contents
for the enclosing section, depending on the output type. For
multi-page HTML output, the flow element is a table of contents; for
Latex output, the flow element is empty.
The meaning of the @scheme[style] argument depends on the output type,
but @scheme['immediate-only] normally creates a table of contents that
contains only immediate sub-sections of the enclosing section. See
also the @scheme['quiet] style of @scheme[part], which normally
suppresses sub-part entries in the table of contents.}
@compat[] Like @scheme[itemlist], but whitespace strings among the
@scheme[itm]s are ignored.}

View File

@ -0,0 +1,6 @@
#lang scribble/manual
@title{Compatibility Libraries}
@include-section["struct.scrbl"]
@include-section["basic.scrbl"]

View File

@ -1,12 +1,12 @@
#lang scribble/doc
@(require scribble/manual
scribble/struct
scribble/core
scribble/decode
scribble/html-variants
scribble/latex-variants
"utils.ss"
(for-label scheme/base))
@(define (nested . str)
(make-blockquote #f (flow-paragraphs (decode-flow str))))
@(define (fake-title . str) (apply bold str))
@title[#:tag "config"]{Extending and Configuring Scribble Output}
@ -18,66 +18,87 @@ extend or configure Scribble fall into two groups:
@itemize[
@item{You may need to drop into the back-end ``language'' of CSS or
Tex to create a specific output effect. For this kind of
extension, you will mostly likely attach a @scheme[`(css
,_file)] or @scheme[`(tex ,_file)] style to a @scheme[section]
and then use a string defined in the @scheme[_file] as an
@scheme[element] or @tech{block} style. This kind of extension
is described in @secref["extra-style"].}
Latex to create a specific output effect. For this kind of
extension, you will mostly likely attach a
@scheme[css-addition] or @scheme[tex-addition] @tech{variant}
to style, where the addition implements the style name. This
kind of extension is described in @secref["extra-style"].}
@item{You may need to produce a document whose page layout is
different from the PLT Scheme documentation style. For that
kind of configuration, you will most likely run the
@exec{scribble} command-line tool and supply flags like
@DFlag{prefix} or @DPFlag{style}. This kind of configuration
is described in @secref["config-style"].}
kind of configuration, you can run the @exec{scribble} command-line
tool and supply flags like @DFlag{prefix} or @DPFlag{style}, or
you can associate a @scheme[html-defaults] or
@scheme[latex-defaults] @tech{variant} to the main document's
style. This kind of configuration is described in
@secref["config-style"].}
]
@; ------------------------------------------------------------
@section[#:tag "extra-style"
#:style `((css "inbox.css") (tex "inbox.tex"))]{Adding a Style}
#:style (make-style #f (list (make-css-addition "inbox.css")
(make-tex-addition "inbox.tex")))
]{Implementing Styles}
When a string is uses as a style in an @scheme[element],
@scheme[styled-paragraph], @scheme[table],
@scheme[styled-itemization], @scheme[blockquote], or @scheme[compound-paragraph], it corresponds to
a CSS class for HTML output or a Tex macro/environment for Latex
output. In Latex output, the string is used as a command name for a
@scheme[styled-paragraph] and an environment name for a
@scheme[table], @scheme[itemization], @scheme[blockquote], or @scheme[compound-paragraph], except
that a @scheme[blockquote] or @scheme[compound-paragraph] style name that starts with @litchar{\} is
used (sans @litchar{\}) as a command instead of an environment.
In addition, for an itemization, the style string is
suffixed with @scheme["Item"] and used as a CSS class or Tex macro
name to use for the itemization's items (in place of @tt{item} in the
case of Latex).
Scribble includes a number of predefined styles that are used by the
exports of @scheme[scribble/manual], but they are not generally
intended for direct use. For now, use them or redefine them at your
own risk.
When a string is uses as a style in an @scheme[element],
a @scheme[multiarg-element], @scheme[paragraph], @scheme[table],
@scheme[itemization], @scheme[nested-flow], or
@scheme[compound-paragraph], it corresponds to a CSS class for HTML
output or a Latex macro/environment for Latex output. In Latex output,
the string is used as a command name for a @scheme[paragraph]
and an environment name for a @scheme[table], @scheme[itemization],
@scheme[nested-flow], or @scheme[compound-paragraph]; the if style has
a @scheme['commad] @tech{variant} for a @scheme[nested-flow] or
@scheme[compound-paragraph], then the style name is used as a command
instead of an environment. In addition, for an itemization, the style
string is suffixed with @scheme["Item"] and used as a CSS class or Latex
macro name to use for the itemization's items (in place of @tt{item}
in the case of Latex).
To add a mapping from your own style name to a CSS configuration, add
a @scheme[`(css ,_file)] style (in a list of styles) to an enclosing
@scheme[part]. To map a style name to a Tex macro (or Latex
environment), add a @scheme[`(tex ,_file)] style to an enclosing part.
a @scheme[css-addition] structure instance to a style's @tech{variant}
list. To map a style name to a Latex macro or environment, add a
scheme[tex-addition] structure instance. A @scheme[css-addition] or
@scheme[tex-addition] is normally associated with the style whose name
is implemented by the adition, but it can also be added to the style
for an enclosing part.
Scribble includes a number of predefined styles that are used by the
exports of @scheme[scribble/base]. You can use them or redefine
them. The styles are specified by @filepath{scribble.css} and
@filepath{scribble.tex} in the @filepath{scribble} collection.
The styles used by @schememodname[scribble/manual] are implemented by
@filepath{scheme.css} and @filepath{scheme.tex} in the
@filepath{scribble} collection. Other libraries, such as
@schememodname[scriblib/autobib], similarly implement styles through files
that are associated by @scheme[css-addition] and @scheme[tex-addition]
@tech{variants}.
To avoid collisions with future additions to Scribble, start your
style name with an uppercase letter that is not @litchar{S}. An
uppercase letter helps to avoid collisions with macros defined by
Latex packages, and future styles needed by @scheme[scribble/manual]
will start with @litchar{S}.
Latex packages, and future styles needed by @schememodname[scribble/base] and
@schememodname[scribble/manual] will start with @litchar{S}.
For example, a Scribble document
@verbatim[#:indent 2]|{
#lang scribble/doc
@(require manual)
#lang scribble/manual
@(require scribble/core
scribble/html-variants
scribble/latex-variants)
@title[#:style `((css "inbox.css") (tex "inbox.tex"))]{Quantum Pet}
(define inbox-style
(make-style "InBox"
(list (make-css-addition "inbox.css")
(make-tex-addition "inbox.tex"))))
Do not open: @elem[#:style "InBox"]{Cat}
@title{Quantum Pet}
Do not open: @elem[#:style inbox-style]{Cat}
}|
combined with an @filepath{inbox.css} that contains
@ -97,7 +118,7 @@ and an @filepath{inbox.tex} that contains
generates
@nested{
@nested[#:style 'inset]{
@fake-title{Quantum Pet}
Do not open: @elem[#:style "InBox"]{Cat}
@ -107,38 +128,87 @@ generates
@section[#:tag "config-style"]{Configuring Output}
Scribble's output is configured in two layers:
The implementation of styles used by libraries depends to some degree
on separately configurable parameters, and configuration is also
possible by replacing style implementations. Latex output is more
configurable in the former way, since a document class determines a
set of page-layout and font properties that are used by other
commands. The style-replacement kind of configuration corresponds to
re-defining Latex macros or overriding CSS class attributes. When
@exec{setup-plt} builds PDF documentation, it uses both kinds of
configuration to produce a standard layout for PLT Scheme manuals;
that is, it selects a particular page layout, and it replaces some
@schememodname[scheme/base] styles.
Two kinds of files implement the two kinds of configuration:
@itemize[
@item{A prefix determines the @tt{DOCTYPE} line for HTML output or
the @tt{documentclass} configuration (and perhaps some addition
package uses or other configuration) for Latex output. The
default prefix is @filepath{scribble-prefix.html} or
@filepath{scribble-prefix.tex} in the @filepath{scribble}
@item{A @deftech{prefix file} determines the @tt{DOCTYPE} line for
HTML output or the @tt{documentclass} configuration (and
perhaps some addition package uses or other configurations) for
Latex output.
The default prefix files are @filepath{scribble-prefix.html}
and @filepath{scribble-prefix.tex} in the @filepath{scribble}
collection.}
@item{Style definitions for all of the ``built-in'' styles used by
@scheme[scribble/manual] (as described in
@secref["extra-style"]). The default style definitions are
@filepath{scribble.css} or @filepath{scribble.tex} in the
@filepath{scribble} collection.}
@item{A @deftech{style file} refines the implementation of styles
nused in the document---typically just the ``built-in'' styles
used by @schememodname[scribble/base].
The default style files, @filepath{scribble-style.css} and
@filepath{scribble-style.tex} in the @filepath{scribble}
collection, change no style implementations.}
]
When using the @exec{scribble} command-line utility:
For a given configuration of output, typically a particular prefix
file works with a particular style file. Some prefix or style files
may be more reusable. For now, reading the default files is the best
way to understand how they interact. A prefix and/or style file may
also require extra accomanying files; for example, a prefix file for
Latex mode may require a corresponding Latex class file. The default
prefix and style files require no extra files.
When rendering a document through the @exec{scribble} command-line
tool, use flags to select a prefix file, style file, and additional
accompanying files:
@itemize[
@item{Replace the prefix using the @as-index{@DFlag{prefix}} flag.}
@item{Select the prefix file using the @as-index{@DFlag{prefix}}
flag. (Selecting the prefix file also cancels the default list
of accompanying files, if any.)}
@item{Replace the style definitions using the
@as-index{@DFlag{style}} flag.}
@item{Replace the style file using the @as-index{@DFlag{style}}
flag. Add additional style definitions and re-definitions using
the @as-index{@DPFlag{style}} flag.}
@item{Add style definitions (that can override earlier ones)
using the @as-index{@DPFlag{style}} flag.}
@item{Add additional accompanying files with @as-index{@DFlag{extra}}.}
]
For now, reading the default files is the best way to understand how
they interact.
When using the @exec{scribble} command-line utility, a document can
declare its default style, prefix, and extra files through a
@scheme[html-defaults] and/or @scheme[latex-defaults] style
@tech{variant}. In particular, when using the @exec{scribble}
command-line tool to generate Latex or PDF a document whose main part
is implemented with @scheme[#, @hash-lang[] #,
@schememodname[scribble/manual]], the result has the standard PLT
Scheme manual configuration, because @schememodname[scribble/manual]
associates a @scheme[latex-defaults] @tech{variant} with the exported
document. The @schememodname[scribble/sigplan] language similarly
associates a default configuration with an exported document. As
libraries imported with @scheme[require], however,
@schememodname[scribble/manual] and @schememodname[scribble/sigplan]
simply implement new styles in a composable way.
Whether or not a document has a default prefix- and style-file
configuration through a style @tech{variant}, the defaults can be
overridden using @exec{scribble} command-line flags. Furthermore,
languages like @schememodname[scribble/manual] and
@schememodname[scribble/sigplan] add a @scheme[html-defaults] and/or
@scheme[latex-defaults] @tech{variant} to a main-document part only if
it does not already have such a variant added through the
@scheme[#:style] argument of @scheme[title].

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@ At the @tech{flow} level, decoding recognizes a blank line as a
@tech{paragraph} separator. Blocks and paragraphs without blank lines
in between are collected into a @tech{compound paragraph}.
At the @tech{paragraph}-content level, decoding makes just a few
At the @tech{content} level, decoding makes just a few
special text conversions:
@itemize[
@ -44,6 +44,29 @@ that in
the @litchar{``apple''} argument is decoded to use fancy quotes, and
then it is bolded.
@defproc[(pre-flow? [v any/c]) boolean?]{
Returns @scheme[#t] if @scheme[v] is a @deftech{pre-flow} value: a
string or other non-list @scheme[content], a @scheme[block?], or a
@scheme[splice] containing a list of @tech{pre-flow} values; otherwise
returns @scheme[#f].
Pre-flow is decoded into a @tech{flow} (i.e., a list of @tech{blocks})
by functions like @scheme[decode] and @scheme[decode-flow].}
@defproc[(pre-content? [v any/c]) boolean?]{
Returns @scheme[#t] if @scheme[v] is a @deftech{pre-content} value: a
string or other non-list @scheme[content], or a @scheme[splice]
containing a list of @tech{pre-content} values; otherwise returns
@scheme[#f].
Pre-content is decoded into @tech{content} by functions like
@scheme[decode-content] and @scheme[decode-paragraph].}
@defproc[(decode [lst list?]) part?]{
Decodes a document, producing a part. In @scheme[lst], instances of
@ -74,7 +97,7 @@ parsing.
}
@defproc[(decode-flow [lst list?]) flow?]{
@defproc[(decode-flow [lst (listof pre-flow?)]) flow?]{
Decodes a flow. A sequence of two or more newlines separated only by
whitespace counts is parsed as a paragraph separator. In @scheme[lst],
@ -84,7 +107,7 @@ the enclosing flow.
}
@defproc[(decode-compound-paragraph [lst list?]) block?]{
@defproc[(decode-compound-paragraph [lst (listof pre-flow?)]) block?]{
Decodes a compound paragraph. If the compound paragraph contains a
single block, the block is returned without a
@ -92,26 +115,26 @@ single block, the block is returned without a
}
@defproc[(decode-paragraph [lst list?]) paragraph?]{
@defproc[(decode-paragraph [lst (listof pre-content?)]) paragraph?]{
Decodes a paragraph.
}
@defproc[(decode-content [lst list?]) list?]{
@defproc[(decode-content [lst (listof pre-content?)]) list?]{
Decodes a sequence of elements.
Decodes @tech{content}.
}
@defproc[(decode-elements [lst list?]) list?]{
@defproc[(decode-elements [lst (listof pre-content?)]) list?]{
An alias for @scheme[decode-content].
}
@defproc[(decode-string [s string?]) list?]{
@defproc[(decode-string [s string?]) (listof content?)]{
Decodes a single string to produce a list of elements.
Decodes a single string to produce @tech{content}.
}
@ -127,7 +150,7 @@ otherwise.
[tags (listof string?)]
[version (or/c string? false/c)]
[style any/c]
[content list?])]{
[content content?])]{
See @scheme[decode] and @scheme[decode-part]. The @scheme[tag-prefix]
and @scheme[style] fields are propagated to the resulting
@ -139,7 +162,7 @@ and @scheme[style] fields are propagated to the resulting
[tag-prefix (or/c false/c string?)]
[tags (listof string?)]
[style any/c]
[title list?])]{
[title content?])]{
Like @scheme[title-decl], but for a sub-part. See @scheme[decode] and
@scheme[decode-part].

View File

@ -1,6 +1,5 @@
#lang scribble/doc
@(require scribble/manual
"utils.ss")
#lang scribble/manual
@(require "utils.ss")
@title[#:tag "doclang"]{Document Language}

View File

@ -0,0 +1,7 @@
#lang scribble/manual
@(require "utils.ss")
@title[#:tag "generic-prose"]{General Documents}
@include-section["base.scrbl"]
@include-section["other.scrbl"]

View File

@ -0,0 +1,13 @@
#lang scribble/manual
@title[#:tag "getting-started" #:style 'toc]{Getting Started}
No matter what you want to do with Scribble, it's best to start with
an introduction on producing HTML and PDF documents in
@secref["how-to-paper"]. The end of the chapter, @secref["roadmap"],
offers advice on where to go afterward depending on your goals.
@local-table-of-contents[]
@include-section["how-to-paper.scrbl"]
@include-section["how-to.scrbl"]

View File

@ -0,0 +1,622 @@
#lang scribble/doc
@(require scribble/manual
scribble/bnf
"utils.ss")
@(define (sample . text) (nested #:style 'inset (apply verbatim text)))
@(define (result . text) (apply nested #:style 'inset text))
@title[#:tag "how-to-paper"]{How to Scribble Documents}
This chapter demonstrates the basics of generating stand-alone HTML
and PDF (through Latex) documents with Scribble.
@section[#:tag "first-example"]{A First Example}
Create a file @filepath{mouse.scrbl} with this content:
@sample|{
#lang scribble/base
@title{On the Cookie-Eating Habits of Mice}
If you give a mouse a cookie, he's going to ask for a
glass of milk.
}|
The first line's @scheme[#, @hash-lang[] #,
@schememodname[scribble/base]] indicates that the file implements a
Scribble document. The document starts in ``text mode,'' and the
@litchar["@"] character escapes to operators like @scheme[title],
where the curly braces return to text mode for the arguments to the
operator. The rest is document content.
Now run the @exec{scribble} command-line program, specifying a mode
for the kind of document that you want as output:
@itemize[
@item{Run
@commandline{scribble --pdf mouse.scrbl}
to generate PDF as @filepath{mouse.pdf}. This will
work only if you have @exec{pdflatex} installed.
If you'd like to see the intermediate Latex, try
@commandline{scribble --latex mouse.scrbl}
to generate @filepath{mouse.tex}.}
@item{Run
@commandline{scribble --html mouse.scrbl}
to generate HTML as @filepath{mouse.html}. You may
notice that the apostrophe in ``he's'' turned into a
curly apostrophe.}
@item{Run
@commandline{scribble --htmls mouse.scrbl}
to generate HTML as @filepath{mouse/index.html}.
Sub-sections (which we add next) will appear as separate
HTML files in the @filepath{mouse} directory.}
]
@section{Multiple Sections}
Add more text to @filepath{mouse.scrbl} so that it looks like this:
@sample|{
#lang scribble/base
@title{On the Cookie-Eating Habits of Mice}
If you give a mouse a cookie, he's going to ask for a
glass of milk.
@section{The Consequences of Milk}
That ``squeak'' was the mouse asking for milk. Let's
suppose that you give him some in a big glass.
He's a small mouse. The glass is too big---way too
big. So, he'll probably ask you for a straw. You might as
well give it to him.
@section{Not the Last Straw}
For now, to handle the milk moustache, it's enough to give
him a napkin. But it doesn't end there... oh, no.
}|
Now, after the first paragraph of the paper, we have two
sub-sections, each created by calling @scheme[section] to
generate a sub-section declaration. The first sub-section has
two paragraphs. The second section, as initiated by the result
of the second @scheme[section] call, has a single paragraph.
Run the @exec{scribble} command(s) from @secref["first-example"]
again. You may notice the curly double-quotes in the output; in PDF
output, the @litchar{---} turned into an em-dash. For HTML, it turned
into a en-dash with surrounding spaces, which is a typical convention
for em-dashes in HTML.
@;----------------------------------------
@section{Splitting the Document Source}
As a document grows larger, it's better to split sections into
separate source files. The @scheme[include-section] operation
incorporates a document defined by a @filepath{.scrbl} file into a
larger document.
To split the example document into multiple files, change
@filepath{mouse.scrbl} to just
@sample|{
#lang scribble/base
@title{On the Cookie-Eating Habits of Mice}
If you give a mouse a cookie, he's going to ask for a
glass of milk.
@include-section["milk.scrbl"]
@include-section["straw.scrbl"]
}|
Create @filepath{milk.scrbl} and @filepath{straw.scrbl} in the same
directory as @filepath{mouse.scrbl}. In @filepath{milk.scrbl}, put
@sample|{
#lang scribble/base
@title{The Consequences of Milk}
That ``squeak'' was the mouse asking for milk...
}|
and in @filepath{straw.scbl}, put
@sample|{
#lang scribble/base
@title{Not the Last Straw}
For now, to handle the milk moustache, ...
}|
Notice that the new files both start with @hash-lang[], like the
original document, and the @scheme[section]s from the original
document become @scheme[title]s in the new documents. Both
@filepath{milk.scrbl} and @filepath{straw.scrbl} are documents in
their own right with their own titles, and they can be individually
rendered using @exec{scribble}. Running @exec{scribble} on
@filepath{mouse.scrbl}, meanwhile, incorporates the smaller documents
into one document that is the same as before.
@; ----------------------------------------
@section{Document Styles}
Scribble currently supports only one from of HTML output. You can
replace the @filepath{scribble.css} file for the generated pages, and
that's about it. (We expect to add more styles in the future.)
For Latex-based PDF output, Scribble includes support for
multiple page-layout configurations. The @filepath{mouse.scrbl}
example so far uses the default Latex style. If you plan on submitting
the paper to a workshop on programming languages, then---well, you
probably need a different topic. But you can start making the current
content look right by changing the first line to
@sample|{
#lang scribble/sigplan
}|
If you're instead working toward PLT Scheme library documentation,
try changing the first line to
@sample|{
#lang scribble/manual
}|
which produces output with a separate title page, initial content on
that page (intended as a brief orientation to the document), and
top-level sections turned into chapters that each start on a new page.
If you have split the document into multiple files, the first line of
the main document file determines the output format.
Using @schememodname[scribble/sigplan] or
@schememodname[scribble/manual] does not change the rendered HTML for
a document---aside from @schememodname[scribble/manual] adding a
version number---but it changes the set of bindings available in the
document body. For example, with @schememodname[scribble/sigplan], the
introductory text can be marked as an abstract:
@sample|{
#lang scribble/sigplan
@title{On the Cookie-Eating Habits of Mice}
@abstract{If you give a mouse a cookie, he's going to
ask for a glass of milk.}
@section{The Consequences of Milk}
....}|
When rendered as HTML, the abstract shows up as an inset paragraph. If
you try to use @scheme[abstract] with the
@schememodname[scribble/base] or @schememodname[scribble/manual]
language, then you get an error, because @scheme[abstract] is not
defined.
When a document is implemented across multiple files, changing the
language of the man document can set the style for all of the parts,
but it does not introduce bindings into the other part files. For
example, if you change the language of @filepath{mouse.scrbl} to
@schememodname[scribble/sigplan], then @scheme[abstract] becomes
available in @filepath{mouse.scrbl} but not in @filepath{milk.scrbl}
or @filepath{straw.scrbl}. In other words, operator names are
lexically scoped.
@; ----------------------------------------
@section{More Functions}
The @schememodname[scribble/sigplan] and
@schememodname[scribble/manual] languages are supersets of the
@schememodname[scribble/base] language, which provides a collection of
basic operations. Many of the operations are style variations that you
can apply to text:
@sample|{
He's a @smaller{small mouse}. The glass is too
@larger{big}---@bold{way @larger{too @larger{big}}}. So, he'll
@italic{probably} ask you for a straw.
}|
which renders as
@result{
He's a @smaller{small mouse}. The glass is too
@larger{big}---@bold{way @larger{too @larger{big}}}. So, he'll
@italic{probably} ask you for a straw.
}
As you would expect, calls to functions like @scheme[smaller],
@scheme[larger], and @scheme[bold] can be nested in other calls. They
can also be nested within calls to @scheme[title] or @scheme[section]:
@sample|{
@section{@italic{Not} the Last Straw}
}|
The @scheme[centered] operation centers a flow of text:
@sample|{
If a mouse eats all your cookies, put up a sign that says
@centerline{
@bold{Cookies Wanted}
@italic{Chocolate chip preferred!}
}
and see if anyone brings you more.
}|
which renders as
@result{
If a mouse eats all your cookies, put up a sign that says
@centerline{
@bold{Cookies Wanted}
@italic{Chocolate chip preferred!}
}
and see if anyone brings you more.
}
The @scheme[margin-note] operation is used in a similar way, but the
rendered text is moved to the margins.
@margin-note{If you use @scheme[margin-note], then the content shows
up over here.}
The @scheme[itemlist] operation creates a sequence of bulleted text,
where the @scheme[item] operation groups text to appear in a single
bullet. The @scheme[itemlist] operation is different from the others
that we have seen before, because it only accepts values produced by
@scheme[item] instead of arbitrary text. This difference is reflected
in the use of @litchar{[}...@litchar{]} for the arguments to
@scheme[itemlist] instead of @litchar["{"]...@litchar["}"]:
@sample|{
@centered{@bold{Notice to Mice}}
@itemlist[@item{We have cookies for you.}
@item{If you want to eat a cookie,
you must bring your own straw.}]
}|
which renders as
@result{
@centered{@bold{Notice to Mice}}
@itemlist[@item{We have cookies for you.}
@item{If you want to eat a cookie,
you must bring your own straw.}]
}
@; ----------------------------------------
@section{Text Mode vs. Scheme Mode for Arguments}
When @litchar{[}...@litchar{]} sounds the arguments of an
operation, the argument expressions are in Scheme mode rather than
text mode. Even in Scheme mode, @litchar["@"] can be used to apply
operations; once the @"@" syntax is enabled through a
language like @schememodname[scribble/base] (as opposed to
@schememodname[scheme]), it behaves the same in both Scheme mode and
text mode.
One advantage of using Scheme mode for the arguments to
@scheme[itemlist] is that we can pass a keyword-tagged optional
argument to @scheme[itemlist]. In particular, if you want a list with
numbers instead of bullets, supply the @scheme['ordered] style to
@scheme[itemlist] using the @scheme[#:style] keyword:
@sample|{
@itemlist[#:style 'ordered
@item{Eat cookie.}
@item{Drink milk.}
@item{Wipe mouth.}
@item{...}]
}|
An operation doesn't care whether it's used with
@litchar{[}...@litchar{]} or @litchar["{"]...@litchar["}"]. Roughly,
@litchar["{"]...@litchar["}"] forms an argument that is a
string. (Only roughly, though. Newlines or uses of @litchar["@"]
within @litchar["{"]...@litchar["}"] complicate the picture, and we'll
get back to that soon.) So,
@sample|{
@italic{Yummy!}
}|
is equivalent to
@sample|{
@italic["Yummy!"]
}|
which is equivalent to the Scheme expression
@schemeblock[
(italic "Yummy!")
]
These equivalences explain why Scribble functions are documented in
Scheme notation. If you're reading this in HTML format, you can click
@scheme[italic] above to access its documentation. The documentation
won't completely make sense, yet, because it will be the end of this
chapter.
What if you want to provide arguments in text mode, but you also want
to supply other optional arguments? You can use both
@litchar{[}...@litchar{]} and @litchar["{"]...@litchar["}"] for an
operation, as long as the @litchar{[}...@litchar{]} is first, and as
long as no character separate the closing @litchar{]} from the
opening @litchar["{"]. For example, calling @scheme[italic] is the
same as using @scheme[elem] with the @scheme['italic] style:
@sample|{
@elem[#:style 'italic]{Yummy!}
}|
You can also @emph{omit} both @litchar{[}...@litchar{]} and
@litchar["{"]...@litchar["}"]. In that case, the Scheme expression
after @litchar["@"] is used directly instead of applied as an
operation. For example,
@sample|{
1 plus 2 is @(number->string (+ 1 2)).
}|
renders as
@result{
1 plus 2 is @(number->string (+ 1 2)).
}
The call to @scheme[number->string] is needed because a naked number
is not valid as document content.
@; ----------------------------------------
@section[#:tag "how-to:reader"]{The @"@" Syntax}
The @"@" notation provided by Scribble is just another way of
writing Scheme expressions. Scribble documents could be constructed
using normal Scheme notation, without using @"@" at all, but
that would be inconvenient for most purposes. The @"@"
notation makes dealing with textual content much easier.
Whether in text mode or Scheme mode, @litchar["@"] in a document
provides an escape to Scheme mode. The basic syntax of @litchar["@"] is
@schemeblock[
@#,BNF-seq[@litchar["@"]
@nonterm{cmd}
@litchar{[} @kleenestar{@nonterm{datum}} @litchar{]}
@litchar["{"] @nonterm{text-body} @litchar["}"]]
]
where all three parts after @litchar["@"] are optional, but at least
one must be present. No spaces are allowed between
@itemize[
@item{@litchar["@"] and @nonterm{cmd}, @litchar{[}, or @litchar["{"]}
@item{@nonterm{cmd} and @litchar{[} or @litchar["{"]; or}
@item{@litchar{]} and @litchar["{"].}
]
A @nonterm{cmd} or @nonterm{datum} is normal Scheme notation, while a
@nonterm{text-body} is itself in text mode. A @nonterm{cmd} obviously
must not start with @litchar{[} or @litchar["{"], even though Scheme
forms could otherwise start with those characters.
The expansion of just @litchar["@"]@nonterm{cmd} into Scheme code is
@schemeblock[
@#,nonterm{cmd}
]
When either @litchar{[} @litchar{]} or @litchar["{"] @litchar["}"]
are used, the expansion is
@schemeblock[
(@#,nonterm{cmd} @#,kleenestar{@nonterm{datum}} @#,kleenestar{@nonterm{parsed-body}})
]
where @kleenestar{@nonterm{parsed-body}} is the parse result of the
@nonterm{text-body}. The @kleenestar{@nonterm{parsed-body}} part often
turns out to be a sequence of Scheme strings.
In practice, the @nonterm{cmd} is normally a Scheme identifier that is
bound to a procedure or syntactic form. If the procedure or form
expects further text to typeset, then @litchar["{"]...@litchar["}"]
supplies the text. If the form expects other data, typically
@litchar{[}...@litchar{]} is used to surround Scheme arguments,
instead. Even if an operation's argument is a string, if the string is
not used as content text (but instead used as, say, a hyperlink
label), then the string is typically provided through
@litchar{[}...@litchar{]} instead of @litchar["{"]...@litchar["}"].
Sometimes, both @litchar{[}...@litchar{]} and
@litchar["{"]...@litchar["}"] are used, where the former surround
Scheme arguments that precede text to typeset. Finally, if a form is a
purely Scheme-level form with not typeset result, such as a
@scheme[require] to import more operations, then typically just
@litchar["@"] is used.
For example the text-mode stream
@sample|{
@(require scriblib/figure)
@section[#:tag "poetry"]{Of Mice and Cookies}
See @secref["milk"].
@section[#:tag "milk"]{@italic{Important} Things About Milk}
@figure["straw" @elem{A straw}]{@image["straw.png"]}
}|
is equivalent to the Scheme-mode sequence
@schemeblock[
(require scriblib/figure) "\n"
"\n"
(section #:tag "poetry" "Of Mice and Cookies") "\n"
"See " (secref "milk") "." "\n"
"\n"
(section #:tag "milk" (italic "Important") " Things About Milk") "\n"
(figure "straw" (elem "A straw") (image "straw.png")) "\n"
]
Besides showing how different argument conventions are used for
different operations, the above example illustrates how whitespace is
preserved in the Scheme form of a text-mode stream---including
newlines preserved as their own strings. Notice how the second
@scheme[section] gets two arguments for its content, since the
argument content for @scheme[section] in the source stream includes
both the use of an operator and additional text. When an operation
like @scheme[section] or @scheme[italic] accepts content to typeset,
it normally accepts an arbitrary number of arguments that together
form the content.
For more information on the syntax of @litchar["@"], see
@secref["reader"]. The full syntax includes a few more details, such
as brackets like @litchar["|{"]...@litchar["}|"] for text-mode
arguments while disabling @litchar["@"] between the brackets.
@; ----------------------------------------
@section{Decoding Sequences}
In a document that starts @scheme[#, @hash-lang[] #,
@schememodname[scribble/base]], the top level is a text-mode stream,
just like the @nonterm{text-body} in a @litchar["@"] form. As
illustrated in the previous section, such a top-level sequence
corresponds to a mixture of Scheme-mode strings and operation
applications. There's an implicit operation, @scheme[decode], that
wraps the whole document to consume this mixture of strings and other
values and turn them into a document description.
The @scheme[decode] operation implements @defterm{flow decoding},
which takes a document stream and breaks it up into sections and
paragraphs. Blank lines delimit paragraphs, and the results of
operations like @scheme[title] and @scheme[section] generate ``here's
the title'' or ``a new section starts here'' declarations that are
recognized by @scheme[decode].
A different but related @defterm{content decoding} takes place within
a paragraph or section title. Content decoding is responsible for
converting @litchar{---} to an em-dash or for converting @litchar{"}
and @litchar{'} to suitable curly quotes.
The decoding process for document's stream is ultimately determined by
the @hash-lang[] line that starts the document. The @schememodname[scribble/base],
@schememodname[scribble/manual], and @schememodname[scribble/sigplan]
languages all use the same @scheme[decode] operation. The
@schememodname[scribble/text] language, however, acts more like a
plain-text preprocessor and it does not perform any such decoding
rules. (For more on @schememodname[scribble/text], see
@secref["preprocessor"].)
@margin-note{More precisely, languages like
@schememodname[scribble/base] apply @scheme[decode] only after
lifting out all definitions and imports from the document
stream.}
When the flow decoder is used, after it breaks the input stream into
paragraphs, it applies content decoding to strings within the
paragraph. When content is wrapped with an operation, however, content
decoding does not apply automatically. An operation is responsible for
calling a content or flow decoder as it sees fit. Most operations call
the decoder; for example, @scheme[italic], @scheme[bold],
@scheme[smaller], etc., all decode their arguments. Similarly,
@scheme[title] and @scheme[section] decode the given content for the
title or section name. The @scheme[literal] and @scheme[verbatim]
operators, however, do not decode the given strings. For example,
@sample|{
@verbatim{---}
}|
renders as
@result{
@verbatim{---}
}
Don't confuse decoding with the expansion of @"@"
notation. The source form
@sample|{
@verbatim{@(number->string (+ 1 2))}
}|
renders as
@result{
@verbatim{@(number->string (+ 1 2))}
}
because the source is equivalent to
@sample|{
(verbatim (number->string (+ 1 2)))
}|
where @scheme[(number->string (+ 1 2))] is evaluated to produce the
argument to @scheme[verbatim]. The @litchar["|{"]...@litchar["}|"]
style of brackets is often used with @scheme[verbatim], because
@litchar["|{"]...@litchar["}|"] disables @"@" notation for
arguments. For example,
@sample|{
@verbatim|{@(number->string (+ 1 2))}|
}|
renders as
@result{
@verbatim|{@(number->string (+ 1 2))}|
}
@; ----------------------------------------
@section[#:tag "roadmap"]{The Big Picture and Next Steps}
Although it may not look like it, @filepath{mouse.scrbl} is a Scheme
program. You could run it directly in DrScheme or with MzScheme, the
latter like this:
@commandline{mzscheme mouse.scrbl}
If you do that though, nothing much seems to happen. As a program
module, @filepath{mouse.scrbl} builds a document description and
exports it as @scheme[doc], but exporting a binding is not a visible
operation. The @exec{scribble} tool runs @filepath{mouse.scrbl} to get
the exported description, and then it uses the description to generate
an output document.
Despite a suspicious lack of parentheses compared to most Scheme
programs, and despite the fact that running @filepath{mouse.scrbl} by
itself has no apparent effect, it's important to understand that
@filepath{mouse.scrbl} is a Scheme program. @emph{Data is code.}
Scribble tools vary in the kinds of documents they transform and
generate, but all share the twin principles of @"@" notation
for convenience and data-as-code for expressiveness.
If your immediate goal is to document a PLT Scheme library or write
literate programs, continue with @secref["how-to-doc"]. If you are more
interested in producing documents unrelated to PLT Scheme, move on to
the main documentation at @secref["generic-prose"], and then read
@secref["internals"] when you need more power. If you are interested
in text preprocessing, go instead to @secref["preprocessor"].

View File

@ -3,20 +3,19 @@
scribble/bnf
"utils.ss")
@title{How to Scribble Documentation}
@title[#:tag "how-to-doc"]{How to Scribble PLT Scheme Documentation}
Although the @exec{scribble} command-line utility generates output
from a Scribble document (run @exec{scribble -h} for more
information), documentation of PLT Scheme libraries is normally built
by @exec{setup-plt}. This chapter emphasizes the @exec{setup-plt}
approach, which more automatically supports links across
documents.
from a Scribble document, documentation of PLT Scheme libraries is
normally built by @exec{setup-plt}. This chapter emphasizes the
@exec{setup-plt} approach, which more automatically supports links
across documents.
@margin-note{See @secref["config"] for information on using the
@margin-note{See @secref["how-to-paper"] for information on using the
@exec{scribble} command-line utility.}
@;----------------------------------------
@section[#:tag "getting-started"]{Getting Started}
@section[#:tag "setting-up"]{Setting Up Documentation}
To document a collection or @|PLaneT| package:
@ -30,20 +29,17 @@ To document a collection or @|PLaneT| package:
@item{Start @filepath{manual.scrbl} like this:
@verbatim[#:indent 2]|{
#lang scribble/doc
@(require scribble/manual)
#lang scribble/manual
@title{My Library}
Welcome to my documentation: @scheme[(list 'testing 1 2 3)].
}|
The first line starts the file in ``text'' mode, and
introduces the @litchar["@"] syntax to use Scheme bindings.
The second line introduces bindings like @scheme[title] and
@scheme[scheme] for writing PLT Scheme documentation. The
@scheme[title] call (using @litchar["@"]) produces a title
declaration in the text stream.}
The first line starts the file in ``text'' mode and selects
the PLT Scheme manual output format.
It also introduces bindings like @scheme[title] and
@scheme[scheme] for writing PLT Scheme documentation.}
@item{Add the following entry to your collect or package's
@filepath{info.ss}:
@ -82,105 +78,19 @@ To document a collection or @|PLaneT| package:
]
@; ----------------------------------------
@section[#:tag "how-to:reader"]{Document Syntax}
Whether in ``text'' mode or Scheme mode, @litchar["@"] in a document
provides an escape to Scheme mode. The syntax of @litchar["@"] is
@schemeblock[
@#,BNF-seq[@litchar["@"]
@nonterm{cmd}
@litchar{[} @kleenestar{@nonterm{datum}} @litchar{]}
@litchar["{"] @nonterm{text-body} @litchar["}"]]
]
where all three parts after @litchar["@"] are optional, but at least
one must be present. No spaces are allowed between
@itemize[
@item{@litchar["@"] and @nonterm{cmd}, @litchar{[}, or @litchar["{"]}
@item{@nonterm{cmd} and @litchar{[} or @litchar["{"]; or}
@item{@litchar{]} and @litchar["{"].}
]
A @nonterm{cmd} or @nonterm{datum} is a Scheme datum, while a
@nonterm{text-body} is itself in text mode.
The expansion of @litchar["@"]@nonterm{cmd} into Scheme code is
@schemeblock[
@#,nonterm{cmd}
]
When either @litchar{[} @litchar{]} or @litchar["{"] @litchar["}"]
are used, the expansion is
@schemeblock[
(@#,nonterm{cmd} @#,kleenestar{@nonterm{datum}} @#,kleenestar{@nonterm{parsed-body}})
]
where @kleenestar{@nonterm{parsed-body}} is the parse result of the
@nonterm{text-body}. The @kleenestar{@nonterm{parsed-body}} part often
turns out to be a sequence of Scheme strings.
In practice, the @nonterm{cmd} is normally a Scheme identifier that is
bound to a procedure or syntactic form. If the procedure or form
expects further text to typeset, then @litchar["{"] @litchar["}"]
supplies the text. If the form expects other data, typically
@litchar{[} @litchar{]} is used to surround Scheme arguments,
instead. Sometimes, both @litchar{[} @litchar{]} and @litchar["{"]
@litchar["}"] are used, where the former surround Scheme arguments
that precede text to typeset.
Thus,
@verbatim[#:indent 2]|{
@(require scribble/manual)
@title{My Library}
@scheme[(list 'testing 1 2 3)]
@section[#:tag "here"]{You Are Here}
}|
means
@schemeblock[
(require scribble/manual)
(title "My Library")
(scheme (list 'testing 1 2 3))
(section #:tag "here" "You Are Here")
]
For more information on the syntax of @litchar["@"], see
@secref["reader"].
In a document that starts @hash-lang[] @schememodname[scribble/doc],
the top level is a text-mode sequence, as the @nonterm{text-body} in a
@litchar["@"] form. The parsed sequence is further
decoded to turn it into a hierarchy of sections and paragraphs. For
example, a linear sequence of @scheme[section] declarations with
interleaved text is turned into a list of @scheme[part] instances with
all text assigned to a particular part. See @secref["layers"] for more
information on these layers.
@; ----------------------------------------
@section[#:tag "scheme-hyperlinks"]{Scheme Typesetting and Hyperlinks}
In the document source at the start of this chapter
(@secref["getting-started"]), the Scheme expression
(@secref["setting-up"]), the Scheme expression
@scheme[(#,(schemeidfont "list") 'testing 1 2 3)] is typeset properly,
but the @schemeidfont{list} identifier is not hyperlinked to the usual
definition. To cause @schemeidfont{list} to be hyperlinked, extend the
definition. To cause @schemeidfont{list} to be hyperlinked, add a
@scheme[require] form like this:
@schemeblock[
(require scribble/manual
(for-label #,(schememodname scheme)))
]
@verbatim[#:indent 2]|{
@(require (for-label scheme))
}|
This @scheme[require] with @scheme[for-label] declaration introduces a
document-time binding for each export of the @schememodname[scheme]
@ -197,9 +107,8 @@ document. Such links require no information about where and how a
binding is documented elsewhere:
@verbatim[#:indent 2]|{
#lang scribble/doc
@(require scribble/manual
(for-label scheme))
#lang scribble/manual
@(require (for-label scheme))
@title{My Library}
@ -212,9 +121,8 @@ so it ignores the source formatting of the expression. The
and it preserves the expression's formatting from the document source.
@verbatim[#:indent 2]|{
#lang scribble/doc
@(require scribble/manual
(for-label scheme))
#lang scribble/manual
@(require (for-label scheme))
@title{My Library}
@ -242,9 +150,8 @@ hyperlink with text other than the section title.
The following example illustrates section hyperlinks:
@verbatim[#:indent 2]|{
#lang scribble/doc
@(require scribble/manual
(for-label scheme))
#lang scribble/manual
@(require (for-label scheme))
@title{My Library}
@ -281,9 +188,8 @@ following example links to a section in the PLT Scheme reference
manual:
@verbatim[#:indent 2]|{
#lang scribble/doc
@(require scribble/manual
(for-label scheme))
#lang scribble/manual
@(require (for-label scheme))
@(define ref-src
'(lib "scribblings/reference/reference.scrbl"))
@ -336,9 +242,8 @@ following:
@; [Eli] This is also using `my-lib/helper' which doesn't work with
@; planet libraries
@verbatim[#:indent 2]|{
#lang scribble/doc
@(require scribble/manual
(for-label scheme
#lang scribble/manual
@(require (for-label scheme
"helper.ss"))
@title{My Library}
@ -408,9 +313,8 @@ from the previous section, @filepath{helper.ss} must be imported both
via @scheme[require-for-label] and @scheme[require]:
@verbatim[#:indent 2]|{
#lang scribble/doc
@(require scribble/manual
scribble/eval ; <--- added
#lang scribble/manual
@(require scribble/eval ; <--- added
"helper.ss" ; <--- added
(for-label scheme
"helper.ss"))
@ -432,58 +336,6 @@ via @scheme[require-for-label] and @scheme[require]:
]}
}|
@;----------------------------------------
@section{Splitting the Document Source}
In general, a @filepath{.scrbl} file produces a @techlink{part}. A part
produced by a document's main source (as specified in the
@filepath{info.ss} file) represents the whole document. The
@scheme[include-section] procedure can be used to incorporate a part
as a sub-part of the enclosing part.
In @filepath{manual.scrbl}:
@verbatim[#:indent 2]|{
#lang scribble/doc
@(require scribble/manual)
@title{My Library}
@defmodule[my-lib/helper]{The @schememodname[my-lib/helper]
module---now with extra cows!}
@include-section["cows.scrbl"]
@include-section["aardvarks.scrbl"]
}|
In @filepath{cows.scrbl}:
@verbatim[#:indent 2]|{
#lang scribble/doc
@(require scribble/manual)
@title{Cows}
Wherever they go, it's a quite a show.
}|
In @filepath{aardvarks.scrbl}:
@verbatim[#:indent 2]|{
#lang scribble/doc
@(require scribble/manual
(for-label scheme
"helper.ss"))
@title{Aardvarks}
@defproc[(my-helper [lst list?])
(listof (not/c (one-of/c 'cow)))]{
Replaces each @scheme['cow] in @scheme[lst] with
@scheme['aardvark].}
}|
@;----------------------------------------
@section{Multi-Page Sections}
@ -500,8 +352,7 @@ sub-sections.
Revising @filepath{cows.scrbl} from the previous section:
@verbatim[#:indent 2]|{
#lang scribble/doc
@(require scribble/manual)
#lang scribble/manual
@title[#:style '(toc)]{Cows}

View File

@ -0,0 +1,16 @@
#lang scribble/manual
@(require "utils.ss")
@title[#:tag "internals" #:style 'toc]{Low-Level Scribble}
@local-table-of-contents[]
@include-section["layers.scrbl"]
@include-section["reader.scrbl"]
@include-section["core.scrbl"]
@include-section["renderer.scrbl"]
@include-section["decode.scrbl"]
@include-section["doclang.scrbl"]
@include-section["docreader.scrbl"]
@include-section["xref.scrbl"]
@include-section["config.scrbl"]

View File

@ -16,14 +16,34 @@ and instead use the document-generation structure directly.
A Scribble document normally starts
@schememod[
scribble/manual
]
but it could also start
@schememod[
scribble/base
]
or
@schememod[
scribble/doc
]
Besides making the file a module, this declaration selects the
Scribble reader (instead of the usual Scheme reader), and it starts
the body of the file in ``text'' mode. The reader layer mostly leaves
text alone, but @litchar["@"] forms escape to S-expression mode.
The last one introduces the smallest number of typesetting bindings in
the document body. Using @schememodname[scribble/base] after
@hash-lang[] is the same as using @schememodname[scribble/doc] plus
@scheme[(require scribble/base)], and using
@schememodname[scribble/manual] after @hash-lang[] is the same as using
@schememodname[scribble/doc] plus @scheme[(require scribble/manual)].
Besides making the file a module, each of the @hash-lang[]
declarations selects the Scribble reader (instead of the usual Scheme
reader), and it starts the body of the file in ``text'' mode. The
reader layer mostly leaves text alone, but @litchar["@"] forms escape
to S-expression mode.
A module written as
@ -150,10 +170,10 @@ Working roughly from the bottom up, the Scribble layers are:
syntax of Scheme with @"@"-forms for conveniently embedding a
mixin of text and escapes. See @secref["reader"].}
@item{@schememodname[scribble/struct]: A set of document datatypes
@item{@schememodname[scribble/core]: A set of document datatypes
and utilities that define the basic layout and processing of a
document. For example, the @scheme[part] datatype is defined in
this layer. See @secref["struct"].}
this layer. See @secref["core"].}
@item{@schememodname[scribble/base-render] with
@schememodname[scribble/html-render],
@ -165,7 +185,7 @@ Working roughly from the bottom up, the Scribble layers are:
@item{@schememodname[scribble/decode]: Processes a stream of text,
section-start markers, etc. to produce instances of the
@schememodname[scribble/struct] datatypes. See
@schememodname[scribble/core] datatypes. See
@secref["decode"].}
@item{@schememodname[scribble/doclang]: A language to be used for the
@ -177,19 +197,22 @@ Working roughly from the bottom up, the Scribble layers are:
@schememodname[scribble/reader] with
@schememodname[scribble/doclang]. See @secref["docreader"].}
@item{@schememodname[scribble/basic]: A library of basic document
@item{@schememodname[scribble/base]: A library of basic document
operators---such as @scheme[title], @scheme[section], and
@scheme[secref]---for use with @schememodname[scribble/decode]
and a renderer. See @secref["basic"].}
and a renderer. This library name also can be used as a
language, where it combines @schememodname[scribble/doc] with
the exports of @schememodname[scribble/base]. See
@secref["base"].}
@item{@schememodname[scribble/scheme]: A library of functions for
typesetting Scheme code. See @secref["scheme"]. These functions
are not normally used directly, but instead through
are not normally used directly, but instead used through
@schememodname[scribble/manual].}
@item{@schememodname[scribble/manual]: A library of functions for
writing PLT Scheme documentation; re-exports
@schememodname[scribble/basic]. Also, the
@schememodname[scribble/base]. Also, the
@schememodname[scribble/manual-struct] library provides types
for index-entry descriptions created by functions in
@schememodname[scribble/manual]. See @secref["manual"].}

View File

@ -1,12 +1,18 @@
#lang scribble/doc
@(require scribble/manual
scribble/struct
scribble/core
scribble/html-variants
scribble/latex-variants
scheme/runtime-path
(prefix-in lp-ex: "lp-ex-doc.scrbl")
"utils.ss"
(for-label scribble/lp-include scribble/lp))
@title[#:tag "lp" #:style `((css "lp.css") (tex "lp.tex")) ]{Literate Programming}
@title[#:tag "lp"
#:style (make-style #f
(list (make-css-addition "lp.css")
(make-tex-addition "lp.tex")))
]{Literate Programming}
Programs written using @schememodname[scribble/lp] are simultaneously
two things: a program and a document describing the program.
@ -43,9 +49,9 @@ function @scheme[f] that squares its argument, and the documentation
is ignored. When it is included with @scheme[lp-include], it looks
like this:
@(make-blockquote
"LPBoxed"
(flow-paragraphs (part-flow lp-ex:doc)))
@(make-nested-flow
(make-style "LPBoxed" null)
(part-blocks lp-ex:doc))
@section{@schememodname[scribble/lp] Language}
@ -73,7 +79,11 @@ provides core support for literate programming.}
@section{@schememodname[scribble/lp-include] Module}
@defmodule[scribble/lp-include]{}
@defmodule[scribble/lp-include]{The
@schememodname[scribble/lp-include] library is normally used within a
Scribble document---that is, a module that starts with something like
@scheme[#, @hash-lang[] scribble/base] or @scheme[#, @hash-lang[]
scribble/manual], instead of @scheme[#, @hash-lang[] scheme].}
@defform[(lp-include filename)]{
Includes the source of @scheme[filename] as the typeset version of the literate

View File

@ -11,14 +11,20 @@
@defmodule[scribble/manual]{The @schememodname[scribble/manual]
library provides all of @schememodname[scribble/basic] plus additional
functions, including many that are relatively specific to writing PLT
Scheme documentation.
functions, including all of @scheme[scribble/base] plus many others
that are relatively specific to writing PLT Scheme documentation.
The @schememodname[scribble/manual] name can also be used as a
language with @hash-lang[]. It acts like the
@schememodname[scribble/doc] language, except that the
@schememodname[scribble/manual] library is also required into
the module.}
@schememodname[scribble/manual] library is also required into the
module.
In addition, @scheme[#, @hash-lang[] #, @schememodname[scribble/manual]]
associates a @scheme[latex-defaults] style @tech{variant} with its
@scheme[doc] export to select the default PLT Scheme manual style for
Latex rendering---unless a style is supplied to @scheme[title] that
already includes a @scheme[latex-defaults] @tech{variant}.}
@local-table-of-contents[]
@ -163,12 +169,6 @@ representation of literal text. Use this when you have to talk about
the individual characters in a stream of text, as as when documenting
a reader extension.}
@defproc[(verbatim [#:indent indent integer? 0] [str string?] ...)
flow-element?]{Typesets @scheme[str]
as a table/paragraph in typewriter font with the linebreaks specified
by newline characters in @scheme[str]. ``Here strings'' are often
useful with @scheme[verbatim].}
@defproc[(schemefont [pre-content any/c] ...) element?]{Typesets
@tech{decode}d @scheme[pre-content] as uncolored, unhyperlinked
Scheme. This procedure is useful for typesetting things like
@ -819,8 +819,8 @@ as a member of the signature named by @scheme[sig-id].}
@; ------------------------------------------------------------------------
@section[#:tag "doc-strings"]{Various String Forms}
@defproc[(emph [pre-content any/c] ...) element?]{Typesets the
@tech{decode}d @scheme[pre-content] with emphasis (e.g., in italic).}
@defproc[(aux-elem [pre-content any/c] ...) element?]{
Like @scheme[elem], but adds an @scheme['aux] style @tech{variant}.}
@defproc[(defterm [pre-content any/c] ...) element?]{Typesets the
@tech{decode}d @scheme[pre-content] as a defined term (e.g., in
@ -862,101 +862,28 @@ font with a leading @litchar{+}).}
@tech{decode}d @scheme[pre-content] a long @litchar{+} flag (e.g., in
typewriter font with two leading @litchar{+}s).}
@defproc[(math [pre-content any/c] ...) element?]{The @tech{decode}d
@scheme[pre-content] is further transformed:
@itemize[
@item{Any immediate @scheme['rsquo] is converted to @scheme['prime].}
@item{Parentheses and sequences of decimal digits in immediate
strings are left as-is, but any other immediate string is
italicized.}
]
Extensions to @scheme[math] are likely, such as recognizing @litchar{_}
and @litchar{^} for subscripts and superscripts.}
@; ------------------------------------------------------------------------
@section[#:tag "section-links"]{Links}
@defproc[(secref [tag string?]
[#:doc module-path (or/c module-path? false/c) #f]
[#:tag-prefixes prefixes (or/c (listof string?) false/c) #f]
[#:underline? underline? any/c #t])
element?]{
Inserts the hyperlinked title of the section tagged @scheme[tag], but
@schemeidfont{aux-element} items in the title content are omitted in the
hyperlink label.
If @scheme[#:doc module-path] is provided, the @scheme[tag] refers to
a tag with a prefix determined by @scheme[module-path]. When
@exec{setup-plt} renders documentation, it automatically adds a tag
prefix to the document based on the source module. Thus, for example,
to refer to a section of the PLT Scheme reference,
@scheme[module-path] would be @scheme['(lib
"scribblings/reference/reference.scrbl")].
The @scheme[#:tag-prefixes prefixes] argument similarly supports
selecting a particular section as determined by a path of tag
prefixes. When a @scheme[#:doc] argument is provided, then
@scheme[prefixes] should trace a path of tag-prefixed subsections to
reach the @scheme[tag] section. When @scheme[#:doc] is not provided,
the @scheme[prefixes] path is relative to any enclosing section (i.e.,
the youngest ancestor that produces a match).
If @scheme[underline?] is @scheme[#f], then the hyperlink is rendered
in HTML without an underline.}
@defproc[(seclink [tag string?]
[#:doc module-path (or/c module-path? false/c) #f]
[#:tag-prefixes prefixes (or/c (listof string?) false/c) #f]
[#:underline? underline? any/c #t]
[pre-content any/c] ...) element?]{
Like @scheme[secref], but the link label is the @tech{decode}d
@scheme[pre-content] instead of the target section's name.}
@defproc[(other-manual [module-path module-path?]
[#:underline? underline? any/c #t])
element?]{
Like @scheme[secref] for the document's implicit @scheme["top"]
tag. Use this function to refer to a whole manual instead of
@scheme[secref], in case a special style in the future is used for
manual titles.}
See also @secref["base-links"].
@defproc[(schemelink [id symbol?] [pre-content any/c] ...) element?]{
The @tech{decode}d @scheme[pre-content] is hyperlinked to the definition
of @scheme[id].}
@defproc[(link [url string?] [pre-content any/c] ...
[#:underline? underline? any/c #t]
[#:style style any/c (if underline? #f "plainlink")])
[#:underline? underline? any/c #t]
[#:style style (or/c style? string? symbol? #f) (if underline? #f "plainlink")])
element?]{
The @tech{decode}d @scheme[pre-content] is hyperlinked to
@scheme[url]. If @scheme[style] is not supplied, then
@scheme[underline?] determines how the link is rendered.}
An alias of @scheme[hyperlink] for backward compatibility.}
@defproc[(other-manual [module-path module-path?]
[#:underline? underline? any/c #t])
element?]{
@defproc[(elemtag [t tag?] [pre-content any/c] ...) element?]{
The tag @scheme[t] refers to the content form of
@scheme[pre-content].}
@defproc[(elemref [t tag?] [pre-content any/c] ...
[#:underline? underline? any/c #t]) element?]{
The @tech{decode}d @scheme[pre-content] is hyperlinked to @scheme[t],
which is normally defined using @scheme[elemtag].}
An alias of @scheme[other-doc] for backward compatibility.}
@defproc[(deftech [pre-content any/c] ...
[#:style? style? any/c #t]) element?]{
@ -1022,6 +949,8 @@ the link.}
@; ------------------------------------------------------------------------
@section[#:tag "manual-indexing"]{Indexing}
See also @secref["base-indexing"].
@defform[(indexed-scheme datum ...)]{
A combination of @scheme[scheme] and @scheme[as-index], with the
@ -1055,28 +984,13 @@ key for the index iterm does not include quotes.}
combination of @scheme[envvar] and @scheme[as-index].}
@; ------------------------------------------------------------------------
@section{Images}
@defproc[(image [filename-relative-to-source string?]
[pre-element any/c] ...)
flow-element?]{
Creates a centered image from the given relative source path. The
@tech{decode}d @scheme[pre-content] serves as the alternate text for
contexts where the image cannot be displayed.
The path is relative to the current directory, which is set by
@exec{setup-plt} and @exec{scribble} to the directory of the main
document file.
When generating Latex output, if the filename has a @filepath{.gif}
suffix, then the suffix is changed to @filepath{.png} (so a PNG file
must exist in addition to the GIF file).}
@section[#:tag "manual-images"]{Images}
@defproc[(image/plain [filename-relative-to-source string?]
[pre-element any/c] ...)
element?]{
Like @scheme[image], but the result is an element to appear inline in
a paragraph.}
An alias for @scheme[image] for backward compatibility.}
@; ------------------------------------------------------------------------
@section{Bibliography}
@ -1160,15 +1074,31 @@ that is hyperlinked to an explanation.}
@defthing[undefined-const element?]{Returns an element for @|undefined-const|.}
@defproc[(centerline [pre-flow any/c] ...) table?]{Produces a
centered table with the @scheme[pre-flow] parsed by
@scheme[decode-flow].}
@defproc[(commandline [pre-content any/c] ...) paragraph?]{Produces
an inset command-line example (e.g., in typewriter font).}
@defproc[(margin-note [pre-content any/c] ...) blockquote?]{Produces
a @tech{blockquote} to be typeset in the margin instead of inlined.}
@defproc[(centerline [pre-flow pre-flow?] ...) nested-flow?]{
An alias for @scheme[centered] for backward compatibility.}
@defproc[(math [pre-content any/c] ...) element?]{The @tech{decode}d
@scheme[pre-content] is further transformed:
@itemize[
@item{Any immediate @scheme['rsquo] is converted to @scheme['prime].}
@item{Parentheses and sequences of decimal digits in immediate
strings are left as-is, but any other immediate string is
italicized.}
@item{When @litchar{_} appears before a non-empty sequence of numbers
and letters, the sequence is typeset as a subscript.}
@item{When @litchar{^} appears before a non-empty sequence of numbers
and letters, the sequence is typeset as a superscript.}
]}
@; ------------------------------------------------------------------------
@section[#:tag "index-entries"]{Index-Entry Descriptions}

View File

@ -0,0 +1,26 @@
#lang scribble/manual
@(require "utils.ss"
(for-label scribble/sigplan))
@title{More Document Styles}
In addition to @schememodname[scribble/base] and
@schememodname[scribble/manual], Scribble provides a few extra
document styles as a convenience.
@section{SIGPLAN Paper Format}
@defmodulelang[scribble/sigplan]{The @schememodname[scribble/sigplan]
language is like @schememodname[scribble/manual], but configured with
Latex style defaults to use the @filepath{sigplanconf.cls} class
file that is included with Scribble.}
@defidform[preprint]{
Enables the @tt{preprint} option. Use @scheme[preprint] only on the
same line as @hash-lang[], with only whitespace between
@schememodname[scribble/sigplan] and @scheme[preprint]:
@verbatim[#:indent 2]|{
#lang scribble/sigplan @preprint
}|}

View File

@ -0,0 +1,13 @@
#lang scribble/manual
@(require "utils.ss")
@title[#:tag "plt-manuals" #:style 'toc]{PLT Scheme Manuals}
@local-table-of-contents[]
@include-section["manual.scrbl"]
@include-section["scheme.scrbl"]
@include-section["eval.scrbl"]
@include-section["srcdoc.scrbl"]
@include-section["bnf.scrbl"]
@include-section["compat.scrbl"]

View File

@ -1,12 +1,17 @@
#lang scribble/doc
@(require scribble/manual scribble/struct "utils.ss"
@(require scribble/manual
scribble/core scribble/html-variants scribble/latex-variants
"utils.ss"
(for-label scheme/base
;; FIXME: need to get this in
;; scribble/text
))
@initialize-tests
@title[#:tag "preprocessor"]{Text Preprocessor}
@title[#:tag "preprocessor"
#:style (make-style #f (list (make-tex-addition "shaded.tex")
(make-css-addition "shaded.css")))
]{Text Preprocessing}
@defmodulelang[scribble/text]{The @schememodname[scribble/text]
language provides everything from @scheme[scheme/base] with a few

View File

@ -440,7 +440,7 @@ of the text. This works for @litchar["@"] too:
}===|
@;--------------------------------------------------------------------
@subsubsub*section{Alternative Body Syntax}
@subsubsub*section[#:tag "alt-body-syntax"]{Alternative Body Syntax}
In addition to the above, there is an alternative syntax for the body,
one that specifies a new marker for its end: use @litchar["|{"] for

View File

@ -69,7 +69,7 @@ Like @scheme[to-paragraph], but @scheme[prefix1] is prefixed onto the
first line, @scheme[prefix] is prefix to any subsequent line, and
@scheme[suffix] is added to the end. The @scheme[prefix1],
@scheme[prefix], and @scheme[suffix] arguments are used as
@tech{elements}, except that if @scheme[suffix] is a list of elements,
@tech{content}, except that if @scheme[suffix] is a list of elements,
it is added to the end on its own line.}
@ -152,3 +152,29 @@ Provided @scheme[for-syntax]; like @scheme[make-element-id-transformer] for
a transformer that produces @scheme[sym] typeset as a variable (like
@scheme[schemevarfont])---unless it appears under quote or quasiquote,
in which case @scheme[sym] is typeset as a symbol.}
@deftogether[(
@defthing[output-color style?]
@defthing[input-color style?]
@defthing[input-background-color style?]
@defthing[no-color style?]
@defthing[reader-color style?]
@defthing[result-color style?]
@defthing[keyword-color style?]
@defthing[comment-color style?]
@defthing[paren-color style?]
@defthing[meta-color style?]
@defthing[value-color style?]
@defthing[symbol-color style?]
@defthing[variable-color style?]
@defthing[opt-color style?]
@defthing[error-color style?]
@defthing[syntax-link-color style?]
@defthing[value-link-color style?]
@defthing[module-color style?]
@defthing[module-link-color style?]
@defthing[block-color style?]
@defthing[highlighted-color style?]
)]{
Styles that are used for coloring Scheme programs, results, and I/O.}

View File

@ -1,19 +1,15 @@
#lang scribble/doc
@(require scribble/manual
scribble/bnf
#lang scribble/manual
@(require scribble/bnf
"utils.ss")
@title{@bold{Scribble}: PLT Documentation Tool}
@title{@bold{Scribble}: PLT Documentation Tools}
@author["Matthew Flatt" "Eli Barzilay"]
Scribble is a collection of tools for creating prose documents,
especially those that document libraries, and especially for HTML and
PDF (via LaTeX) output. More generally, it is useful for cases where
you need to deal with Scheme code that is rich in textual content: it
has a syntactic extension for writing almost free-form text and a tool
for using the scribble syntax for preprocessing text files with
embedded Scheme code.
Scribble is a collection of tools for creating ASCII, HTML, and
Latex/PDF documents with PLT Scheme. Suitable uses include the
creation of papers, books, literate programs, preprocessed text, and
PLT Scheme library documentation.
This document itself is written using Scribble. At the time that it
was written, its source was available at
@ -24,23 +20,11 @@ starting with the @filepath{scribble.scrbl} file.
@table-of-contents[]
@; ------------------------------------------------------------------------
@include-section["how-to.scrbl"]
@include-section["layers.scrbl"]
@include-section["reader.scrbl"]
@include-section["struct.scrbl"]
@include-section["renderer.scrbl"]
@include-section["decode.scrbl"]
@include-section["doclang.scrbl"]
@include-section["docreader.scrbl"]
@include-section["basic.scrbl"]
@include-section["scheme.scrbl"]
@include-section["manual.scrbl"]
@include-section["eval.scrbl"]
@include-section["srcdoc.scrbl"]
@include-section["bnf.scrbl"]
@include-section["getting-started.scrbl"]
@include-section["generic.scrbl"]
@include-section["plt.scrbl"]
@include-section["lp.scrbl"]
@include-section["xref.scrbl"]
@include-section["preprocessor.scrbl"]
@include-section["config.scrbl"]
@include-section["internals.scrbl"]
@index-section[]

View File

@ -0,0 +1,5 @@
.Shaded {
width: 100%;
background-color: #E8E8FF;
}

View File

@ -0,0 +1,5 @@
\newenvironment{Shaded}{}{}
\newcommand{\Short}[1]{\begin{minipage}[c]{6ex}#1\end{minipage}}
\newcommand{\Medium}[1]{\begin{minipage}[c]{20ex}#1\end{minipage}}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
#lang scheme/base
(require scribble/struct
(require scribble/core
scribble/html-variants
scribble/manual
(prefix-in scheme: scribble/scheme)
(prefix-in scribble: scribble/reader))
@ -15,25 +16,27 @@
[(_ mod ...) (begin (bounce-for-label mod) ...)]))
(bounce-for-label (all-except scheme (link) ())
scribble/struct
scribble/core
scribble/base-render
scribble/decode
scribble/manual
scribble/scheme
scribble/html-variants
scribble/latex-variants
scribble/eval
scribble/bnf)
(provide scribble-examples litchar/lines)
(define (as-flow e)
(make-flow (list (if (block? e) e (make-paragraph (list e))))))
(if (block? e) e (make-paragraph plain (list e))))
(define (litchar/lines . strs)
(let ([strs (regexp-split #rx"\n" (apply string-append strs))])
(if (= 1 (length strs))
(litchar (car strs))
(make-table
#f
plain
(map (lambda (s) ; the nbsp is needed for IE
(list (as-flow (if (string=? s "") 'nbsp (litchar s)))))
strs)))))
@ -69,7 +72,7 @@
p)]))
(define (scribble-examples . lines)
(define reads-as (make-paragraph (list spacer "reads as" spacer)))
(define reads-as (make-paragraph plain (list spacer "reads as" spacer)))
(let* ([lines (apply string-append lines)]
[p (open-input-string lines)])
(port-count-lines! p)
@ -87,7 +90,7 @@
(cdr (apply append (map (lambda (x) (list #f x)) r)))
r)])
(make-table
#f
plain
(map (lambda (x)
(let ([@expr (if x (litchar/lines (car x)) "")]
[sexpr (if x
@ -122,9 +125,10 @@
(list (as-flow (make-element 'newline '())))
(list (as-flow (make-element 'tt (str->elts str))))))
(define (small-attr attr)
(make-with-attributes attr '([style . "font-size: 82%;"])))
(make-style attr (list
(make-attributes '([style . "font-size: 82%;"])))))
(define (make-box strs)
(make-table (small-attr 'boxed) (map make-line strs)))
(make-table (small-attr "Shaded") (map make-line strs)))
(define filenames (map car more))
(define indent (let ([d (- max-textsample-width
(for*/fold ([m 0])
@ -138,16 +142,20 @@
;; Note: the font-size property is reset for every table, so we need it
;; everywhere there's text, and they don't accumulate for nested tables
(values
(make-table (make-with-attributes
'([alignment right left] [valignment top top])
'())
(make-table
(make-style #f
(list (make-table-columns (list (make-style (if (null? filenames)
"Short"
"Medium")
'(right top))
(make-style #f '(left top))))))
(cons (list (as-flow (make-table (small-attr #f)
(list (list (as-flow indent)))))
(as-flow (make-box strs1)))
(map (lambda (file strs)
(let* ([file (make-element 'tt (list file ":" 'nbsp))]
[file (list (make-element 'italic (list file)))])
(list (as-flow (make-element '(bg-color 232 232 255) file))
(list (as-flow (make-element (make-style #f (list (make-background-color-variant '(232 232 255)))) file))
(as-flow (make-box strs)))))
filenames strsm)))
(make-box strs2)))
@ -155,8 +163,11 @@
(define (textsample line in-text out-text more)
(define-values (box1 box2)
(textsample-verbatim-boxes line in-text out-text more))
(make-table '([alignment left left left] [valignment center center center])
(list (map as-flow (list box1 (make-paragraph '(nbsp rarr nbsp)) box2)))))
(make-table
(make-style #f (list (make-table-columns (list (make-style #f '(left vcenter))
(make-style "Short" '(left vcenter))
(make-style #f '(left vcenter))))))
(list (map as-flow (list box1 (make-paragraph plain '(nbsp rarr nbsp)) box2)))))
(define-for-syntax tests-ids #f)

View File

@ -1,5 +1,9 @@
.SBibliography p {
.AutoBibliography p {
padding-left: 1em;
text-indent: -1em;
}
.AutoBibliography td {
vertical-align: text-top;
}

View File

@ -1,21 +1,29 @@
#lang at-exp scheme/base
(require scribble/manual
scribble/struct
scribble/core
scribble/decode
scheme/string)
scribble/html-variants
scribble/latex-variants
scheme/string
setup/main-collects)
(provide autobib-style-extras
define-cite
(provide define-cite
make-bib in-bib (rename-out [auto-bib? bib?])
proceedings-location journal-location book-location
techrpt-location dissertation-location
author-name org-author-name authors other-authors editor)
(define (autobib-style-extras)
(define autobib-style-extras
(let ([abs (lambda (s)
(build-path (collection-path "scriblib") s))])
`((css ,(abs "autobib.css")) (tex ,(abs "autobib.tex")))))
(path->main-collects-relative
(build-path (collection-path "scriblib") s)))])
(list
(make-css-addition (abs "autobib.css"))
(make-tex-addition (abs "autobib.tex")))))
(define bib-table-style (make-style "AutoBibliography" autobib-style-extras))
(define bibentry-style (make-style "Autobibentry" autobib-style-extras))
(define-struct auto-bib (author date entry-element key specific))
(define-struct bib-group (ht))
@ -57,48 +65,46 @@
[bibs (sort (hash-map (bib-group-ht group)
(lambda (k v) k))
author<?)])
(make-unnumbered-part
(make-part
#f
`((part ,tag))
'("Bibliography")
'()
(make-style #f '(unnumbered))
null
(make-flow
(list
(make-table
"SBibliography"
(map (lambda (k)
(list
(make-flow
(list
(make-paragraph
(list
(make-collect-element
#f
(list (make-target-element
#f
(list (auto-bib-entry-element k))
`(autobib ,(auto-bib-key k))))
(lambda (ci)
(collect-put! ci
`(autobib-cite ,(auto-bib-key k))
(make-element
#f
(list
(author-element-cite (auto-bib-author k))
" "
(auto-bib-date k))))
(collect-put! ci
`(autobib-inline ,(auto-bib-key k))
(make-element
#f
(list
(author-element-cite (auto-bib-author k))
'nbsp
"("
(auto-bib-date k)
")")))))))))))
bibs))))
(list
(make-table
bib-table-style
(map (lambda (k)
(list
(make-paragraph
plain
(list
(make-collect-element
#f
(list (make-target-element
#f
(list (auto-bib-entry-element k))
`(autobib ,(auto-bib-key k))))
(lambda (ci)
(collect-put! ci
`(autobib-cite ,(auto-bib-key k))
(make-element
#f
(list
(author-element-cite (auto-bib-author k))
" "
(auto-bib-date k))))
(collect-put! ci
`(autobib-inline ,(auto-bib-key k))
(make-element
#f
(list
(author-element-cite (auto-bib-author k))
'nbsp
"("
(auto-bib-date k)
")")))))))))
bibs)))
null)))
(define-syntax-rule (define-cite ~cite citet generate-bibliography)
@ -112,7 +118,7 @@
(gen-bib tag group))))
(define (ends-in-punc? e)
(regexp-match? #rx"[.!?,]$" (element->string e)))
(regexp-match? #rx"[.!?,]$" (content->string e)))
(define (make-bib #:title title
#:author [author #f]
@ -125,7 +131,7 @@
[(author-element? author) author]
[else (parse-author author)])]
[elem (make-element
"bibentry"
bibentry-style
(append
(if author
`(,author
@ -144,13 +150,13 @@
(if location
`(" " ,@(decode-content (list location)) ,(if date "," "."))
null)
(if date `(" " ,@(decode-content (list date)) ".") null)
(if date `(" " ,@(decode-content (list (to-string date))) ".") null)
(if url `(" " ,(link url (make-element 'url (list url)))) null)))])
(make-auto-bib
(or author (org-author-name title))
date
(to-string date)
elem
(element->string elem)
(content->string elem)
"")))
(define (in-bib bib where)
@ -164,7 +170,7 @@
(define (parse-author a)
(if (author-element? a)
a
(let* ([s (element->string a)]
(let* ([s (content->string a)]
[m (regexp-match #rx"^(.*) ([A-Za-z]+)$" s)])
(make-author-element
#f
@ -183,13 +189,13 @@
#:volume [volume #f])
(let* ([s @elem{In @italic{@elem{Proc. @|location|}}}]
[s (if series
@elem{@|s|, @|series|}
@elem{@|s|, @(format "~a" series)}
s)]
[s (if volume
@elem{@|s| volume @|volume|}
@elem{@|s| volume @(format "~a" volume)}
s)]
[s (if pages
@elem{@|s|, pp. @(car pages)--@(cadr pages)}
@elem{@|s|, pp. @(to-string (car pages))--@(to-string (cadr pages))}
s)])
s))
@ -200,13 +206,13 @@
#:volume [volume #f])
(let* ([s @italic{@|location|}]
[s (if volume
@elem{@|s| @|volume|}
@elem{@|s| @(to-string volume)}
s)]
[s (if number
@elem{@|s|(@|number|)}
@elem{@|s|(@(to-string number))}
s)]
[s (if pages
@elem{@|s|, pp. @(car pages)--@(cadr pages)}
@elem{@|s|, pp. @(to-string (car pages))--@(to-string (cadr pages))}
s)])
s))
@ -301,3 +307,5 @@
'(" (Ed.)"))
(author-element-names name)
(author-element-cite name))))
(define (to-string v) (format "~a" v))

View File

@ -1,3 +1,3 @@
\renewenvironment{SBibliography}{\begin{small}}{\end{small}}
\renewcommand{\bibentry}[1]{\hspace{0.05\linewidth}\parbox[t]{0.95\linewidth}{\parindent=-0.05\linewidth#1\vspace{1.0ex}}}
\newenvironment{AutoBibliography}{\begin{small}}{\end{small}}
\newcommand{\Autobibentry}[1]{\hspace{0.05\linewidth}\parbox[t]{0.95\linewidth}{\parindent=-0.05\linewidth#1\vspace{1.0ex}}}

View File

@ -1,58 +1,67 @@
#lang scheme/base
(require scribble/manual
scribble/struct
scribble/core
scribble/decode
scribble/html-variants
scribble/latex-variants
setup/main-collects
"private/counter.ss")
(provide figure
figure*
figure**
Figure-target
Figure-ref
figure-style-extras)
Figure-ref)
(define (figure-style-extras)
(define figure-style-extras
(let ([abs (lambda (s)
(build-path (collection-path "scriblib") s))])
`((css ,(abs "figure.css")) (tex ,(abs "figure.tex")))))
(list (make-css-addition (abs "figure.css"))
(make-tex-addition (abs "figure.tex")))))
(define centerfigure-style (make-style "Centerfigure" figure-style-extras))
(define figureinside-style (make-style "FigureInside" figure-style-extras))
(define legend-style (make-style "Legend" figure-style-extras))
(define centerfiguremulti-style (make-style "CenterfigureMulti" figure-style-extras))
(define centerfiguremultiwide-style (make-style "CenterfigureMultiWide" figure-style-extras))
(define (figure tag caption . content)
(make-blockquote
"Centerfigure"
(make-nested-flow
centerfigure-style
(list
(make-blockquote
"FigureInside"
(make-nested-flow
figureinside-style
(append
(flow-paragraphs
(decode-flow content))
(decode-flow content)
(list
(make-paragraph
plain
(list
(make-element "Legend"
(make-element legend-style
(list* (Figure-target tag) ": "
(decode-content (list caption))))))))))))
(define (*figure style tag caption content)
(make-blockquote
(make-nested-flow
style
(list
(make-blockquote
"FigureInside"
(make-nested-flow
figureinside-style
(append
(flow-paragraphs
(decode-flow content))
(decode-flow content)
(list
(make-paragraph
plain
(list
(make-element "Legend"
(make-element legend-style
(list* (Figure-target tag) ": "
(decode-content (list caption))))))))))))
(define (figure* tag caption . content)
(*figure "CenterfigureMulti" tag caption content))
(*figure centerfiguremulti-style tag caption content))
(define (figure** tag caption . content)
(*figure "CenterfigureMultiWide" tag caption content))
(*figure centerfiguremultiwide-style tag caption content))
(define figures (new-counter "figure"))
(define (Figure-target tag)

View File

@ -12,4 +12,4 @@
\newenvironment{CenterfigureMulti}{\begin{figure*}\centering}{\end{figure*}}
\newenvironment{CenterfigureMultiWide}{\begin{CenterfigureMulti}}{\end{CenterfigureMulti}}
\newenvironment{Centerfigure}{\begin{figure}\centering}{\end{figure}}
\newenvironment{FigureInside}{\begin{list}{}{\leftmargin=0pt\parsep=\FigOrigskip}\item}{\end{list}}
\newenvironment{FigureInside}{\begin{list}{}{\leftmargin=0pt\topsep=0pt\parsep=\FigOrigskip\partopsep=0pt}\item}{\end{list}}

View File

@ -1,7 +1,7 @@
#lang scheme/base
(require scribble/eval
scribble/struct
scribble/core
scribble/scheme
scheme/class
scheme/file
@ -127,13 +127,14 @@
(send dc clear)
(((gui-eval 'make-pict-drawer) v) dc 0 0)
(send bm save-file fn 'png)
(make-element #f (list (make-element (make-image-file
;; For HTML output, .pdf is automatically changed to .png.
;; Be sure to use a string rather than a path, because
;; it gets recorded in "exprs.dat".
(path->string (path-replace-suffix fn #".pdf"))
1.0)
(list "[image]"))))))]
(make-image-element
#f
(list "[image]")
;; Be sure to use a string rather than a path, because
;; it gets recorded in "exprs.dat".
(path->string (path-replace-suffix fn #""))
'(".pdf" ".png")
1.0)))]
[(pair? v) (cons (fixup-picts (car v))
(fixup-picts (cdr v)))]
[(serializable? v) v]