www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

scribble-enhanced.scrbl (8311B)


      1 #lang scribble/manual
      2 @require[@for-label[(except-in scribble-enhanced define-code)
      3                     racket/base
      4                     (only-in scribble/racket define-code)
      5                     (only-in syntax/stx stx-list?)]
      6          scribble-enhanced]
      7 
      8 @title{Scribble Enhanced}
      9 @author[@author+email["Suzanne Soy" "racket@suzanne.soy"]]
     10 
     11 @defmodule[scribble-enhanced]
     12 
     13 @section{@racket[defform] enhancements}
     14 
     15 @subsection{Easy rendering of quotes and syntax reader abbreviations}
     16 
     17 The six common reader abbreviations are rendered as
     18 expected, using a heuristic on source locations (so that 
     19 @tt{#`} renders as @tt{#`} and not @tt{quasisyntax} when the
     20 source location span is exactly two characters, for
     21 example).
     22 
     23 @racketblock[
     24  @defform[#:kind "example"
     25           (example-1 a
     26                      #'(b arg …)
     27                      #`(c arg …)
     28                      ((unsyntax 'unsyntax) (d arg …))
     29                      'd
     30                      `e
     31                      ,f
     32                      (@#,RACKET[syntax] (e arg …))
     33                      (@#,RACKET[quasisyntax] (f arg …))
     34                      (@#,RACKET[unsyntax] (g arg …))
     35                      (@#,RACKET[quote] d)
     36                      (@#,RACKET[quasiquote] e)
     37                      (@#,RACKET[unquote] f))]]
     38 
     39 The above example renders as (with reader abbreviations for
     40 the first six, but not for the last six):
     41 
     42 @nested[#:style 'code-inset]{
     43  @defform[#:kind "example"
     44           (example-1 a
     45                      #'(b arg …)
     46                      #`(c arg …)
     47                      #,(d arg …)
     48                      'd
     49                      `e
     50                      ,f
     51                      (syntax (a arg …))
     52                      (quasisyntax (b arg …))
     53                      (unsyntax (c arg …))
     54                      (quote d)
     55                      (quasiquote e)
     56                      (unquote f))]
     57 }
     58 
     59 @subsubsection{Escaping from @racket[defform]}
     60 
     61 Escaping from defform using @racket[UNSYNTAX] is not
     62 implemented yet.
     63 
     64 @subsection{@racket[#:result] for @racket[defform]}
     65 
     66 @racketblock[
     67  @defform[#:kind "example"
     68           (example-2 a #'([b c] ...))
     69           #:result void?
     70           #:contracts ([a port?]
     71                        [b number?]
     72                        [c string?])]{
     73   Example description
     74   }]
     75 
     76 The code above renders as follows:
     77 
     78 @nested[#:style 'code-inset]{
     79  @defform[#:kind "example"
     80           (example-2 a #'([b c] ...))
     81           #:result void?
     82           #:contracts ([a port?]
     83                        [b number?]
     84                        [c string?])]{
     85   Example description
     86  }
     87 }
     88 
     89 @subsection{Arbitrary rewriting of code in @racket[racketblock] and similar}
     90 
     91 @defthing[#:kind "mutable-match-lambda"
     92           mutable-match-element-id-transformer]{As an example, it would be
     93  possible to create a rewrite handler which turns the ⁰¹²³⁴⁵⁶⁷⁸⁹ unicode
     94  superscripts at the end of identifiers into superscripts alongside the
     95  base identifier.
     96 
     97  This could be useful to typeset code using the @elem[#:style 'tt "xlist"]
     98  package, which rewrites identifiers ending with a superscript to mean
     99  repetition, so that @racket[(define-type three-ints (xList Integer³))] is
    100  equivalent to @racket[(define-type three-ints (List Integer Integer Integer))].
    101 
    102  @racketblock[
    103  @(code:comment "Correctly display xyz⃰, xyzⁿ, xyz⁰, xyz¹, … xyz⁹")
    104  (begin-for-syntax
    105    (mutable-match-lambda-add-overriding-clause!
    106     mutable-match-element-id-transformer
    107     #:match-lambda
    108     [(? identifier?
    109         whole-id
    110         (app (compose symbol->string syntax-e)
    111              (pregexp #px"^(.*?)(⃰|ⁿ|[⁰¹²³⁴⁵⁶⁷⁸⁹]+)$"
    112                       (list whole base power))))
    113      (define/with-syntax base-id (format-id whole-id "~a" base))
    114      (define/with-syntax power-characters
    115        (string-join
    116         (map (match-lambda ["⃰" "*"]
    117                            ["ⁿ" "n"]
    118                            ["⁰" "0"] ["¹" "1"] ["²" "2"] ["³" "3"] ["⁴" "4"]
    119                            ["⁵" "5"] ["⁶" "6"] ["⁷" "7"] ["⁸" "8"] ["⁹" "9"])
    120              (map string (string->list power)))))
    121      #'(elem (list (racket base-id)
    122                    (superscript power-characters)))]))]
    123 
    124  Another use case would be a hack to correctly colour syntax classes from
    125  syntax-parse, when used as @racket[attr:stxclass]. Here is how it would be
    126  defined:
    127 
    128  @racketblock[
    129  (begin-for-syntax
    130    (mutable-match-lambda-add-overriding-clause!
    131     mutable-match-element-id-transformer
    132     #:match-lambda
    133     [(? identifier?
    134         whole-id
    135         (app (compose symbol->string syntax-e)
    136              (pregexp #px"^([^:]*):([^:]*)$"
    137                       (list whole attr cls))))
    138      (define/with-syntax attr-id (format-id whole-id "~a" attr))
    139      (define/with-syntax cls-id (format-id whole-id "~a" cls))
    140      #'(elem (list (racket attr-id)
    141                    (elem #:style 'tt ":")
    142                    (racket cls-id)))]))]
    143 
    144  The code for these two examles would be inserted directly inside the document,
    145  before any @racket[racketblock], @racket[chunk] or similar.}
    146 
    147 @defthing[#:kind "syntax property"
    148           scribble-render]{
    149  The @racket['scribble-render] syntax property can contain a function. It will
    150  be called with the whole syntax object, and must return the syntax for
    151  scribble code which will be used in place of that s-expression.
    152 
    153  This feature is experimental, and may be changed in future versions.
    154 
    155  @history[#:added "0.2"
    156           #:changed "0.3"
    157           @elem{Deprecated in favour of @racket[scribble-render-as].}]
    158 
    159  @deprecated[#:what "syntax property"
    160              @racket[scribble-render-as]]{
    161   Deprecated as of @racketmodname[scribble-enhanced] version 0.3, because
    162   @racket['scribble-render] only supports single-line replacements. The new
    163   @racket['scribble-render-as] property is more flexible.}}
    164 
    165 @defthing[#:kind "syntax property"
    166           scribble-render-as]{
    167  The @racket['scribble-render-as] syntax property can contain a function. It
    168  will be called with six argumens:
    169 
    170  @defproc[(scribble-render-as-proc
    171            [self syntax?]
    172            [id identifier?]
    173            [typeset-expr syntax?]
    174            [uncode-id identifier?]
    175            [d->s-expr syntax?]
    176            [stx-prop-expr syntax?])
    177           stx-list?]{}
    178                                                                    
    179  The first argument, @racket[self], is the whole syntax object bearing the
    180  @racket['scribble-render-as] property. The other arguments are the (quoted
    181  syntax form of) the arguments passed to the @racket[define-code] macro which
    182  generated the form currently rendering the code. The most useful argument is
    183  @racket[uncode], indicating which identifier should be used in place of
    184  @racket[unsyntax] to escape the current form, which will be
    185  @racket[racketblock], @racket[RACKETBLOCK] or another similar form.
    186 
    187  The function must return a syntax object which will be spliced in place of the
    188  original when rendering. Note that the returned syntax object will be spliced,
    189  i.e. the outer pair of parentheses removed. If the original syntax object must
    190  be replaced by @racket[foo], then @racket[#'foo] must be returned. The splicing
    191  operation allows several tokens to be rendered. For example, in
    192  @racket[(racketblock a b c)], if @racket[b] has the
    193  @racket['scribble-render-as] property, and the function returns
    194  @racket[#'(x y z)], then the whole form will be rendered like
    195  @racket[(racketblock a x y z c)].
    196 
    197  As an example, here is the @racket['scribble-render-as] procedure used by
    198  @racketmodname[aful #:indirect], to render the lambda shorthand notation
    199  @racket["#λ(+ % 1)"]:
    200 
    201  @racketblock[
    202  (define (aful-scribble-render self id code typeset-code uncode d->s stx-prop)
    203    (syntax-case self ()
    204      (code:comment "#λ(body) reads as:")
    205      (code:comment "(lambda args")
    206      (code:comment "  (define-syntax % (make-rename-transformer #'%1))")
    207      (code:comment "  body)")
    208      [(_ _ _ body)
    209       (with-syntax ([uncode (datum->syntax uncode (syntax-e uncode) self)])
    210         (syntax/top-loc self
    211           ((uncode(seclink "_lang_aful"
    212                            #:doc '(lib "aful/docs/aful.scrbl")
    213                            (tt "#λ")))
    214            body)))]))]
    215 
    216  This feature is experimental, and may be changed in future versions.
    217 
    218  @history[#:added "0.3"]}