more improvements to the Scribble manual
svn: r15570 original commit: 3cb5bf183505c60f7428ca558894d52a173469ed
This commit is contained in:
parent
478de81b55
commit
4b30348010
|
@ -25,7 +25,7 @@
|
|||
[(_ id)
|
||||
@def-elem-proc[id]{Like @scheme[elem], but with style @scheme['id].}]))
|
||||
|
||||
@title[#:tag "base"]{Base Document Forms}
|
||||
@title[#:tag "base"]{Base Document Format}
|
||||
|
||||
@defmodule[scribble/base]{The @schememodname[scribble/base] library
|
||||
provides functions and forms that can be used from code written either
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#lang scribble/manual
|
||||
@(require "utils.ss")
|
||||
|
||||
@title[#:tag "generic-prose"]{General Documents}
|
||||
@title[#:tag "generic-prose" #:style 'toc]{High-Level Scribble API}
|
||||
|
||||
@local-table-of-contents[]
|
||||
|
||||
@include-section["base.scrbl"]
|
||||
@include-section["other.scrbl"]
|
||||
@include-section["manual-stub.scrbl"]
|
||||
@include-section["sigplan.scrbl"]
|
||||
|
|
|
@ -2,10 +2,7 @@
|
|||
|
||||
@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[]
|
||||
|
||||
|
|
|
@ -6,10 +6,12 @@
|
|||
@(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}
|
||||
@title[#:tag "how-to-paper"]{Getting Started}
|
||||
|
||||
This chapter demonstrates the basics of generating stand-alone HTML
|
||||
and PDF (through Latex) documents with Scribble.
|
||||
No matter what you want to do with Scribble, it's best to start by
|
||||
generating a few simple HTML and/or PDF documents. This chapter steps
|
||||
you through the basics, and it ends in @secref["roadmap"] with
|
||||
goal-specific advice on how to continue.
|
||||
|
||||
@section[#:tag "first-example"]{A First Example}
|
||||
|
||||
|
@ -387,7 +389,7 @@ 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}
|
||||
@section[#:tag "how-to:reader"]{@"@" Syntax Basics}
|
||||
|
||||
The @"@" notation provided by Scribble is just another way of
|
||||
writing Scheme expressions. Scribble documents could be constructed
|
||||
|
@ -591,32 +593,15 @@ renders as
|
|||
}
|
||||
|
||||
@; ----------------------------------------
|
||||
@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.
|
||||
@section[#:tag "roadmap"]{Next Steps}
|
||||
|
||||
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"].
|
||||
literate programs, skip to @secref["how-to-doc"].
|
||||
|
||||
If you are more interested in producing documents unrelated to PLT
|
||||
Scheme, skip continue with @secref["reader"] and then
|
||||
@secref["generic-prose"]. Move on to @secref["internals"] when you
|
||||
need more power.
|
||||
|
||||
If you are interested in text preprocessing, contiue with
|
||||
@secref["reader"], but then skip to @secref["preprocessor"].
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
scribble/bnf
|
||||
"utils.ss")
|
||||
|
||||
@title[#:tag "how-to-doc"]{How to Scribble PLT Scheme Documentation}
|
||||
@title[#:tag "how-to-doc"]{Starting Documentation}
|
||||
|
||||
Although the @exec{scribble} command-line utility generates output
|
||||
from a Scribble document, documentation of PLT Scheme libraries is
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#lang scribble/manual
|
||||
@(require "utils.ss")
|
||||
|
||||
@title[#:tag "internals" #:style 'toc]{Low-Level Scribble}
|
||||
@title[#:tag "internals" #:style 'toc]{Low-Level Scribble API}
|
||||
|
||||
@local-table-of-contents[]
|
||||
|
||||
@include-section["layers.scrbl"]
|
||||
@include-section["reader.scrbl"]
|
||||
@include-section["reader-internals.scrbl"]
|
||||
@include-section["core.scrbl"]
|
||||
@include-section["renderer.scrbl"]
|
||||
@include-section["decode.scrbl"]
|
||||
|
|
9
collects/scribblings/scribble/manual-stub.scrbl
Normal file
9
collects/scribblings/scribble/manual-stub.scrbl
Normal file
|
@ -0,0 +1,9 @@
|
|||
#lang scribble/manual
|
||||
@(require "utils.ss"
|
||||
(for-label scribble/sigplan))
|
||||
|
||||
@title{PLT Scheme Manual Format}
|
||||
|
||||
The @schememodname[scribble/manual] language is a major component of
|
||||
Scribble, and it is documented in its own chapter:
|
||||
@secref["plt-manuals"].
|
|
@ -1,10 +1,21 @@
|
|||
#lang scribble/manual
|
||||
@(require "utils.ss")
|
||||
|
||||
@title[#:tag "plt-manuals" #:style 'toc]{PLT Scheme Manuals}
|
||||
@title[#:tag "plt-manuals" #:style 'toc]{Scribbling Documentation}
|
||||
|
||||
The @schememodname[scribble/manual] language and associated libraries
|
||||
provide extensive support for documenting PLT Scheme libraries. The
|
||||
most significant aspect of support for documentation is the way that
|
||||
source-code bindings are connected to documentation sites through the
|
||||
module namespace---a connection that is facilitated by the fact that
|
||||
Scribble documents are themselves modules that reside in the same
|
||||
namespace. @Secref["how-to-doc"] provides an introduction to using
|
||||
Scribble for documentation, and the remaining sections document the
|
||||
relevant libraries and APIs in detail.
|
||||
|
||||
@local-table-of-contents[]
|
||||
|
||||
@include-section["how-to.scrbl"]
|
||||
@include-section["manual.scrbl"]
|
||||
@include-section["scheme.scrbl"]
|
||||
@include-section["eval.scrbl"]
|
||||
|
|
286
collects/scribblings/scribble/reader-internals.scrbl
Normal file
286
collects/scribblings/scribble/reader-internals.scrbl
Normal file
|
@ -0,0 +1,286 @@
|
|||
#lang scribble/doc
|
||||
@(require scribble/manual
|
||||
scribble/bnf
|
||||
scribble/eval
|
||||
"utils.ss"
|
||||
(for-syntax scheme/base)
|
||||
(for-label (only-in scribble/reader
|
||||
use-at-readtable)))
|
||||
|
||||
@(define read-eval (make-base-eval))
|
||||
@(interaction-eval #:eval read-eval (require (for-syntax scheme/base)))
|
||||
|
||||
@title[#:tag "reader-internals"]{@"@" Reader Internals}
|
||||
|
||||
@;--------------------------------------------------------------------
|
||||
@section{Using the @"@" Reader}
|
||||
|
||||
You can use the reader via Scheme's @schemefont{#reader} form:
|
||||
|
||||
@schemeblock[
|
||||
@#,schemefont|{
|
||||
#reader scribble/reader @foo{This is free-form text!}
|
||||
}|]
|
||||
|
||||
or use the @scheme[at-exp] meta-language as described in
|
||||
@secref["at-exp-lang"].
|
||||
|
||||
Note that the Scribble reader reads @"@"-forms as S-expressions. This
|
||||
means that it is up to you to give meanings for these expressions in
|
||||
the usual way: use Scheme functions, define your functions, or require
|
||||
functions. For example, typing the above into @exec{mzscheme} is likely
|
||||
going to produce a ``reference to undefined identifier'' error, unless
|
||||
@scheme[foo] is defined. You can use @scheme[string-append] instead,
|
||||
or you can define @scheme[foo] as a function (with variable arity).
|
||||
|
||||
A common use of the Scribble @"@"-reader is when using Scribble as a
|
||||
documentation system for producing manuals. In this case, the manual
|
||||
text is likely to start with
|
||||
|
||||
@schememod[scribble/doc]
|
||||
|
||||
which installs the @"@" reader starting in ``text mode,'' wraps the
|
||||
file content afterward into a Scheme module where many useful Scheme
|
||||
and documentation related functions are available, and parses the body
|
||||
into a document using @schememodname[scribble/decode]. See
|
||||
@secref["docreader"] for more information.
|
||||
|
||||
Another way to use the reader is to use the @scheme[use-at-readtable]
|
||||
function to switch the current readtable to a readtable that parses
|
||||
@"@"-forms. You can do this in a single command line:
|
||||
|
||||
@commandline{mzscheme -ile scribble/reader "(use-at-readtable)"}
|
||||
|
||||
@;--------------------------------------------------------------------
|
||||
@section{Syntax Properties}
|
||||
|
||||
The Scribble reader attaches properties to syntax objects. These
|
||||
properties might be useful in some rare situations.
|
||||
|
||||
Forms that Scribble reads are marked with a @scheme['scribble]
|
||||
property, and a value of a list of three elements: the first is
|
||||
@scheme['form], the second is the number of items that were read from
|
||||
the datum part, and the third is the number of items in the body part
|
||||
(strings, sub-forms, and escapes). In both cases, a @scheme[0] means
|
||||
an empty datum/body part, and @scheme[#f] means that the corresponding
|
||||
part was omitted. If the form has neither parts, the property is not
|
||||
attached to the result. This property can be used to give different
|
||||
meanings to expressions from the datum and the body parts, for
|
||||
example, implicitly quoted keywords:
|
||||
|
||||
@; FIXME: a bit of code duplication here
|
||||
@def+int[
|
||||
#:eval read-eval
|
||||
(define-syntax (foo stx)
|
||||
(let ([p (syntax-property stx 'scribble)])
|
||||
(printf ">>> ~s\n" (syntax->datum stx))
|
||||
(syntax-case stx ()
|
||||
[(_ x ...)
|
||||
(and (pair? p) (eq? (car p) 'form) (even? (cadr p)))
|
||||
(let loop ([n (/ (cadr p) 2)]
|
||||
[as '()]
|
||||
[xs (syntax->list #'(x ...))])
|
||||
(if (zero? n)
|
||||
(with-syntax ([attrs (reverse as)]
|
||||
[(x ...) xs])
|
||||
#'(list 'foo `attrs x ...))
|
||||
(loop (sub1 n)
|
||||
(cons (with-syntax ([key (car xs)]
|
||||
[val (cadr xs)])
|
||||
#'(key ,val))
|
||||
as)
|
||||
(cddr xs))))])))
|
||||
(eval:alts
|
||||
(code:line
|
||||
@#,tt["@foo[x 1 y (* 2 3)]{blah}"])
|
||||
;; Unfortunately, expressions are preserved by `def+int'
|
||||
;; using `quote', not `quote-syntax' (which would create all sorts
|
||||
;; or binding trouble), so we manually re-attach the property:
|
||||
(eval (syntax-property #'@foo[x 1 y (* 2 3)]{blah}
|
||||
'scribble '(form 4 1))))
|
||||
]
|
||||
|
||||
In addition, the Scribble parser uses syntax properties to mark syntax
|
||||
items that are not physically in the original source --- indentation
|
||||
spaces and newlines. Both of these will have a @scheme['scribble]
|
||||
property; an indentation string of spaces will have
|
||||
@scheme['indentation] as the value of the property, and a newline will
|
||||
have a @scheme['(newline S)] value where @scheme[S] is the original
|
||||
newline string including spaces that precede and follow it (which
|
||||
includes the indentation for the following item). This can be used to
|
||||
implement a verbatim environment: drop indentation strings, and use
|
||||
the original source strings instead of the single-newline string. Here
|
||||
is an example of this.
|
||||
|
||||
@; FIXME: a bit of code duplication here
|
||||
@def+int[
|
||||
#:eval read-eval
|
||||
(define-syntax (verb stx)
|
||||
(syntax-case stx ()
|
||||
[(_ cmd item ...)
|
||||
#`(cmd
|
||||
#,@(let loop ([items (syntax->list #'(item ...))])
|
||||
(if (null? items)
|
||||
'()
|
||||
(let* ([fst (car items)]
|
||||
[prop (syntax-property fst 'scribble)]
|
||||
[rst (loop (cdr items))])
|
||||
(cond [(eq? prop 'indentation) rst]
|
||||
[(not (and (pair? prop)
|
||||
(eq? (car prop) 'newline)))
|
||||
(cons fst rst)]
|
||||
[else (cons (datum->syntax-object
|
||||
fst (cadr prop) fst)
|
||||
rst)])))))]))
|
||||
(eval:alts
|
||||
(code:line
|
||||
@#,tt["@verb[string-append]{"]
|
||||
@#,tt[" foo"]
|
||||
@#,tt[" bar"]
|
||||
@#,tt["}"])
|
||||
@verb[string-append]{
|
||||
foo
|
||||
bar
|
||||
})
|
||||
]
|
||||
|
||||
@;--------------------------------------------------------------------
|
||||
@section[#:tag "at-exp-lang"]{Adding @"@"-expressions to a Language}
|
||||
|
||||
@defmodulelang[at-exp]{The @schememodname[at-exp] language installs
|
||||
@"@"-reader support in the readtable, and then chains to the reader of
|
||||
another language that is specified immediate after
|
||||
@schememodname[at-exp].}
|
||||
|
||||
For example, @scheme[@#,hash-lang[] at-exp scheme/base] adds @"@"-reader
|
||||
support to @scheme[scheme/base], so that
|
||||
|
||||
@schememod[
|
||||
at-exp scheme/base
|
||||
|
||||
(define (greet who) @#,elem{@tt["@"]@scheme[string-append]@schemeparenfont["{"]@schemevalfont{Hello, }@tt["@|"]@scheme[who]@tt["|"]@schemevalfont{.}@schemeparenfont["}"]})
|
||||
(greet "friend")]
|
||||
|
||||
reports @scheme["Hello, friend."].
|
||||
|
||||
@;--------------------------------------------------------------------
|
||||
@section{Interface}
|
||||
|
||||
@defmodule[scribble/reader]{The @schememodname[scribble/reader] module
|
||||
provides direct Scribble reader functionality for advanced needs.}
|
||||
|
||||
@; The `with-scribble-read' trick below shadows `read' and
|
||||
@; `read-syntax' with for-label bindings from the Scribble reader
|
||||
|
||||
@(define-syntax with-scribble-read
|
||||
(syntax-rules ()
|
||||
[(_)
|
||||
(...
|
||||
(begin
|
||||
(require (for-label scribble/reader))
|
||||
|
||||
@; *** Start reader-import section ***
|
||||
@defproc[(read [in input-port? (current-input-port)]) any]{}
|
||||
@defproc[(read-syntax [source-name any/c (object-name in)]
|
||||
[in input-port? (current-input-port)])
|
||||
(or/c syntax? eof-object?)]{
|
||||
These procedures implement the Scribble reader. They do so by
|
||||
constructing a reader table based on the current one, and using that
|
||||
for reading.
|
||||
}
|
||||
|
||||
@defproc[(read-inside [in input-port? (current-input-port)]) any]{}
|
||||
@defproc[(read-syntax-inside [source-name any/c (object-name in)]
|
||||
[in input-port? (current-input-port)])
|
||||
(or/c syntax? eof-object?)]{
|
||||
These @schemeid[-inside] variants parse as if starting inside a
|
||||
@litchar["@{"]...@litchar["}"], and they return a (syntactic) list.
|
||||
Useful for implementing languages that are textual by default (see
|
||||
@filepath{docreader.ss} for example).
|
||||
}
|
||||
|
||||
@defproc[(make-at-readtable
|
||||
[#:readtable readtable readtable? (current-readtable)]
|
||||
[#:command-char command-char character? #\@]
|
||||
[#:datum-readtable datum-readtable
|
||||
(or/c readtable? boolean?
|
||||
(readtable? . -> . readtable?))
|
||||
#t]
|
||||
[#:syntax-post-processor syntax-post-proc
|
||||
(syntax? . -> . syntax?)
|
||||
values])
|
||||
readtable?]{
|
||||
|
||||
Constructs an @"@"-readtable. The keyword arguments can customize the
|
||||
resulting reader in several ways:
|
||||
|
||||
@itemize[
|
||||
|
||||
@item{@scheme[readtable] --- a readtable to base the @"@"-readtable
|
||||
on.}
|
||||
|
||||
@item{@scheme[command-char] --- the character used for @"@"-forms.}
|
||||
|
||||
@item{@scheme[datum-readtable] --- determines the readtable used for
|
||||
reading the datum part. A @scheme[#t] values uses the
|
||||
@"@"-readtable, otherwise it can be a readtable, or a
|
||||
readtable-to-readtable function that will construct one from the
|
||||
@"@"-readtable. The idea is that you may want to have completely
|
||||
different uses for the datum part, for example, introducing a
|
||||
convenient @litchar{key=val} syntax for attributes.}
|
||||
|
||||
@item{@scheme[syntax-post-proc] --- function that is applied on
|
||||
each resulting syntax value after it has been parsed (but before it
|
||||
is wrapped quoting punctuations). You can use this to further
|
||||
control uses of @"@"-forms, for example, making the command be the
|
||||
head of a list:
|
||||
|
||||
@schemeblock[
|
||||
(use-at-readtable
|
||||
#:syntax-post-processor
|
||||
(lambda (stx)
|
||||
(syntax-case stx ()
|
||||
[(cmd rest ...) #'(list 'cmd rest ...)]
|
||||
[_else (error "@ forms must have a body")])))
|
||||
]}
|
||||
|
||||
]}
|
||||
|
||||
@defproc[(make-at-reader [#:syntax? syntax? #t] [#:inside? inside? #f] ...)
|
||||
procedure?]{
|
||||
Constructs a variant of a @"@"-readtable. The arguments are the same
|
||||
as in @scheme[make-at-readtable], with two more that determine the
|
||||
kind of reader function that will be created: @scheme[syntax?] chooses
|
||||
between a @scheme[read]- or @scheme[read-syntax]-like function, and
|
||||
@scheme[inside?] chooses a plain reader or an @schemeid[-inside]
|
||||
variant.
|
||||
|
||||
The resulting function has a different contract and action based on
|
||||
these inputs. The expected inputs are as in @scheme[read] or
|
||||
@scheme[read-syntax] depending on @scheme[syntax?]; the function will
|
||||
read a single expression or, if @scheme[inside?] is true, the whole
|
||||
input; it will return a syntactic list of expressions rather than a
|
||||
single one in this case.
|
||||
|
||||
Note that @scheme[syntax?] defaults to @scheme[#t], as this is the
|
||||
more expected common case when you're dealing with concrete-syntax
|
||||
reading.
|
||||
|
||||
Note that if @scheme[syntax?] is true, the @scheme[read]-like function
|
||||
is constructed by simply converting a syntax result back into a datum.}
|
||||
|
||||
@defproc[(use-at-readtable ...) void?]{
|
||||
|
||||
Passes all arguments to @scheme[make-at-readtable], and installs the
|
||||
resulting readtable using @scheme[current-readtable]. It also enables
|
||||
line counting for the current input-port via @scheme[port-count-lines!].
|
||||
|
||||
This is mostly useful for playing with the Scribble syntax on the REPL.}
|
||||
|
||||
@; *** End reader-import section ***
|
||||
))]))
|
||||
@with-scribble-read[]
|
||||
|
||||
@; --------------------------------------------------
|
||||
@(close-eval read-eval)
|
||||
|
|
@ -10,54 +10,41 @@
|
|||
@(define read-eval (make-base-eval))
|
||||
@(interaction-eval #:eval read-eval (require (for-syntax scheme/base)))
|
||||
|
||||
@title[#:tag "reader"]{@"@"-Reader}
|
||||
@(define (at-exp-scheme)
|
||||
@scheme[#, @hash-lang[] #, @schememodname[at-exp] #, @schemeidfont{scheme}])
|
||||
|
||||
The Scribble @"@"-reader is designed to be a convenient facility for
|
||||
using free-form text in Scheme code, where ``@"@"'' is chosen as one of
|
||||
the least-used characters in Scheme code.
|
||||
@title[#:tag "reader"]{@"@" Syntax}
|
||||
|
||||
You can use the reader via Scheme's @schemefont{#reader} form:
|
||||
The Scribble @"@" notation is designed to be a convenient facility for
|
||||
free-form text in Scheme code, where ``@"@"'' was chosen as one of the
|
||||
least-used characters in existing Scheme code. An @"@"-expression is
|
||||
simply an S-expression in disguise.
|
||||
|
||||
@schemeblock[
|
||||
@#,schemefont|{
|
||||
#reader scribble/reader @foo{This is free-form text!}
|
||||
}|]
|
||||
Typically, @"@" notation is enabled through
|
||||
@schememodname[scribble/base] or similar languages, but you can also
|
||||
add @"@" notation to an S-expression-based language using the
|
||||
@schememodname[at-exp] meta-language. For example,
|
||||
|
||||
or use the @scheme[at-exp] meta-language as described in
|
||||
@secref["at-exp-lang"].
|
||||
@verbatim[#:indent 2]|{
|
||||
#lang at-exp scheme
|
||||
(define v '@op{str})
|
||||
}|
|
||||
|
||||
Note that the Scribble reader reads @"@"-forms as S-expressions. This
|
||||
means that it is up to you to give meanings for these expressions in
|
||||
the usual way: use Scheme functions, define your functions, or require
|
||||
functions. For example, typing the above into @exec{mzscheme} is likely
|
||||
going to produce a ``reference to undefined identifier'' error, unless
|
||||
@scheme[foo] is defined. You can use @scheme[string-append] instead,
|
||||
or you can define @scheme[foo] as a function (with variable arity).
|
||||
is equivalent to
|
||||
|
||||
A common use of the Scribble @"@"-reader is when using Scribble as a
|
||||
documentation system for producing manuals. In this case, the manual
|
||||
text is likely to start with
|
||||
@schememod[
|
||||
scheme
|
||||
(define v '(op "str"))
|
||||
]
|
||||
|
||||
@schememod[scribble/doc]
|
||||
|
||||
which installs the @"@" reader starting in ``text mode,'' wraps the
|
||||
file content afterward into a Scheme module where many useful Scheme
|
||||
and documentation related functions are available, and parses the body
|
||||
into a document using @schememodname[scribble/decode]. See
|
||||
@secref["docreader"] for more information.
|
||||
|
||||
Another way to use the reader is to use the @scheme[use-at-readtable]
|
||||
function to switch the current readtable to a readtable that parses
|
||||
@"@"-forms. You can do this in a single command line:
|
||||
|
||||
@commandline{mzscheme -ile scribble/reader "(use-at-readtable)"}
|
||||
Using @at-exp-scheme[] is probably the easiest way to try the examples
|
||||
in this chapter.
|
||||
|
||||
@;--------------------------------------------------------------------
|
||||
@section{Concrete Syntax}
|
||||
@section{The Scribble Syntax at a Glance}
|
||||
|
||||
@subsection{The Scribble Syntax at a Glance}
|
||||
|
||||
Informally, the concrete syntax of @"@"-forms is
|
||||
To review @secref["how-to:reader"], the concrete syntax of @"@"-forms
|
||||
is roughly
|
||||
|
||||
@schemeblock[
|
||||
@#,BNF-seq[@litchar["@"]
|
||||
|
@ -67,7 +54,7 @@ Informally, the concrete syntax of @"@"-forms is
|
|||
]
|
||||
|
||||
where all three parts after @litchar["@"] are optional, but at least
|
||||
one should be present. (Note that spaces are not allowed between the
|
||||
one should be present. (Spaces are not allowed between the
|
||||
three parts.) Roughly, a form matching the above grammar is read as
|
||||
|
||||
@schemeblock[
|
||||
|
@ -80,8 +67,48 @@ determines the Scheme code that the input is translated into. The
|
|||
common case is when @nonterm{cmd} is a Scheme identifier, which reads
|
||||
as a plain Scheme form, with datum arguments and/or string arguments.
|
||||
|
||||
Here is one example:
|
||||
|
||||
@scribble-examples|==={
|
||||
@foo{blah blah blah}
|
||||
}===|
|
||||
|
||||
The example shows how an input syntax is read as Scheme syntax, not
|
||||
what it evaluates to. If you want to see the translation of an example
|
||||
into S-expression form, add a quote in front of it in a
|
||||
@at-exp-scheme[] module. For example, running
|
||||
|
||||
@verbatim[#:indent 2]|{
|
||||
#lang at-exp scheme
|
||||
'@foo{blah blah blah}
|
||||
}|
|
||||
|
||||
in DrScheme prints the output
|
||||
|
||||
@nested[#:style 'inset]{@schemeresult[(foo "blah blah blah")]}
|
||||
|
||||
while omitting the quote
|
||||
|
||||
@verbatim[#:indent 2]|{
|
||||
#lang at-exp scheme
|
||||
@foo{blah blah blah}
|
||||
}|
|
||||
|
||||
triggers a syntax error because @scheme[foo] is not bound, and
|
||||
|
||||
@verbatim[#:indent 2]|{
|
||||
#lang at-exp scheme
|
||||
(define (foo str) (printf "He wrote ~s.\n" str))
|
||||
@foo{blah blah blah}
|
||||
}|
|
||||
|
||||
prints the output
|
||||
|
||||
@nested[#:style 'inset]{@schemeoutput{He wrote "blah blah blah".}}
|
||||
|
||||
Here are more examples of @"@"-forms:
|
||||
|
||||
@scribble-examples|==={
|
||||
@foo{blah "blah" (`blah'?)}
|
||||
@foo[1 2]{3 4}
|
||||
@foo[1 2 3 4]
|
||||
|
@ -94,9 +121,6 @@ as a plain Scheme form, with datum arguments and/or string arguments.
|
|||
}
|
||||
}===|
|
||||
|
||||
(Note that these examples show how an input syntax is read as Scheme
|
||||
syntax, not what it evaluates to.)
|
||||
|
||||
As seen in the last example, multiple lines and the newlines that
|
||||
separate them are parsed to multiple Scheme strings. More generally,
|
||||
a @nonterm{text-body} is made of text, newlines, and nested
|
||||
|
@ -116,9 +140,10 @@ expressions.
|
|||
*p = '\n';}
|
||||
}===|
|
||||
|
||||
The command part of an @"@"-form is optional as well, which is read as
|
||||
a list, usually a function application, but also useful when quoted
|
||||
with the usual Scheme @scheme[quote]:
|
||||
The command part of an @"@"-form is optional as well. In that case,
|
||||
the @"@" forms is read as a list, which usually counts as a function
|
||||
application, but it also useful when quoted with the usual Scheme
|
||||
@scheme[quote]:
|
||||
|
||||
@scribble-examples|==={
|
||||
@{blah blah}
|
||||
|
@ -128,8 +153,8 @@ with the usual Scheme @scheme[quote]:
|
|||
baz}
|
||||
}===|
|
||||
|
||||
But we can also drop the datum and text parts, which leaves us with
|
||||
only the command --- which is read as is, not within a parenthesized
|
||||
Finally, we can also drop the datum and text parts, which leaves us with
|
||||
only the command---which is read as is, not within a parenthesized
|
||||
form. This is not useful when reading Scheme code, but it can be used
|
||||
inside a text block to escape a Scheme identifier. A vertical bar
|
||||
(@litchar{|}) can be used to delimit the escaped identifier when
|
||||
|
@ -142,7 +167,8 @@ needed.
|
|||
@{blah @|foo|: blah}
|
||||
}===|
|
||||
|
||||
Actually, the command part can be any Scheme expression, which is
|
||||
Actually, the command part can be any Scheme expression (that does
|
||||
start with @litchar["["], @litchar["{"], or @litchar["|"]), which is
|
||||
particularly useful with such escapes since they can be used with any
|
||||
expression.
|
||||
|
||||
|
@ -153,8 +179,8 @@ expression.
|
|||
|
||||
Note that an escaped Scheme string is merged with the surrounding text
|
||||
as a special case. This is useful if you want to use the special
|
||||
characters in your string (but note that escaping braces is not
|
||||
necessary if they are balanced).
|
||||
characters in your string, but escaping braces are not necessary if
|
||||
they are balanced.
|
||||
|
||||
@scribble-examples|==={
|
||||
@foo{eli@"@"barzilay.org}
|
||||
|
@ -164,9 +190,10 @@ necessary if they are balanced).
|
|||
}}
|
||||
}===|
|
||||
|
||||
In some cases a @"@"-rich text can become cumbersome to quote. For
|
||||
this, the braces have an alternative syntax --- a block of text can
|
||||
begin with a ``@litchar["|{"]'' and terminated accordingly with a
|
||||
In some cases, a text contains many literal @"@"s, which can be
|
||||
cumbersome to quote individually. For such case, braces have an
|
||||
alternative syntax: A block of text can begin with a
|
||||
``@litchar["|{"]'' and terminated accordingly with a
|
||||
``@litchar["}|"]''. Furthermore, any nested @"@" forms must begin
|
||||
with a ``@litchar["|@"]''.
|
||||
|
||||
|
@ -179,21 +206,22 @@ with a ``@litchar["|@"]''.
|
|||
In cases when even this is not convenient enough, punctuation
|
||||
characters can be added between the @litchar{|} and the braces and the
|
||||
@"@" in nested forms. (The punctuation is mirrored for parentheses
|
||||
and @litchar{<>}s.) With this, the Scribble syntax can be used as a
|
||||
here-string replacement.
|
||||
and @litchar{<>}s.) With this extension, Scribble syntax can be used as a
|
||||
``here string'' replacement.
|
||||
|
||||
@scribble-examples|==={
|
||||
@foo|--{bar}@|{baz}--|
|
||||
@foo|<<{bar}@|{baz}>>|
|
||||
}===|
|
||||
|
||||
The flip side of this is: how can an @"@" sign be used in Scheme code?
|
||||
This is almost never an issue, because Scheme strings and characters
|
||||
are still read the same, and because @litchar["@"] is set as a
|
||||
On the flip side of this is, how can an @"@" sign be used in Scheme
|
||||
code? This is almost never an issue, because Scheme strings and
|
||||
characters are still read the same, and @litchar["@"] is set as a
|
||||
non-terminating reader macro so it can be used in Scheme identifiers
|
||||
as usual, except when it is the first character of an identifier. In
|
||||
this case, you need to quote the identifier like other non-standard
|
||||
characters --- with a backslash or with vertical bars:
|
||||
anywhere except in the first character of an identifier. When
|
||||
@litchar["@"] must appear as the first character of an identifier, you
|
||||
must quote the identifier just like other non-standard characters in
|
||||
normal S-expression syntax: with a backslash or with vertical bars.
|
||||
|
||||
@scribble-examples|==={
|
||||
(define \@email "foo@bar.com")
|
||||
|
@ -209,7 +237,7 @@ code). (More on using braces in body texts below.)
|
|||
}===|
|
||||
|
||||
Finally, remember that the Scribble is just an alternate for
|
||||
S-expressions --- identifiers still get their meaning, as in any
|
||||
S-expressions. Identifiers still get their meaning, as in any
|
||||
Scheme code, through the lexical context in which they appear.
|
||||
Specifically, when the above @"@"-form appears in a Scheme expression
|
||||
context, the lexical environment must provide bindings for
|
||||
|
@ -235,19 +263,8 @@ or bound locally (with @scheme[let], for example).
|
|||
@text{@it{Note}: @bf{This is @ul{not} a pipe}.}))
|
||||
]
|
||||
|
||||
When you first experiment with the Scribble syntax, it is often useful
|
||||
to use Scheme's @scheme[quote] to inspect how some concrete syntax is
|
||||
being read.
|
||||
|
||||
@; FIXME: unfortunate code duplication
|
||||
@interaction[
|
||||
(eval:alts
|
||||
#,(tt "'@foo{bar}")
|
||||
'@foo{bar})
|
||||
]
|
||||
|
||||
@;--------------------------------------------------------------------
|
||||
@subsection{The Command Part}
|
||||
@section{The Command Part}
|
||||
|
||||
Besides being a Scheme identifier, the @nonterm{cmd} part of an
|
||||
@"@"-form can have Scheme punctuation prefixes, which will end up
|
||||
|
@ -337,7 +354,7 @@ Finally, note that there are currently no special rules for using
|
|||
}===|
|
||||
|
||||
@;--------------------------------------------------------------------
|
||||
@subsection{The Datum Part}
|
||||
@section{The Datum Part}
|
||||
|
||||
The datum part can contains arbitrary Scheme expressions, which
|
||||
are simply stacked before the body text arguments:
|
||||
|
@ -374,7 +391,7 @@ keyword-value arguments that precede the body of text arguments.
|
|||
}===|
|
||||
|
||||
@;--------------------------------------------------------------------
|
||||
@subsection{The Body Part}
|
||||
@section{The Body Part}
|
||||
|
||||
The syntax of the body part is intended to be as convenient as
|
||||
possible for free text. It can contain almost any text---the only
|
||||
|
@ -440,7 +457,7 @@ of the text. This works for @litchar["@"] too:
|
|||
}===|
|
||||
|
||||
@;--------------------------------------------------------------------
|
||||
@subsubsub*section[#:tag "alt-body-syntax"]{Alternative Body Syntax}
|
||||
@subsection[#: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
|
||||
|
@ -486,7 +503,7 @@ to quote short pieces, and the above works well when you have larger
|
|||
multi-line body texts.
|
||||
|
||||
@;--------------------------------------------------------------------
|
||||
@subsubsub*section{Scheme Expression Escapes}
|
||||
@subsection{Scheme Expression Escapes}
|
||||
|
||||
In some cases, you may want to use a Scheme identifier (or a number or
|
||||
a boolean etc.) in a position that touches the following text; in
|
||||
|
@ -543,7 +560,7 @@ as the Scheme command part of a @"@"-form. The latter is used in this case
|
|||
}===|
|
||||
|
||||
@;--------------------------------------------------------------------
|
||||
@subsubsub*section{Comments}
|
||||
@subsection{Comments}
|
||||
|
||||
As noted above, there are two kinds of Scribble comments: @litchar|{@;{...}}| is
|
||||
a (nestable) comment for a whole body of text (following the same
|
||||
|
@ -569,7 +586,7 @@ Note how this is different from using @litchar["@||"]s in that strings
|
|||
around it are not merged.
|
||||
|
||||
@;--------------------------------------------------------------------
|
||||
@subsubsub*section{Spaces, Newlines, and Indentation}
|
||||
@subsection{Spaces, Newlines, and Indentation}
|
||||
|
||||
The Scribble syntax treats spaces and newlines in a special way is
|
||||
meant to be sensible for dealing with text. As mentioned above,
|
||||
|
@ -744,234 +761,6 @@ matter, you can begin (or end) a line with a "@||".
|
|||
@|| baz}
|
||||
}===|
|
||||
|
||||
@;--------------------------------------------------------------------
|
||||
@section{Syntax Properties}
|
||||
@; --------------------------------------------------
|
||||
@(close-eval read-eval)
|
||||
|
||||
The Scribble reader attaches properties to syntax objects. These
|
||||
properties might be useful in some rare situations.
|
||||
|
||||
Forms that Scribble reads are marked with a @scheme['scribble]
|
||||
property, and a value of a list of three elements: the first is
|
||||
@scheme['form], the second is the number of items that were read from
|
||||
the datum part, and the third is the number of items in the body part
|
||||
(strings, sub-forms, and escapes). In both cases, a @scheme[0] means
|
||||
an empty datum/body part, and @scheme[#f] means that the corresponding
|
||||
part was omitted. If the form has neither parts, the property is not
|
||||
attached to the result. This property can be used to give different
|
||||
meanings to expressions from the datum and the body parts, for
|
||||
example, implicitly quoted keywords:
|
||||
|
||||
@; FIXME: a bit of code duplication here
|
||||
@def+int[
|
||||
#:eval read-eval
|
||||
(define-syntax (foo stx)
|
||||
(let ([p (syntax-property stx 'scribble)])
|
||||
(printf ">>> ~s\n" (syntax->datum stx))
|
||||
(syntax-case stx ()
|
||||
[(_ x ...)
|
||||
(and (pair? p) (eq? (car p) 'form) (even? (cadr p)))
|
||||
(let loop ([n (/ (cadr p) 2)]
|
||||
[as '()]
|
||||
[xs (syntax->list #'(x ...))])
|
||||
(if (zero? n)
|
||||
(with-syntax ([attrs (reverse as)]
|
||||
[(x ...) xs])
|
||||
#'(list 'foo `attrs x ...))
|
||||
(loop (sub1 n)
|
||||
(cons (with-syntax ([key (car xs)]
|
||||
[val (cadr xs)])
|
||||
#'(key ,val))
|
||||
as)
|
||||
(cddr xs))))])))
|
||||
(eval:alts
|
||||
(code:line
|
||||
@#,tt["@foo[x 1 y (* 2 3)]{blah}"])
|
||||
;; Unfortunately, expressions are preserved by `def+int'
|
||||
;; using `quote', not `quote-syntax' (which would create all sorts
|
||||
;; or binding trouble), so we manually re-attach the property:
|
||||
(eval (syntax-property #'@foo[x 1 y (* 2 3)]{blah}
|
||||
'scribble '(form 4 1))))
|
||||
]
|
||||
|
||||
In addition, the Scribble parser uses syntax properties to mark syntax
|
||||
items that are not physically in the original source --- indentation
|
||||
spaces and newlines. Both of these will have a @scheme['scribble]
|
||||
property; an indentation string of spaces will have
|
||||
@scheme['indentation] as the value of the property, and a newline will
|
||||
have a @scheme['(newline S)] value where @scheme[S] is the original
|
||||
newline string including spaces that precede and follow it (which
|
||||
includes the indentation for the following item). This can be used to
|
||||
implement a verbatim environment: drop indentation strings, and use
|
||||
the original source strings instead of the single-newline string. Here
|
||||
is an example of this.
|
||||
|
||||
@; FIXME: a bit of code duplication here
|
||||
@def+int[
|
||||
#:eval read-eval
|
||||
(define-syntax (verb stx)
|
||||
(syntax-case stx ()
|
||||
[(_ cmd item ...)
|
||||
#`(cmd
|
||||
#,@(let loop ([items (syntax->list #'(item ...))])
|
||||
(if (null? items)
|
||||
'()
|
||||
(let* ([fst (car items)]
|
||||
[prop (syntax-property fst 'scribble)]
|
||||
[rst (loop (cdr items))])
|
||||
(cond [(eq? prop 'indentation) rst]
|
||||
[(not (and (pair? prop)
|
||||
(eq? (car prop) 'newline)))
|
||||
(cons fst rst)]
|
||||
[else (cons (datum->syntax-object
|
||||
fst (cadr prop) fst)
|
||||
rst)])))))]))
|
||||
(eval:alts
|
||||
(code:line
|
||||
@#,tt["@verb[string-append]{"]
|
||||
@#,tt[" foo"]
|
||||
@#,tt[" bar"]
|
||||
@#,tt["}"])
|
||||
@verb[string-append]{
|
||||
foo
|
||||
bar
|
||||
})
|
||||
]
|
||||
|
||||
@;--------------------------------------------------------------------
|
||||
@section[#:tag "at-exp-lang"]{Adding @"@"-expressions to a Language}
|
||||
|
||||
@defmodulelang[at-exp]{The @schememodname[at-exp] language installs
|
||||
@"@"-reader support in the readtable, and then chains to the reader of
|
||||
another language that is specified immediate after
|
||||
@schememodname[at-exp].}
|
||||
|
||||
For example, @scheme[@#,hash-lang[] at-exp scheme/base] adds @"@"-reader
|
||||
support to @scheme[scheme/base], so that
|
||||
|
||||
@schememod[
|
||||
at-exp scheme/base
|
||||
|
||||
(define (greet who) @#,elem{@tt["@"]@scheme[string-append]@schemeparenfont["{"]@schemevalfont{Hello, }@tt["@|"]@scheme[who]@tt["|"]@schemevalfont{.}@schemeparenfont["}"]})
|
||||
(greet "friend")]
|
||||
|
||||
reports @scheme["Hello, friend."].
|
||||
|
||||
@;--------------------------------------------------------------------
|
||||
@section{Interface}
|
||||
|
||||
@defmodule[scribble/reader]{The @schememodname[scribble/reader] module
|
||||
provides direct Scribble reader functionality for advanced needs.}
|
||||
|
||||
@; The `with-scribble-read' trick below shadows `read' and
|
||||
@; `read-syntax' with for-label bindings from the Scribble reader
|
||||
|
||||
@(define-syntax with-scribble-read
|
||||
(syntax-rules ()
|
||||
[(_)
|
||||
(...
|
||||
(begin
|
||||
(require (for-label scribble/reader))
|
||||
|
||||
@; *** Start reader-import section ***
|
||||
@defproc[(read [in input-port? (current-input-port)]) any]{}
|
||||
@defproc[(read-syntax [source-name any/c (object-name in)]
|
||||
[in input-port? (current-input-port)])
|
||||
(or/c syntax? eof-object?)]{
|
||||
These procedures implement the Scribble reader. They do so by
|
||||
constructing a reader table based on the current one, and using that
|
||||
for reading.
|
||||
}
|
||||
|
||||
@defproc[(read-inside [in input-port? (current-input-port)]) any]{}
|
||||
@defproc[(read-syntax-inside [source-name any/c (object-name in)]
|
||||
[in input-port? (current-input-port)])
|
||||
(or/c syntax? eof-object?)]{
|
||||
These @schemeid[-inside] variants parse as if starting inside a
|
||||
@litchar["@{"]...@litchar["}"], and they return a (syntactic) list.
|
||||
Useful for implementing languages that are textual by default (see
|
||||
@filepath{docreader.ss} for example).
|
||||
}
|
||||
|
||||
@defproc[(make-at-readtable
|
||||
[#:readtable readtable readtable? (current-readtable)]
|
||||
[#:command-char command-char character? #\@]
|
||||
[#:datum-readtable datum-readtable
|
||||
(or/c readtable? boolean?
|
||||
(readtable? . -> . readtable?))
|
||||
#t]
|
||||
[#:syntax-post-processor syntax-post-proc
|
||||
(syntax? . -> . syntax?)
|
||||
values])
|
||||
readtable?]{
|
||||
|
||||
Constructs an @"@"-readtable. The keyword arguments can customize the
|
||||
resulting reader in several ways:
|
||||
|
||||
@itemize[
|
||||
|
||||
@item{@scheme[readtable] --- a readtable to base the @"@"-readtable
|
||||
on.}
|
||||
|
||||
@item{@scheme[command-char] --- the character used for @"@"-forms.}
|
||||
|
||||
@item{@scheme[datum-readtable] --- determines the readtable used for
|
||||
reading the datum part. A @scheme[#t] values uses the
|
||||
@"@"-readtable, otherwise it can be a readtable, or a
|
||||
readtable-to-readtable function that will construct one from the
|
||||
@"@"-readtable. The idea is that you may want to have completely
|
||||
different uses for the datum part, for example, introducing a
|
||||
convenient @litchar{key=val} syntax for attributes.}
|
||||
|
||||
@item{@scheme[syntax-post-proc] --- function that is applied on
|
||||
each resulting syntax value after it has been parsed (but before it
|
||||
is wrapped quoting punctuations). You can use this to further
|
||||
control uses of @"@"-forms, for example, making the command be the
|
||||
head of a list:
|
||||
|
||||
@schemeblock[
|
||||
(use-at-readtable
|
||||
#:syntax-post-processor
|
||||
(lambda (stx)
|
||||
(syntax-case stx ()
|
||||
[(cmd rest ...) #'(list 'cmd rest ...)]
|
||||
[_else (error "@ forms must have a body")])))
|
||||
]}
|
||||
|
||||
]}
|
||||
|
||||
@defproc[(make-at-reader [#:syntax? syntax? #t] [#:inside? inside? #f] ...)
|
||||
procedure?]{
|
||||
Constructs a variant of a @"@"-readtable. The arguments are the same
|
||||
as in @scheme[make-at-readtable], with two more that determine the
|
||||
kind of reader function that will be created: @scheme[syntax?] chooses
|
||||
between a @scheme[read]- or @scheme[read-syntax]-like function, and
|
||||
@scheme[inside?] chooses a plain reader or an @schemeid[-inside]
|
||||
variant.
|
||||
|
||||
The resulting function has a different contract and action based on
|
||||
these inputs. The expected inputs are as in @scheme[read] or
|
||||
@scheme[read-syntax] depending on @scheme[syntax?]; the function will
|
||||
read a single expression or, if @scheme[inside?] is true, the whole
|
||||
input; it will return a syntactic list of expressions rather than a
|
||||
single one in this case.
|
||||
|
||||
Note that @scheme[syntax?] defaults to @scheme[#t], as this is the
|
||||
more expected common case when you're dealing with concrete-syntax
|
||||
reading.
|
||||
|
||||
Note that if @scheme[syntax?] is true, the @scheme[read]-like function
|
||||
is constructed by simply converting a syntax result back into a datum.}
|
||||
|
||||
@defproc[(use-at-readtable ...) void?]{
|
||||
|
||||
Passes all arguments to @scheme[make-at-readtable], and installs the
|
||||
resulting readtable using @scheme[current-readtable]. It also enables
|
||||
line counting for the current input-port via @scheme[port-count-lines!].
|
||||
|
||||
This is mostly useful for playing with the Scribble syntax on the REPL.}
|
||||
|
||||
@; *** End reader-import section ***
|
||||
))]))
|
||||
@with-scribble-read[]
|
||||
|
||||
|
||||
|
|
|
@ -2,14 +2,16 @@
|
|||
@(require scribble/bnf
|
||||
"utils.ss")
|
||||
|
||||
@title{@bold{Scribble}: PLT Documentation Tools}
|
||||
@title{@bold{Scribble}: PLT Documentation Tool}
|
||||
|
||||
@author["Matthew Flatt" "Eli Barzilay"]
|
||||
|
||||
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.
|
||||
Scribble is a collection of tools for creating prose
|
||||
documents---papers, books, library documentation, etc.---in HTML or
|
||||
PDF (via Latex) form. More generally, Scribble helps you write
|
||||
programs that are rich in textual content, whether the content is
|
||||
prose to be typeset or some other form of text to be generated
|
||||
programmatically.
|
||||
|
||||
This document itself is written using Scribble. At the time that it
|
||||
was written, its source was available at
|
||||
|
@ -20,7 +22,8 @@ starting with the @filepath{scribble.scrbl} file.
|
|||
@table-of-contents[]
|
||||
|
||||
@; ------------------------------------------------------------------------
|
||||
@include-section["getting-started.scrbl"]
|
||||
@include-section["how-to-paper.scrbl"]
|
||||
@include-section["reader.scrbl"]
|
||||
@include-section["generic.scrbl"]
|
||||
@include-section["plt.scrbl"]
|
||||
@include-section["lp.scrbl"]
|
||||
|
|
|
@ -2,13 +2,7 @@
|
|||
@(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}
|
||||
@title{SIGPLAN Paper Format}
|
||||
|
||||
@defmodulelang[scribble/sigplan]{The @schememodname[scribble/sigplan]
|
||||
language is like @schememodname[scribble/manual], but configured with
|
Loading…
Reference in New Issue
Block a user