395 lines
14 KiB
Racket
395 lines
14 KiB
Racket
#lang scribble/doc
|
|
@(require "ss.rkt"
|
|
scribble/eval
|
|
(for-label slideshow/code
|
|
racket/gui/base))
|
|
|
|
@(define stx-obj
|
|
(tech #:doc '(lib "scribblings/reference/reference.scrbl") "syntax object"))
|
|
|
|
@(define ss-eval (make-base-eval))
|
|
@(interaction-eval #:eval ss-eval
|
|
(begin
|
|
(require slideshow/code-pict
|
|
slideshow/pict
|
|
(for-syntax racket/base))
|
|
(current-code-tt (lambda (s) (text s "monospace" 14)))
|
|
(define-code code typeset-code)))
|
|
|
|
@title{Typesetting Racket Code}
|
|
|
|
@defmodule*[(slideshow/code-pict slideshow/code)]{
|
|
The @racketmodname[slideshow/code-pict] library
|
|
provides utilities for typesetting Racket code as a pict.
|
|
The @racketmodname[slideshow/code] library initializes
|
|
@racket[get-current-code-font-size] to @racket[current-font-size].}
|
|
|
|
@defproc[(typeset-code [stx syntax?]) pict?]{
|
|
|
|
Produces a pict for code in the given @|stx-obj|. The
|
|
source-location information of the syntax object determines the line
|
|
breaks, line indenting, and space within a row. Empty rows are
|
|
ignored.
|
|
|
|
Beware that if you use @racket[read-syntax] on a file port, you may
|
|
have to turn on line counting via @racket[port-count-lines!] for the
|
|
code to typeset properly. Also beware that when a source file
|
|
containing a @racket[syntax] or @racket[quote-syntax] form is
|
|
compiled, source location information is omitted from the compiled
|
|
@|stx-obj|.
|
|
|
|
Normally, @racket[typeset-code] is used through the @racket[code]
|
|
syntactic form, which works properly with compilation, and that
|
|
escapes to pict-producing code via @racket[unsyntax]. See also
|
|
@racket[define-code].
|
|
|
|
Embedded picts within @racket[stx] are used directly. Row elements are
|
|
combined using and operator like @racket[htl-append], so use
|
|
@racket[code-align] (see below) as necessary to add an ascent to
|
|
ascentless picts. More precisely, creation of a line of code uses
|
|
@racket[pict-last] to determine the end point of the element most
|
|
recently added to a line; the main effect is that closing parentheses
|
|
are attached in the right place when a multi-line pict is embedded in
|
|
@racket[stx].
|
|
|
|
An identifier that starts with @litchar{_} is italicized in the pict,
|
|
and the @litchar{_} is dropped, unless the
|
|
@racket[code-italic-underscore-enabled] parameter is set to
|
|
@racket[#f]. Also, unless @racket[code-scripts-enabled] is set to
|
|
@racket[#f], @litchar{_} and @litchar{^} in the middle of a word
|
|
create superscripts and subscripts, respectively (like TeX); for
|
|
example @racketidfont{foo^4_ok} is displayed as the identifier
|
|
@racketidfont{foo} with a @racketidfont{4} superscript and an
|
|
@racketidfont{ok} subscript.
|
|
|
|
Further, uses of certain identifiers in @racket[stx] typeset
|
|
specially:
|
|
|
|
@itemize[
|
|
|
|
@item{@as-index{@racketidfont{code:blank}} --- produces a space.}
|
|
|
|
@item{@racket[(#,(as-index (racketidfont "code:comment")) _s ...)]
|
|
--- produces a comment block, with each @racket[_s] on its own line,
|
|
where each @racket[_s] must be a string or a pict.}
|
|
|
|
@item{@racket[(#,(as-index (racketidfont "code:line")) _datum ...)]
|
|
--- typesets the @racket[_datum] sequence, which is mostly useful for
|
|
the top-level sequence, since @racket[typeset-code] accepts only one
|
|
argument.}
|
|
|
|
@item{@racket[(#,(as-index (racketidfont "code:contract")) _datum
|
|
...)] --- like @racketidfont{code:line}, but every @racket[_datum]
|
|
is colored as a comment, and a @litchar{;} is prefixed to every line.}
|
|
|
|
@item{@racket[(#,(as-index (racketidfont "code:template")) _datum
|
|
...)] --- like @racketidfont{code:line}, but a @litchar{;} is
|
|
prefixed to every line.}
|
|
|
|
@item{@racketidfont{$} --- typesets as a vertical bar (for no
|
|
particularly good reason).}
|
|
|
|
]}
|
|
|
|
|
|
@defform[(code datum ...)]{
|
|
|
|
The macro form of @racket[typeset-code]. Within a @racket[datum],
|
|
@racket[unsyntax] can be used to escape to an expression, and
|
|
identifiers bound as syntax to @tech{code transformer}s trigger
|
|
transformations.
|
|
|
|
For more information, see @racket[typeset-code] and
|
|
@racket[define-code], since @racket[code] is defined as
|
|
|
|
@racketblock[
|
|
(define-code code typeset-code)
|
|
]
|
|
|
|
@defexamples[#:eval ss-eval #:escape potato
|
|
(code (+ 1 2))
|
|
(code (+ 1 #,(+ 1 1)))
|
|
(code (+ 1 #,(frame (code 2))))
|
|
(define-syntax two (make-code-transformer #'(code 2)))
|
|
(code (+ 1 two))
|
|
]}
|
|
|
|
|
|
@defparam[current-code-font style text-style/c]{
|
|
|
|
Parameter for a base font used to typeset text. The default is
|
|
@racket[`(bold . modern)]. For even more control, see
|
|
@racket[current-code-tt].}
|
|
|
|
|
|
@defparam[current-code-tt proc (string? . -> . pict?)]{
|
|
|
|
Parameter for a one-argument procedure to turn a
|
|
string into a pict, used to typeset text. The default is
|
|
|
|
@racketblock[
|
|
(lambda (s) (text s (current-code-font) ((get-current-code-font-size))))
|
|
]
|
|
|
|
This procedure is not used to typeset subscripts or other items that
|
|
require font changes, where @racket[current-code-font] is used
|
|
directly.}
|
|
|
|
|
|
@defparam[get-current-code-font-size proc (-> exact-nonnegative-integer?)]{
|
|
|
|
A parameter used to access the default font size. The
|
|
@racketmodname[slideshow/code] library initializes this parameter to
|
|
@racket[current-font-size].}
|
|
|
|
|
|
@defparam[current-code-line-sep amt real?]{
|
|
|
|
A parameter that determines the spacing between lines of typeset code.
|
|
The default is @racket[2].}
|
|
|
|
|
|
@defparam[current-comment-color color (or/c string? (is-a?/c color%))]{
|
|
|
|
A parameter for the color of comments.}
|
|
|
|
|
|
@defparam[current-keyword-color color (or/c string? (is-a?/c color%))]{
|
|
|
|
A parameter for the color of syntactic-form names. See
|
|
@racket[current-keyword-list].}
|
|
|
|
|
|
@defparam[current-id-color color (or/c string? (is-a?/c color%))]{
|
|
|
|
A parameter for the color of identifiers that are not syntactic form
|
|
names or constants.}
|
|
|
|
|
|
@defparam[current-literal-color color (or/c string? (is-a?/c color%))]{
|
|
|
|
A parameter for the color of literal values, such as strings and
|
|
numbers. See also @racket[current-literal-list]}
|
|
|
|
|
|
@defparam[current-const-color color (or/c string? (is-a?/c color%))]{
|
|
|
|
A parameter for the color of constant names. See
|
|
@racket[current-const-list].}
|
|
|
|
|
|
@defparam[current-base-color color (or/c string? (is-a?/c color%))]{
|
|
|
|
A parameter for the color of everything else.}
|
|
|
|
|
|
@defparam[current-reader-forms syms (listof symbol?)]{
|
|
|
|
Parameter for a list of symbols indicating which built-in reader forms
|
|
should be used. The default is @racket['(quote quasiquote unquote
|
|
unquote-splicing syntax quasisyntax unsyntax unsyntax-splicing)].
|
|
Remove a symbol to suppress the corresponding reader output.}
|
|
|
|
|
|
@defproc[(code-align [pict pict?]) pict?]{
|
|
|
|
Adjusts the ascent of @racket[pict] so that its bottom aligns with the
|
|
baseline for text; use this function when @racket[pict] has no
|
|
ascent.}
|
|
|
|
|
|
@defparam[current-keyword-list names (listof string?)]{
|
|
|
|
A list of strings to color as syntactic-form names. The default
|
|
includes all of the forms provided by @racketmodname[racket/base]
|
|
and all of the forms provided by @racketmodname[mzscheme].}
|
|
|
|
|
|
@defparam[current-const-list names (listof string?)]{
|
|
|
|
A list of strings to color as constant names. The default is
|
|
@racket[null].}
|
|
|
|
|
|
@defparam[current-literal-list names (listof string?)]{
|
|
|
|
A list of strings to color as literals, in addition to literals such
|
|
as strings. The default is @racket[null].}
|
|
|
|
@defthing[racket/base-const-list (listof string?)]{
|
|
|
|
A list of strings that could be used to initialize the
|
|
@racket[current-const-list] parameter.}
|
|
|
|
@defthing[mzscheme-const-list (listof string?)]{
|
|
|
|
A list of strings that could be used to initialize the
|
|
@racket[current-const-list] parameter.}
|
|
|
|
@defboolparam[code-colorize-enabled on?]{
|
|
|
|
A parameter to enable or disable all code coloring. The default is
|
|
@racket[#t].}
|
|
|
|
|
|
@defboolparam[code-colorize-quote-enabled on?]{
|
|
|
|
A parameter to control whether under a @racket[quote] is colorized as
|
|
a literal (as in this documentation). The default is @racket[#t].}
|
|
|
|
|
|
@defboolparam[code-italic-underscore-enabled on?]{
|
|
|
|
A parameter to control whether @litchar{_}-prefixed identifiers are
|
|
italicized (dropping the @litchar{_}). The default is @racket[#t].}
|
|
|
|
@defboolparam[code-scripts-enabled on?]{
|
|
|
|
A parameter to control whether TeX-style subscripts and subscripts are
|
|
recognized in an identifier.}
|
|
|
|
@defform*[[(define-code code-id typeset-code-id)
|
|
(define-code code-id typeset-code-id escape-id)]]{
|
|
|
|
Defines @racket[code-id] as a macro that uses
|
|
@racket[typeset-code-id], which is a function with the same input as
|
|
@racket[typeset-code]. The @racket[escape-id] form defaults to
|
|
@racket[unsyntax].
|
|
|
|
The resulting @racket[code-id] syntactic form takes a sequence of
|
|
@racket[_datum]s:
|
|
|
|
@racketblock[
|
|
(code-id _datum ...)
|
|
]
|
|
|
|
It produces a pict that typesets the sequence. Source-location
|
|
information for the @racket[_datum] determines the layout of code in
|
|
the resulting pict. The @racket[code-id] is expanded in such a way
|
|
that source location is preserved during compilation (so
|
|
@racket[typeset-code-id] receives a syntax object with source
|
|
locations intact).
|
|
|
|
If a @racket[_datum] contains @racket[(escape-id _expr)]---perhaps as
|
|
@RACKET[#,_expr] when @racket[escape-id] is @racket[unsyntax]---then
|
|
the @racket[_expr] is evaluated and the result datum is spliced in
|
|
place of the @racket[escape-id] form in @racket[_datum]. If the result
|
|
is not a syntax object, it is given the source location of the
|
|
@racket[escape-id] form. A pict value intected this way as a
|
|
@racket[_datum] is rendered as itself.
|
|
|
|
If a @racket[_datum] contains @racket[(transform-id _datum ...)] or
|
|
@racket[transform-id] for a @racket[transform-id] that is bound as syntax to a
|
|
@tech{code transformer}, then the @racket[(transform-id _datum ...)]
|
|
or @racket[transform-id] may be replaced with an escaped expression,
|
|
depending on the @tech{code transformer}'s result.}
|
|
|
|
@deftogether[(
|
|
@defproc[(make-code-transformer [proc-or-stx (or/c (syntax? . -> . (or/c syntax? #f))
|
|
syntax?)])
|
|
code-transformer?]
|
|
@defthing[prop:code-transformer struct-type-property?]
|
|
@defproc[(code-transformer? [v any/c]) boolean?]
|
|
)]{
|
|
|
|
Exported @racket[for-syntax] for creating @deftech{code transformers}.
|
|
|
|
For @tech{code transformer} created with
|
|
@racket[(make-code-transformer _proc)], @racket[proc] takes a syntax
|
|
object representing the use of an identifier bound to the transformer,
|
|
and it produces an expression whose value replaces the identifier use
|
|
within a @racket[code] form or a form defined via
|
|
@racket[define-code]. Like a macro transformer, a code transformer is
|
|
triggered either by a use of the bound identifier in an
|
|
``application'' position, in which case the transformer receives the
|
|
entire ``application'' form, or the identifier by itself can also
|
|
trigger the transformer. The @tech{code transformer}'s @racket[_proc]
|
|
can return @racket[#f], in which case the use of the identifier is
|
|
left untransformed; if the identifier was used in an ``application''
|
|
position, the transformer @racket[_proc] will be called again for the
|
|
identifier use by itself.
|
|
|
|
A @tech{code transformer} produced by @racket[(make-code-transformer _stx)]
|
|
is equivalent to
|
|
|
|
@racketblock[
|
|
(make-code-transformer (lambda (use-stx)
|
|
(if (identifier? use-stx)
|
|
_stx
|
|
#f)))
|
|
]
|
|
|
|
A structure type with the @racket[prop:code-transformer] property
|
|
implements a @tech{code transformer}. The property value must be a
|
|
procedure of one argument, which receives the structure and returns a
|
|
procedure that is like a @racket[_proc] passed to
|
|
@racket[make-code-transformer], except that the property value takes
|
|
the structure instance as an argument before the syntax object to
|
|
transform.
|
|
|
|
The @racket[code-transformer?] predicate returns @racket[#t] for a
|
|
value produced by @racket[make-code-transformer] or for an instance of
|
|
a structure type with the @racket[prop:code-transformer] property,
|
|
@racket[#f] otherwise.
|
|
|
|
@examples[
|
|
#:eval ss-eval
|
|
(let-syntax ([bag (make-code-transformer #'(code hat))]
|
|
[copy (make-code-transformer (syntax-rules ()
|
|
[(_ c) (code (* 2 c))]))])
|
|
(inset (frame (code ((copy cat) in the bag))) 2))
|
|
]}
|
|
|
|
|
|
@defform[(define-exec-code (pict-id runnable-id string-id)
|
|
datum ...)]{
|
|
|
|
Binds @racket[pict-id] to the result of @racket[(code datum ...)],
|
|
except that if an identifier @racketidfont{_} appears anywhere in a
|
|
@racket[datum], then the identifier and the following expression are
|
|
not included for @racket[code].
|
|
|
|
Meanwhile, @racket[runnable-id] is bound to a @|stx-obj| that wraps
|
|
the @racket[datum]s in a @racket[begin]. In this case,
|
|
@racketidfont{_}s are removed from the @racket[datum]s, but not the
|
|
following expression. Thus, an @racketidfont{_} identifier is used to
|
|
comment out an expression from the pict, but have it present in the
|
|
@|stx-obj| for evaluation.
|
|
|
|
The @racket[string-id] is bound to a string representation of the code
|
|
that is in the pict. This string is useful for copying to the
|
|
clipboard with @racket[(send the-clipboard set-clipboard-string
|
|
string-id 0)].}
|
|
|
|
|
|
@defform[(define-exec-code/scale scale-expr (pict-id runnable-id string-id)
|
|
datum ...)]{
|
|
|
|
Like @racket[define-exec-code], but with a scale to use via
|
|
@racket[scale/improve-new-text] when generating the pict.}
|
|
|
|
|
|
@deftogether[(
|
|
@defthing[comment-color (or/c string? (is-a?/c color%))]
|
|
@defthing[keyword-color (or/c string? (is-a?/c color%))]
|
|
@defthing[id-color (or/c string? (is-a?/c color%))]
|
|
@defthing[literal-color (or/c string? (is-a?/c color%))]
|
|
)]{
|
|
|
|
For backward compatibility, the default values for
|
|
@racket[current-comment-color], etc.}
|
|
|
|
@defproc[(code-pict-bottom-line-pict [pict pict?])
|
|
(or/c pict? #f)]{
|
|
|
|
The same as @racket[pict-last], provided for backward compatibility.}
|
|
|
|
@defproc[(pict->code-pict [pict pict?] [bl-pict (or/c pict? #f)]) pict?]{
|
|
|
|
Mainly for backward compatibility: returns @racket[(if bl-pict
|
|
(use-last pict (or (pict-last bl-pict) bl-pict)))].}
|
|
|
|
@; ----------------------------------------
|
|
|
|
@close-eval[ss-eval]
|