{"size": 16433, "ext": "scrbl", "max_stars_repo_path": "pict-doc/pict/scribblings/code.scrbl", "max_stars_repo_name": "jackfirth/pict", "max_stars_repo_stars_event_min_datetime": "2015-02-13T20:25:32.000Z", "max_stars_repo_stars_event_max_datetime": "2021-10-17T02:32:33.000Z", "max_issues_repo_path": "pict-doc/pict/scribblings/code.scrbl", "max_issues_repo_name": "jackfirth/pict", "max_issues_repo_issues_event_min_datetime": "2015-06-21T23:40:37.000Z", "max_issues_repo_issues_event_max_datetime": "2022-02-23T09:56:04.000Z", "max_forks_repo_path": "pict-doc/pict/scribblings/code.scrbl", "max_forks_repo_name": "jackfirth/pict", "max_forks_repo_forks_event_min_datetime": "2015-06-21T23:10:58.000Z", "max_forks_repo_forks_event_max_datetime": "2022-01-01T03:03:24.000Z"}
{"max_stars_count": 13, "max_issues_count": 67, "max_forks_count": 20, "avg_line_length": 35.8799126638, "max_line_length": 100, "alphanum_fraction": 0.69220471}
#lang scribble/doc
@(require scribble/manual
          scribble/eval
          (for-label (except-in racket only drop)
                     pict/code
                     pict
                     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 pict/code
            pict
            (for-syntax racket/base))
   (current-code-tt (lambda (s) (text s "monospace" 14)))
   (define-code code typeset-code)))

@title{Typesetting Racket Code}

@defmodule[pict/code]{This library is re-provided by
                      @racketmodname[slideshow/code], but
                      initializes @racket[get-current-code-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.

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 the datum 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 injected 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)))].}

@; ----------------------------------------

@section{Codeblocks}

@(require (for-label (only-in scribble/manual codeblock)))

@defproc[(codeblock-pict [code-string string?] [#:keep-lang-line? keep? any/c #t]) pict?]{

 Like Scribble's @racket[codeblock] but generates picts.

 Unlike @racket[code], @racket[codeblock-pict] formats and
 colors based on the code's language's lexer, which makes it
 suitable for use with code that doesn't use Racket syntax.

 When @racket[keep?] is @racket[#f], the first @tt{#lang}
 line is removed from the pict.

@(ss-eval '(require racket/string))
@defexamples[#:eval ss-eval
(codeblock-pict
  #:keep-lang-line? #f
  (string-join
    '("#lang 2d racket"
      "(require 2d/cond)"
      "(define (same? a b)"
      "  #2dcond"
      "  ╔═════════════╦═══════════════════════╦═════════════╗"
      "  ║             ║       (pair? a)       ║ (number? a) ║"
      "  ╠═════════════╬═══════════════════════╬═════════════╣"
      "  ║ (pair? b)   ║ (and (same? (car a)   ║     #f      ║"
      "  ║             ║             (car b))  ║             ║"
      "  ║             ║      (same? (cdr a)   ║             ║"
      "  ║             ║             (cdr b))) ║             ║"
      "  ╠═════════════╬═══════════════════════╬═════════════╣"
      "  ║ (number? b) ║          #f           ║   (= a b)   ║"
      "  ╚═════════════╩═══════════════════════╩═════════════╝)")
    "\n"))
]

}

@defparam[current-token-class->color to-color (-> symbol? (or/c string? (is-a?/c color%)))]{

A parameter that provides additional control over the colors used by @racket[codeblock-pict]. The
@racket[to-color] procedure is applied to each token class produced by a language’s lexer to map the
class name to a particular color.

The default value maps the standard set of token classes (as recognized by DrRacket) to the
corresponding colors used by @racket[code]. Specifically, it maps

@itemlist[
  @item{@racket['no-color], @racket['parenthesis], and @racket['hash-colon-keyword] to
        @racket[(current-base-color)],}
  @item{@racket['symbol] to @racket[(current-id-color)],}
  @item{@racket['keyword] to @racket[(current-keyword-color)],}
  @item{@racket['string] and @racket['constant] to @racket[(current-literal-color)],}
  @item{@racket['comment] to @racket[(current-comment-color)],}
  @item{@racket['white-space] to @racket["white"],}
  @item{and everything else to @racket["black"].}]

It is usually sufficient to adjust the individual color parameters also used by @racket[code], but
@racket[current-token-class->color] allows for more fine-grained control over how
@racket[codeblock-pict] interprets token classes.

@history[#:added "1.8"]}

@; ----------------------------------------

@(close-eval ss-eval)
