#lang scribble/doc @(require "common.ss") @title[#:tag "scheme"]{Typesetting Code} We have so far concentrated on Scribble's support for writing text, but typesetting code is equally important for documentation. Code appears in several different contexts: @itemize[ @item{API documentation refers to contracts (or types) that are defined elsewhere.} @item{Example code uses bindings that may be defined far from the example.} @item{Prose refers to bindings that are defined elsewhere.} ] In all cases, Scribble supports automatic styling of Scheme program text based on the syntactic role of each code fragment. Example code typically uses the @scheme[schemeblock] form to create a block, while inline code within a paragraph uses the @scheme[scheme] form to create an element. API documentation uses more complex forms, such as @scheme[defproc], which accepts information about the expected and returned values and expands to uses of @scheme[scheme] within a table. We prefer to read code in typewriter font, so the default configuration mostly uses color to distinguish syntactic categories: green for strings like @scheme["hello"], black for syntactic forms like @scheme[define], bright blue for defined variables like @scheme[cons], dark blue for free variables like @scheme[undefined], and brown for ambient delimiters like the parentheses in @scheme[(+ 1 2)]. Syntactic form names, defined names, and free names are all just identifiers in the source, but @scheme[scheme] and @scheme[schemeblock] need to distinguish them for typesetting. One way to distinguish different identifiers is to have a programmer enumerate different sets of bindings. For example, the @|slatex|@~cite["slatex"] pre-processor for @|latex| relies on @tt{defkeyword} and @tt{defconstant} declarations to identify syntactic forms and constants: @verbatim[#:indent 2]{ \documentclass{article} \usepackage{slatex} \defkeyword{define} \defconstant{string-append} .... \begin{schemedisplay} (define (louder s) (string-append s "!")) \end{schemedisplay} } In this mode, the author of a work in progress must constantly add another ``standard'' binding to @|slatex|'s list. Actually, @|slatex| includes @tt{define} in its built-in table of syntactic forms, but the table is small compared to the number of syntactic forms available in PLT Scheme. More generally, the problem is the usual one for ``standards'': there are many to choose from. Scribble gives the document author a simple way to declare which bindings are relevant. Furthermore, the mechanism is one that the document author already knows, because it's the same as the mechanism for introducing bindings for code. The only difference is an extra @scheme[for-label] around the import, which indicates that the module's bindings should be made visible for typesetting instead of direct calls: @code-block|{ #lang scribble/doc .... @(require (for-label htdp-langs/beginner)) @schemeblock[ (define (louder s) (string-append s "!")) ] }| A module that is imported only with @scheme[for-label] is @emph{not} run when the documentation is built, because the time at which a document is built may not be a suitable time to actually run a module. As an extreme example, an author might want to document a module whose job is to erase all files on the disk. More practically, executing a GUI library might require a graphics terminal, while the documentation for the graphics library might be built using only a text terminal. When a large document source is split into multiple modules, most of the modules need the same basic typesetting functions as well as the same ``standard'' bindings for examples. In Scribble, both sets of bindings can be packaged together; since @scheme[for-label] declarations build on the module system's import mechanisms, they work with the module system's re-exporting mechanisms. For example, the documentation for a library that builds on the @schememodname[scheme/base] library might use a @filepath{common.ss} library: @code-block{ #lang scheme/base (require scribble/manual (for-label htdp-langs/beginner)) (provide (all-from-out scribble/manual) (for-label (all-from-out htdp-langs/beginner))) } Then, each part of the document can be implemented as @code-block|{ #lang scribble/doc @(require "common.ss") .... }| instead of separately requiring @schememodname[scribble/manual] and @schememodname[(for-label scribble/base)] in every file. In addition to adjusting the typesetting style of code to reflect its syntactic role, every syntactic form and defined variable in a code fragment is hyperlinked to its specification. The @scheme[for-label] imports of a document play a crucial role in ensuring that the hyperlink goes to the appropriate documentation: @scheme[(for-label scheme/base)] means that uses of @scheme[lambda] will be hyperlinked to the documentation for PLT Scheme's primary dialect of Scheme, whereas @scheme[(for-label htdp-langs/beginner)] means that uses of @htdp-lambda[] will be hyperlinked to the documentation for one of the pedagogic dialects. If a document (such as this one) needs to refer to both bindings, then one of the references can be given a different context. One simple way to get a different context is to import the document fragment from a module that uses a different context: @code-block{ ;; In htdp-lambda.ss: #lang scheme/base (require scribble/manual (for-label htdp-langs/beginner)) (provide htdp-lambda) (define (htdp-lambda) ;; Bound to htdp-langs/beginner: (scheme lambda)) } @code-block|{ ;; In doc.scrbl: #lang scribble/doc (require scribble/manual (for-label scheme/base) "htdp-lambda.ss") Compare the core @scheme[lambda] to the pedagogic @htdp-lambda[]. }| PLT Scheme's macro system is also powerful enough to implement local @scheme[for-label] bindings without resorting to a separate module, but the syntax is more complicated. Pervasive and precise hyperlinking of identifiers greatly improves the quality of documentation, and it relieves a document author from much tedious cross-referencing work. The author need not specify where @scheme[lambda] is documented, but instead merely import module that supplies @scheme[lambda], and the documentation system is responsible for correlating the use and the definition. Furthermore, since hyperlinks are used in examples everywhere, an author can expect readers to follow them, instead of explicitly writing ``for more information on the @scheme[lambda] form used above, see ...'' The @scheme[scheme] and @scheme[schemeblock] forms work only on PLT Scheme's core S-expression syntax. Since the code in this paper uses many Scribble extensions, it is written with more general @scheme[code-element] and @scheme[code-block] forms, which accept a text-mode to parse; the layout of the source text is used for the typeset layout, while the parser-generated S-expression is used to correlate source text with syntactic roles for coloring and hyperlinking.