1 How to Scribble Documentation
Although the scribble command-line utility generates output from a Scribble document (run scribble -h for more information), documentation of PLT Scheme libraries is normally built by setup-plt. This chapter emphasizes the setup-plt approach, which more automatically supports links across documents.
1.1 Getting Started
To document a collection or PLaneT package:
Create a file in your collection or planet package with the file extension ".scrbl". Beware that the file name you choose will determine the output directory’s name. The remainder of these instructions assume that the file is called "manual.scrbl".
Start "manual.scrbl" like this:
#lang scribble/doc
@(require 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 @ syntax to use Scheme bindings. The second line introduces bindings like title and scheme for writing PLT Scheme documentation. The title call (using @) produces a title declaration in the text stream.
Add the following entry to your collect or package’s "info.ss":
(define scribblings '(("manual.scrbl" ())))
The () above is a list of options. When your document gets large enough that you want it split into multiple pages, add the 'multi-page option (omitting the quote, since the whole right-hand side of the definition is already quoted).
If you do not already have an "info.ss" module, here’s a suitable complete module:
(define scribblings '(("manual.scrbl" ())))
Run setup-plt to build your documentation. For a collection, optionally supply -l followed by the collection name to limit the build process to that collection. For a PLaneT package, optionally supply -P followed by the package information to limit the build process to that package.
The generated documentation is normally "doc/manual/index.html" within the collection or PLaneT package directory. If the collection is in PLT Scheme’s main "collects" directory, however, then the documentation is generated as "manual/index.html" in the installation’s main "doc" directory.
1.2 Document Syntax
Whether in “text” mode or Scheme mode, @ in a document provides an escape to Scheme mode. The syntax of @ is
@ 〈cmd〉 [ 〈datum〉* ] { 〈text-body〉 }
where all three parts after @ are optional, but at least one must be present. No spaces are allowed between
@ and 〈cmd〉, [, or {
〈cmd〉 and [ or {; or
] and {.
A 〈cmd〉 or 〈datum〉 is a Scheme datum, while a 〈text-body〉 is itself in text mode.
The expansion of @〈cmd〉 into Scheme code is
〈cmd〉
When either [ ] or { } are used, the expansion is
(〈cmd〉 〈datum〉* 〈parsed-body〉*)
where 〈parsed-body〉* is the parse result of the 〈text-body〉. The 〈parsed-body〉* part often turns out to be a sequence of Scheme strings.
In practice, the 〈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 { } supplies the text. If the form expects other data, typically [ ] is used to surround Scheme arguments, instead. Sometimes, both [ ] and { } are used, where the former surround Scheme arguments that precede text to typeset.
Thus,
@(require scribble/manual) |
@title{My Library} |
@scheme[(list 'testing 1 2 3)] |
@section[#:tag "here"]{You Are Here} |
means
(require scribble/manual) |
(title "My Library") |
(section #:tag "here" "You Are Here") |
For more information on the syntax of @, see @-Reader.
In a document that starts #lang scribble/doc, the top level is a text-mode sequence, as the 〈text-body〉 in a @ form. The parsed sequence is further decoded to turn it into a hierarchy of sections and paragraphs. For example, a linear sequence of section declarations with interleaved text is turned into a list of part instances with all text assigned to a particular part. See Scribble Layers for more information on these layers.
1.3 Scheme Typesetting and Hyperlinks
In the document source at the start of this chapter (Getting Started), the Scheme expression (list 'testing 1 2 3) is typeset properly, but the list identifier is not hyperlinked to the usual definition. To cause list to be hyperlinked, extend the require form like this:
(require scribble/manual |
This require with for-label declaration introduces a document-time binding for each export of the scheme module. When the document is built, the scheme form detects the binding for list, and so it generates a reference to the specification of list. The setup process detects the reference, and it finds the matching specification in the existing documentation, and ultimately directs the hyperlink to that specification.
Hyperlinks based on for-label and scheme are the preferred mechanism for linking to information outside of a single document. Such links require no information about where and how a binding is documented elsewhere:
#lang scribble/doc |
@(require scribble/manual |
(for-label scheme)) |
|
@title{My Library} |
|
See also @scheme[list]. |
The scheme form typesets a Scheme expression for inline text, so it ignores the source formatting of the expression. The schemeblock form, in contrast, typesets inset Scheme code, and it preserves the expression’s formatting from the document source.
#lang scribble/doc |
@(require scribble/manual |
(for-label scheme)) |
|
@title{My Library} |
|
Some example Scheme code: |
|
@schemeblock[ |
(define (nobody-understands-me what) |
(list "When I think of all the" |
what |
"I've tried so hard to explain!")) |
(nobody-understands-me "glorble snop") |
] |
1.4 Section Hyperlinks
A section declaration in a document can include a #:tag argument that declares a hyperlink-target tag. The secref function generates a hyperlink, using the section name as the text of the hyperlink. Use seclink to create a hyperlink with text other than the section title.
The following example illustrates section hyperlinks:
#lang scribble/doc |
@(require scribble/manual |
(for-label scheme)) |
|
|
@title{My Library} |
|
Welcome to my documentation: @scheme[(list 'testing 1 2 3)]. |
|
@table-of-contents[] |
|
|
@section[#:tag "chickens"]{Philadelphia Chickens} |
|
Dancing tonight! |
|
|
@section{Reprise} |
|
See @secref{chickens}. |
Since the page is so short, the hyperlinks in the above example are more effective if you change the "info.ss" file to add the 'multi-file flag:
(define scribblings '(("manual.scrbl" (multi-page))))
A section can have a tag prefix that applies to all tags as seen from outside the section. Such a prefix is automatically given to each top-level document as processed by setup-plt. Thus, referencing a section tag in a different document requires using a prefix, which is based on the target document’s main source file. The following example links to a section in the PLT Scheme reference manual:
#lang scribble/doc |
@(require scribble/manual |
(for-label scheme)) |
@(define ref-src |
'(lib "scribblings/reference/reference.scrbl")) |
|
@title{My Library} |
|
See also @italic{@secref[#:doc ref-src]{pairs}}. |
As mentioned in Scheme Typesetting and Hyperlinks, however, cross-document references based on (require (for-label ....)) and scheme are usually better than cross-document references using secref.
1.5 Defining Scheme Bindings
Use defproc to document a procedure, defform to document a syntactic form, defstruct to document a structure type, etc. These forms provide consistent formatting of definitions, and they declare hyperlink targets for scheme-based hyperlinks.
To document a my-helper procedure that is exported by "helper.ss" in the "my-lib" collection that contains "manual.scrbl":
Use (require (for-label "helper.ss")) to import the binding information about the bindings of "helper.ss" for use when typesetting identifiers. A relative reference "helper.ss" works since it is relative to the documentation source.
Add a @defmodule[my-lib/helper] declaration, which specifies the library that is being documented within the section. The defmodule form needs an absolute module name mylib/helper, instead of a relative reference "helper.ss", since the module path given to defmodule appears verbatim in the generated documentation.
Use defproc to document the procedure.
Adding these pieces to ""manual.scrbl"" gives us the following:
#lang scribble/doc |
@(require scribble/manual |
(for-label scheme |
"helper.ss")) |
|
@title{My Library} |
|
@defmodule[my-lib/helper] |
|
@defproc[(my-helper [lst list?]) |
(listof |
(not/c (one-of/c 'cow)))]{ |
|
Replaces each @scheme['cow] in @scheme[lst] with |
@scheme['aardvark].} |
In defproc, a contract is specified with each argument to the procedure. In this example, the contract for the lst argument is list?, which is the contract for a list. After the closing parenthesis that ends the argument sequence, the contract of the result must be given; in this case, my-helper guarantees a result that is a list where none of the elements are 'cow.
Some things to notice in this example and the documentation that it generates:
The list?, listof, etc. elements of contracts are hyperlinked to their documentation.
The result contract is formatted in the generated documentation in the same way as in the source. That is, the source layout of contracts is preserved. (In this case, putting the contract all on one line would be better.)
In the prose that documents my-helper, lst is automatically typeset in italic, matching the typesetting in the blue box. The scheme form essentially knows that it’s used in the scope of a procedure with argument lst.
If you hover the mouse pointer over my-helper, a popup reports that it is provided from my-lib/helper.
If you use my-helper in any documentation now, as long as that documentation source also has a (require (for-label ....)) of "helper.ss", then the reference is hyperlinked to the definition above.
See defproc*, defform, etc. for more information on forms to document Scheme bindings.
1.6 Showing Scheme Examples
The examples form from scribble/eval helps you generate examples in your documentation. Warning: the examples form is especially likely to change or be replaced.
To use examples, the procedures to document must be suitable for use at documentation time; in fact, examples uses bindings introduced into the document source by require. Thus, to generate examples using my-helper from the previous section, "helper.ss" must be imported both via require-for-label and require:
#lang scribble/doc |
@(require scribble/manual |
scribble/eval ; <--- added |
"helper.ss" ; <--- added |
(for-label scheme |
"helper.ss")) |
|
@title{My Library} |
|
@defmodule[my-lib/helper]{The @schememodname[my-lib/helper] |
module---now with extra cows!} |
|
@defproc[(my-helper [lst list?]) |
(listof (not/c (one-of/c 'cow)))]{ |
|
Replaces each @scheme['cow] in @scheme[lst] with |
@scheme['aardvark]. |
|
@examples[ |
(my-helper '()) |
(my-helper '(cows such remarkable cows)) |
]} |
1.7 Splitting the Document Source
In general, a ".scrbl" file produces a part. A part produced by a document’s main source (as specified in the "info.ss" file) represents the whole document. The include-section procedure can be used to incorporate a part as a sub-part of the enclosing part.
In "manual.scrbl":
#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 "cows.scrbl":
#lang scribble/doc |
@(require scribble/manual) |
|
@title{Cows} |
|
Wherever they go, it's a quite a show. |
In "aardvarks.scrbl":
#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].} |
1.8 Multi-Page Sections
Setting the 'multi-page option (see Section Hyperlinks) causes each top-level section of a document to be rendered as a separate HTML page.
To push sub-sections onto separate pages, use the 'toc style for the enclosing section (as started by title, section, subsection, etc.) and use local-table-of-contents to generate hyperlinks to the sub-sections.
Revising "cows.scrbl" from the previous section:
#lang scribble/doc |
@(require scribble/manual) |
|
@title[#:style '(toc)]{Cows} |
|
@local-table-of-contents[] |
|
@section[#:tag "singing"]{Singing} |
Wherever they go, it's a quite a show. |
|
@section{Dancing} |
See @secref["singing"]. |
To run this example, remember to change "info.ss" to add the 'multi-page style. You may also want to add a call to table-of-contents in "manual.scrbl".
The difference between table-of-contents and local-table-of-contents is that the latter is ignored for Latex output.
When using local-table-of-contents, it often makes sense to include introductory text before the call of local-table-of-contents. When the introductory text is less important and when when local table of contents is short, putting the introductory text after the call of local-table-of-contents may be appropriate.
1.9 Style Guide
1.9.1 Prose and Terminology
In the descriptive body of defform, defproc, etc., do not start with “This ...” Instead, start with a sentence whose implicit subject is the form or value being described. Capitalize the first word. Thus, the description will often start with “Returns” or “Produces.” Refer to arguments and sub-forms by name.
Do not use the word “argument” to describe a sub-form in a syntactic form; use the term “sub-form” instead, reserving “argument” for values or expressions in a function call. Refer to libraries and languages as such, rather than as “modules” (even though the form to typeset a library or language name is called schememodname). Do not call an identifier (i.e., a syntactic element) a “variable” or a “symbol.” Do not use the word “expression” for a form that is a definition or might be a definition; use the word “form,” instead. Prefer “function” to “procedure.”
Avoid cut-and-paste for descriptive text. If two functions are similar, consider documenting them together with deftogether. To abstract a description, consider using explicit prose abstraction, such as “x is like y, except that ...,” instead of abstracting the source and instantiating it multiple times; often, a prose abstraction is clearer to the reader than a hidden abstraction in the document implementation.
1.9.2 Typesetting Code
Use id or a name that ends -id in defform to mean an identifier, not identifier, variable, name, or symbol. Similarly, use expr or something that ends -expr for an expression position within a syntactic form. Use body for a form (definition or expression) in an internal-definition position. Do not use expr for something that isn’t exactly an expression, id for something that isn’t exactly an identifier, etc.; instead, use defform/subs to define a new non-terminal.
Beware of using deftogether to define multiple variants of a syntactic form or procedure, because each defform or defproc creates a definition point, but each form or procedure should have a single definition point. (Scribble issues a warning when a binding has multiple definition points.) Instead, use defproc* or defform*.
Pay attention to the difference between identifiers and meta-variables when using scheme, especially outside of defproc or defform. Prefix a meta-variable with _; for example,
@scheme[(rator-expr rand-expr ...)] |
would be the wrong way to refer to the grammar of a function call, because it produces (rator-expr rand-expr ...), where rator-expr and rand-expr are typeset as variables. The correct description is
@scheme[(_rator-expr _rand-expr ...)] |
which produces (rator-expr rand-expr ...), where rator-expr and rand-expr are typeset as meta-variables. The defproc, defform, etc. forms greatly reduce this burden in descriptions, since they automatically set up meta-variable typesetting for non-literal identifiers. In defform, be sure to include literal identifiers (i.e., those not meant as variables, other than the form name being defined) in a #:literals clause.
To typeset an identifier with no particular interpretation – syntax, variable, meta-variable, etc. – use schemeidfont (e.g., as in rand-expr above). Otherwise, use litchar, not merely schemefont or verbatim, to refer to a specific sequence of characters.
When showing example evaluations, use the REPL-snapshot style:
@interaction[ |
(+ 1 2) |
] |
See also the scribble/eval library.
Use four dots, ...., in place of omitted code, since ... means repetition.
1.9.3 Typesetting Prose
Refrain from referring to documentation “above” or “below,” and instead have a hyperlink point to the right place.
In prose, use `` and '' quotation marks instead of ". Use --- for an em-dash, and do not include spaces on either side, though it will typeset as an en-dash and spaces in HTML output. Use American style for quotation marks and punctuation at the end of quotation marks (i.e., a sentence-terminating period goes inside the quotation marks). Of course, this rule does not apply for quotation marks that are part of code.
Do not use a citation reference (as created by cite) as a noun; use it as an annotation.
Do not start a sentence with a Scheme variable name, since it is normally lowercase. For example, use “The thing argument is...” instead of “thing is...”
1.9.4 Section Titles
Capitalize all words except articles (“the,” “a,” etc.), prepositions, and conjunctions that are not at the start of the title.
A manual title should normally start with a suitable keyword or key phrase (such as “Scribble” for this manual) that is in boldface. If the key word is primarily an executable name, use exec instead of bold. Optionally add further descriptive text in the title after a colon, where the text starting with the colon is not in boldface.