scribble-enhanced/scribble-doc/scribblings/scribble/layers.scrbl
2014-12-02 00:54:52 -05:00

240 lines
8.7 KiB
Racket

#lang scribble/doc
@(require scribble/manual scribble/bnf "utils.rkt")
@title[#:tag "layers"]{Scribble Layers}
Scribble is made of independently usable parts. For example, the
Scribble reader can be used in any situation that requires lots of
free-form text. You can also skip Scribble's special reader support,
and instead use the document-generation structure directly.
@; ----------------------------------------------------------------------
@section{Typical Composition}
A Scribble document normally starts
@racketmod[
scribble/manual
]
but it could also start
@racketmod[
scribble/base
]
or
@racketmod[
scribble/doc
]
The last one introduces the smallest number of typesetting bindings in
the document body. Using @racketmodname[scribble/base] after
@hash-lang[] is the same as using @racketmodname[scribble/doc] plus
@racket[(require scribble/base)], and using
@racketmodname[scribble/manual] after @hash-lang[] is the same as using
@racketmodname[scribble/doc] plus @racket[(require scribble/manual)].
Besides making the file a module, each of the @hash-lang[]
declarations selects the Scribble reader (instead of the usual Racket
reader), and it starts the body of the file in ``text'' mode. The
reader layer mostly leaves text alone, but @tech{@"@"-forms} escape
to S-expression mode.
A module written as
@verbatim[#:indent 2]|{
#lang scribble/doc
@(require scribble/manual)
@(define to-be "To Be")
@title{@|to-be| or Not @|to-be|}
@bold{That} is the question.
Whether 'tis nobler...
}|
reads as
@racketblock[
(module #,(nonterm "name") scribble/doc
(require scribble/manual)
"\n"
(define to-be "To Be") "\n"
"\n"
(title to-be " or Not " to-be) "\n"
"\n"
(bold "That") " is the question." "\n"
"Whether 'tis nobler..." "\n")
]
As shown in this example, the read result is a module whose content
mingles text and definitions. The @racketmodname[scribble/doc]
language lifts definitions, @racket[require]s, and @racket[provide]s
to the beginning of the module, while everything else is collected
into a document bound to the provided identifier @racket[doc]. That
is, the module is transformed to something like this:
@racketblock[
(module #,(nonterm "name") racket/base
(require scribble/decode
scribble/manual)
(define to-be "To Be")
(define doc
(decode
"\n" "\n" "\n"
(title to-be " or Not " to-be) "\n"
"\n"
(bold "That") " is the question." "\n"
"Whether 'tis nobler..." "\n"))
(provide doc))
]
The @racket[decode] function produces a @racket[part] structure
instance that represents the document. To build the @racket[part]
instance, it inspects its arguments to find a @racket[title-decl]
value created by @racket[title] to name the part, @racket[part-start]
values created by @racket[section] to designate sub-parts, etc.
A @racket[part] is the input to a rendering back-end, such as the HTML
renderer. All renderers recognize a fixed structure hierarchy: the
content of a part is a @defterm{flow}, which is a sequence of
@defterm{flow elements}, such as paragraphs and tables; a table, in
turn, consists of a list of list of flows; a paragraph is a list of
@defterm{elements}, which can be instances of the @racket[element]
structure type, plain strings, or certain special symbols.
The value bound to @racket[doc] in the example above is something like
@racketblock[
(make-part ....
(list "To Be" " or Not " "To Be") (code:comment "title")
....
(make-flow
(list
(make-paragraph
(list (make-element 'bold (list "That"))
" is the question." "\n"
"Whether " 'rsquo "tis nobler..."))))
....)
]
Notice that the @litchar{'} in the input's @litchar{'tis} has turned
into @racket['rsquo] (rendered as a curly apostrophe). The conversion to use
@racket['rsquo] was performed by @racket[decode] via
@racket[decode-flow] via @racket[decode-paragraph] via
@racket[decode-content] via @racket[decode-string].
In contrast, @racket[(make-element 'bold (list "That"))] was produced
by the @racket[bold] function. The @racket[decode] operation is a
function, not a syntactic form, and so @racket[bold] has control over
its argument before @racket[decode] sees the result. Also, decoding
traverses only immediate string arguments.
As it turns out, @racket[bold] also decodes its argument, because the
@racket[bold] function is implemented as
@racketblock[
(define (bold . strs)
(make-element 'bold (decode-content strs)))
]
The @racket[verbatim] function, however, does not decode its content,
and instead typesets its text arguments directly.
A document module can construct elements directly using
@racket[make-element], but normally functions like @racket[bold] and
@racket[verbatim] are used to construct them. In particular, the
@racketmodname[scribble/manual] library provides many functions and
forms to typeset elements and flow elements.
The @racket[part] structure hierarchy includes built-in element types
for setting hyperlink targets and references. Again, this machinery is
normally packaged into higher-level functions and forms, such as
@racket[secref], @racket[defproc], and @racket[racket].
@; ----------------------------------------------------------------------
@section{Layer Roadmap}
Working roughly from the bottom up, the Scribble layers are:
@itemize[
@item{@racketmodname[scribble/reader]: A reader that extends the
syntax of Racket with @tech{@"@"-forms} for conveniently embedding a
mixin of text and escapes. See @secref["reader"].}
@item{@racketmodname[scribble/core]: A set of document datatypes
and utilities that define the basic layout and processing of a
document. For example, the @racket[part] datatype is defined in
this layer. See @secref["core"].}
@item{@racketmodname[scribble/base-render] with
@racketmodname[scribble/html-render],
@racketmodname[scribble/latex-render], or
@racketmodname[scribble/text-render]: A base renderer and
mixins that generate documents in various formats from
instances of the @racketmodname[scribble/struct] datatypes. See
@secref["renderer"].}
@item{@racketmodname[scribble/decode]: Processes a stream of text,
section-start markers, etc. to produce instances of the
@racketmodname[scribble/core] datatypes. See
@secref["decode"].}
@item{@racketmodname[scribble/doclang]: A language to be used for the
initial import of a module; processes the module top level
through @racketmodname[scribble/decode], and otherwise provides
all of @racketmodname[racket/base]. See @secref["doclang"].}
@item{@racketmodname[scribble/doc]: A language that combines
@racketmodname[scribble/reader] with
@racketmodname[scribble/doclang]. See @secref["docreader"].}
@item{@racketmodname[scribble/base]: A library of basic document
operators---such as @racket[title], @racket[section], and
@racket[secref]---for use with @racketmodname[scribble/decode]
and a renderer. This library name also can be used as a
language, where it combines @racketmodname[scribble/doc] with
the exports of @racketmodname[scribble/base]. See
@secref["base"].}
@item{@racketmodname[scribble/racket]: A library of functions for
typesetting Racket code. See @secref["scheme"]. These functions
are not normally used directly, but instead used through
@racketmodname[scribble/manual].}
@item{@racketmodname[scribble/manual]: A library of functions for
writing Racket documentation; re-exports
@racketmodname[scribble/base]. Also, the
@racketmodname[scribble/manual-struct] library provides types
for index-entry descriptions created by functions in
@racketmodname[scribble/manual]. See @secref["manual"].}
@item{@racketmodname[scribble/eval]: A library of functions for
evaluating code at document-build time, especially for showing
examples. See @secref["eval"].}
@item{@racketmodname[scribble/bnf]: A library of support functions
for writing grammars. See @secref["bnf"].}
@item{@racketmodname[scribble/xref]: A library of support functions
for using cross-reference information, typically after a
document is rendered (e.g., to search). See @secref["xref"].}
@item{@racketmodname[scribble/text]: A language that uses
@racketmodname[scribble/reader] preprocessing text files.}
]
The @exec{scribble} command-line utility generates output with a
specified renderer. More specifically, the executable installs a
renderer, loads the modules specified on the command line, extracts
the @racket[doc] export of each module (which must be an instance of
@racket[part]), and renders each---potentially with links that span
documents.