4.2.1 Typesetting Code
The codeblock and code forms (see #lang-Specified Code) typeset code verbatim, adding a layer of color to the code based on the same syntax-coloring parsers that are used by DrRacket. Input that is parsed as an identifier is further given a lexical context and hyperlinked via for-label imports.
The racketblock and racket forms (see Racket Code) typeset S-expression code roughly verbatim, but roughly by quoting the source term with syntax. Identifiers in the quoted S-expression are hyperlinked via for-label imports.
The two different approaches to typesetting code—
The codeblock and code forms work with non-S-expression syntax, and they give authors more control over output (e.g., the literal number 2/4 is not normalized to 1/2). The codeblock and code forms do not yet support escapes to Scribble element mode, and they cannot adapt spacing based on the width of elements in escapes.
The racketblock and racket forms are more efficient and allow escapes to Scribble element mode. The racketblock and racket forms are tied to S-expression syntax, however, and they are based on a syntax representation that tends to normalize source terms (e.g., the literal number 2/4 is normalized to 1/2).
4.2.1.1 #lang-Specified Code
syntax
(codeblock option ... str-expr ...+)
option = #:keep-lang-line? keep-expr | #:indent indent-expr | #:expand expand-expr | #:context context-expr | #:line-numbers line-number-expr | #:line-number-sep line-number-sep-expr
keep-expr : any/c
indent-expr : exact-nonnegative-integer?
expand-expr : (or/c #f (syntax? . -> . syntax?))
context-expr : (or/c #f syntax?)
line-number-expr : (or/c #f exact-nonnegative-integer?)
line-number-sep-expr : exact-nonnegative-integer?
The str-exprs should normally start with #lang to
determine the reader syntax for the module, but the resulting
“module” need not expand or compile—
When keep-expr produces a true value (the default), the first line in the input (which is typically #lang) is preserved in the typeset output, otherwise the first line is dropped. The typeset code is indented by the amount specified by indent-expr, which defaults to 0.
When expand-expr produces #f (which is the default), identifiers in the typeset code are colored and linked based on for-label bindings in the lexical environment of the syntax object provided by context-expr. The default context-expr has the same lexical context as the first str-expr. When line-number-expr is true, line number is enabled starting from line-number-expr, and line-number-sep-expr controls the separation (in spaces; defaults to 1) between the line numbers and code.
When expand-expr produces a procedure, it is used to macro-expand the parsed program, and syntax coloring is based on the parsed program.
For example,
@codeblock|{ #lang scribble/manual @codeblock{ #lang scribble/manual @title{Hello} } }|
produces the typeset result
#lang scribble/manual @codeblock{ #lang scribble/manual @title{Hello} }
syntax
(codeblock0 option ... str-expr ...+)
syntax
(code option ... str-expr ...+)
option = #:lang lang-line-expr | #:expand expand-expr | #:context context-expr
lang-line-expr : (or/c #f string?)
expand-expr : (or/c #f (syntax? . -> . syntax?))
context-expr : (or/c #f syntax?)
For example,
This is @code[#:lang "at-exp racket"]|{@bold{Hi}}|'s result: @bold{Hi}.
produces the typeset result
This is @bold{Hi}’s result: Hi.
procedure
(typeset-code [ #:context context #:expand expand #:indent indent #:keep-lang-line? keep? #:line-numbers line-numbers #:line-number-sep line-number-sep #:block? return-block?] strs ...) → (if return-block? block? element?) context : (or/c #f syntax?) = #f expand : (or/c #f (syntax? . -> . syntax?)) = #f indent : exact-nonnegative-integer? = 2 keep? : any/c = #t line-numbers : (or/c #f exact-nonnegative-integer?) = #f line-number-sep : exact-nonnegative-integer? = 1 return-block? : any/c = #t strs : string?
Unlike codeblock, the default context argument (#f) implies that the context is untouched and the return-block? argument determines the result structure. The other arguments are treated the same way as codeblock.
4.2.1.2 Racket Code
syntax
(racketblock maybe-escape datum ...)
maybe-escape =
| #:escape escape-id
(racketblock (define (loop x) (loop (not x))))
produces the output
(define (loop x) (loop (not x)))
with the (loop (not x)) indented under define, because that’s the way it is idented the use of racketblock. Source-location span information is used to preserve #true versus #t and #false versus #f; span information is also used heuristically to add #i to the start of an inexact number if its printed form would otherwise be two characters shorter than the source; syntax-object properties are used to preserve square brackets and curly braces versus parentheses; otherwise, using syntax objects tends to normalize the form of S-expression elements, such as rendering 2/4 as 1/2. When source-location information is not available, such as when it is lost by bytecode-compiled macros, spacing is inserted in the same style (within a single line) as the racket form.
See also quote-syntax/keep-srcloc for use in a macro to preserve source-location information in a template.
In the above example, define is typeset as a keyword (in black) and as a hyperlink to define’s definition in the reference manual, because this document was built using a for-label binding of define (in the source) that matches a definition in the reference manual. Similarly, not is a hyperlink to its definition in the reference manual.
Like other forms defined via define-code, racketblock expands identifiers that are bound as element transformers.
An #:escape clause specifies an identifier to escape back to an expression that produces an element. By default, the escape identifier is unsyntax. For example,
(racketblock (+ 1 #,(elem (racket x) (subscript "2"))))
produces
(+ 1 x2)
The escape-id that defaults to unsyntax is recognized via free-identifier=?, so a binding can hide the escape behavior:
(racketblock (let ([unsyntax #f]) (racketblock #'(+ 1 #,x))))
The RACKETBLOCK form’s default escape is UNSYNTAX instead of unsyntax.
A few other escapes are recognized symbolically:
(code:line datum ...) typesets as the sequence of datums (i.e., without the code:line wrapper).
(code:comment content) typesets like content, but colored as a comment and prefixed with a semi-colon. A typical content escapes from Racket-typesetting mode using unsyntax and produces a string, an element using elem, or a paragraph using t:
(code:comment @#,elem{this is a comment})
(Note that @#,foo{...} reads as #,(foo "...").)
(code:contract datum ...) typesets like the sequence of datums (including its coloring), but prefixed with a semi-colon.
(code:hilite datum) typesets like datum, but with a background highlight.
(code:quote datum) typesets like (quote datum), but without rendering the quote as '.
_id typesets as id, but colored as a variable (like racketvarfont); this escape applies only if _id has no for-label binding and is not specifically colored as a subform non-terminal via defform, a variable via defproc, etc.
See also scribble/comment-reader.
Changed in version 1.9 of package scribble-lib: Added heuristic for adding #i to inexact numbers.
syntax
(RACKETBLOCK maybe-escape datum ...)
syntax
(racketblock0 maybe-escape datum ...)
syntax
(RACKETBLOCK0 maybe-escape datum ...)
syntax
(racketresultblock maybe-escape datum ...)
syntax
(racketresultblock0 maybe-escape datum ...)
syntax
(RACKETRESULTBLOCK maybe-escape datum ...)
syntax
(RACKETRESULTBLOCK0 maybe-escape datum ...)
Unlike racketblock, racketresultblock and RACKETRESULTBLOCK implement indentation by adding an (hspace 2) to the start of each line, instead of using nested with the 'code-inset style. To get formatting more like racketblock and racketinput, use (nested #:style 'code-inset (racketresultblock0 datum ...)) instead of (racketresultblock datum ...).
syntax
(racketinput maybe-escape datum ...)
syntax
(RACKETINPUT maybe-escape datum ...)
syntax
(racketinput0 maybe-escape datum ...)
syntax
(RACKETINPUT0 maybe-escape datum ...)
syntax
(racketmod maybe-file maybe-escape lang datum ...)
maybe-file =
| #:file filename-expr maybe-escape =
| #:escape escape-id
The source location of lang (relative to the body datums) determines the relative positioning of the #lang line in the typeset output. So, line up lang with the left end of the content code.
If #:file is provided, then the code block is typeset using filebox with filename-expr as the filename argument.
syntax
(racketmod0 maybe-file maybe-escape lang datum ...)
syntax
(racket maybe-escape datum ...)
syntax
(RACKET maybe-escape datum ...)
syntax
(racketresult maybe-escape datum ...)
syntax
(racketid maybe-escape datum ...)
syntax
(schemeblock maybe-escape datum ...)
syntax
(SCHEMEBLOCK maybe-escape datum ...)
syntax
(schemeblock0 maybe-escape datum ...)
syntax
(SCHEMEBLOCK0 maybe-escape datum ...)
syntax
(schemeinput maybe-escape datum ...)
syntax
(schememod lang maybe-escape datum ...)
syntax
(scheme maybe-escape datum ...)
syntax
(SCHEME maybe-escape datum ...)
syntax
(schemeresult maybe-escape datum ...)
syntax
(schemeid maybe-escape datum ...)
4.2.1.3 Preserving Comments
#reader scribble/comment-reader | package: scribble-lib |
As a reader module, scribble/comment-reader reads a single S-expression that contains ;-based comment lines, and it wraps the comments with code:comment for use with forms like racketblock. More precisely, scribble/comment-reader extends the current reader to adjust the parsing of ;.
For example, within a Scribble document that imports scribble/manual,
@#reader scribble/comment-reader |
(racketblock |
;; This is not a pipe |
(make-pipe) |
) |
generates
; This is not a pipe (make-pipe)
The initial @ is needed above to shift into S-expression mode, so that #reader is recognized as a reader declaration instead of literal text. Also, the example uses (racketblock ....) instead of @racketblock[....] because the @-reader would drop comments within the racketblock before giving scribble/comment-reader a chance to convert them.
The implementation of scribble/comment-reader uses unsyntax to typeset comments. When using scribble/comment-reader with, for instance, RACKETBLOCK, unsyntax does not escape, since RACKETBLOCK uses UNSYNTAX as its escape form. You can declare an escape identifier for scribble/comment-reader with #:escape-id. For example,
@#reader scribble/comment-reader #:escape-id UNSYNTAX |
(RACKETBLOCK |
(define-syntax (m stx) |
(syntax-case stx () |
[(_ x) |
;; Well this was silly |
#`(#,x)])) |
) |
generates
(define-syntax (m stx) (syntax-case stx () [(_ x) ; Well this was silly #`(#,x)]))
4.2.1.4 Code Fonts and Styles
syntax
(racketmodname datum maybe-indirect)
(racketmodname (unsyntax expr) maybe-indirect)
maybe-indirect =
| #:indirect
If #:indirect is specified, then the hyperlink is given the 'indirect-link style property, which makes the hyperlink’s resolution in HTML potentially delayed; see 'indirect-link for link-element.
Changed in version 1.21 of package scribble-lib: Disabled racket-style special treatment of identifiers.
syntax
(racketmodlink datum pre-content-expr ...)
procedure
(racketfont pre-content ...) → element?
pre-content : pre-content?
procedure
(racketplainfont pre-content ...) → element?
pre-content : pre-content?
Added in version 1.6 of package scribble-lib.
procedure
(racketvalfont pre-content ...) → element?
pre-content : pre-content?
procedure
(racketresultfont [ #:decode? decode?] pre-content ...) → element? decode? : boolean? = #t pre-content : pre-content?
procedure
(racketidfont pre-content ...) → element?
pre-content : pre-content?
procedure
(racketvarfont pre-content ...) → element?
pre-content : pre-content?
procedure
(racketkeywordfont pre-content ...) → element?
pre-content : pre-content?
procedure
(racketparenfont pre-content ...) → element?
pre-content : pre-content?
procedure
(racketoptionalfont pre-content ...) → element?
pre-content : pre-content?
Added in version 1.36 of package scribble-lib.
procedure
(racketmetafont pre-content ...) → element?
pre-content : pre-content?
procedure
(racketcommentfont pre-content ...) → element?
pre-content : pre-content?
procedure
(racketerror pre-content ...) → element?
pre-content : pre-content?
procedure
(racketmodfont pre-content ...) → element?
pre-content : pre-content?
procedure
(racketoutput pre-content ...) → element?
pre-content : pre-content?
procedure
pre-content : pre-content?
syntax
(var datum)
syntax
(svar datum)
syntax
(schememodname datum)
(schememodname (unsyntax expr))
syntax
(schememodlink datum pre-content-expr ...)
procedure
(schemefont pre-content ...) → element?
pre-content : pre-content?
procedure
(schemevalfont pre-content ...) → element?
pre-content : pre-content?
procedure
(schemeresultfont pre-content ...) → element?
pre-content : pre-content?
procedure
(schemeidfont pre-content ...) → element?
pre-content : pre-content?
procedure
(schemevarfont pre-content ...) → element?
pre-content : pre-content?
procedure
(schemekeywordfont pre-content ...) → element?
pre-content : pre-content?
procedure
(schemeparenfont pre-content ...) → element?
pre-content : pre-content?
procedure
(schemeoptionalfont pre-content ...) → element?
pre-content : pre-content?
procedure
(schememetafont pre-content ...) → element?
pre-content : pre-content?
procedure
(schemeerror pre-content ...) → element?
pre-content : pre-content?
procedure
(schememodfont pre-content ...) → element?
pre-content : pre-content?
procedure
(schemeoutput pre-content ...) → element?
pre-content : pre-content?