Scribble Enhanced
1 defform enhancements
1.1 Easy rendering of quotes and syntax reader abbreviations
example-1
1.1.1 Escaping from defform
1.2 #:  result for defform
example-2
1.3 Arbitrary rewriting of code in racketblock and similar
mutable-match-element-id-transformer
scribble-render
scribble-render-as
scribble-render-as-proc
7.0

Scribble Enhanced

Georges Dupéron

 (require scribble-enhanced) package: scribble-enhanced

1 defform enhancements

1.1 Easy rendering of quotes and syntax reader abbreviations

The six common reader abbreviations are rendered as expected, using a heuristic on source locations (so that # renders as # and not quasisyntax when the source location span is exactly two characters, for example).

(defform #:kind "example"
         (example-1 a
                    #'(b arg )
                    #`(c arg )
                    #,(d arg )
                    'd
                    `e
                    ,f
                    (syntax (e arg ))
                    (quasisyntax (f arg ))
                    (unsyntax (g arg ))
                    (quote d)
                    (quasiquote e)
                    (unquote f)))

The above example renders as (with reader abbreviations for the first six, but not for the last six):

example

(example-1 a
           #'(b arg )
           #`(c arg )
           #,(d arg )
           'd
           `e
           ,f
           (syntax (a arg ))
           (quasisyntax (b arg ))
           (unsyntax (c arg ))
           (quote d)
           (quasiquote e)
           (unquote f))
1.1.1 Escaping from defform

Escaping from defform using UNSYNTAX is not implemented yet.

1.2 #:result for defform

(defform #:kind "example"
         (example-2 a #'([b c] ...))
         #:result void?
         #:contracts ([a port?]
                      [b number?]
                      [c string?])
 "Example description")

The code above renders as follows:

example

(example-2 a #'([b c] ...))
  void?
 
  a : port?
  b : number?
  c : string?
Example description

1.3 Arbitrary rewriting of code in racketblock and similar

mutable-match-lambda

mutable-match-element-id-transformer

 : "As an example, it would be"
possible to create a rewrite handler which turns the ⁰¹²³⁴⁵⁶⁷⁸⁹ unicode superscripts at the end of identifiers into superscripts alongside the base identifier.

This could be useful to typeset code using the xlist package, which rewrites identifiers ending with a superscript to mean repetition, so that (define-type three-ints (xList Integer³)) is equivalent to (define-type three-ints (List Integer Integer Integer)).

;Correctly display xyz⃰, xyzⁿ, xyz⁰, xyz¹, … xyz⁹
(begin-for-syntax
 (mutable-match-lambda-add-overriding-clause!
  mutable-match-element-id-transformer
  #:match-lambda
  [(? identifier?
      whole-id
      (app (compose symbol->string syntax-e)
           (pregexp #px"^(.*?)(⃰|ⁿ|[⁰¹²³⁴⁵⁶⁷⁸⁹]+)$"
                    (list whole base power))))
   (define/with-syntax base-id (format-id whole-id "~a" base))
   (define/with-syntax power-characters
     (string-join
      (map (match-lambda ["⃰" "*"]
                         ["ⁿ" "n"]
                         ["⁰" "0"] ["¹" "1"] ["²" "2"] ["³" "3"] ["⁴" "4"]
                         ["⁵" "5"] ["⁶" "6"] ["⁷" "7"] ["⁸" "8"] ["⁹" "9"])
           (map string (string->list power)))))
   #'(elem (list (racket base-id)
                 (superscript power-characters)))]))

Another use case would be a hack to correctly colour syntax classes from syntax-parse, when used as attr:stxclass. Here is how it would be defined:

(begin-for-syntax
  (mutable-match-lambda-add-overriding-clause!
   mutable-match-element-id-transformer
   #:match-lambda
   [(? identifier?
       whole-id
       (app (compose symbol->string syntax-e)
            (pregexp #px"^([^:]*):([^:]*)$"
                     (list whole attr cls))))
    (define/with-syntax attr-id (format-id whole-id "~a" attr))
    (define/with-syntax cls-id (format-id whole-id "~a" cls))
    #'(elem (list (racket attr-id)
                  (elem #:style 'tt ":")
                  (racket cls-id)))]))

The code for these two examles would be inserted directly inside the document, before any racketblock, chunk or similar.

syntax property

scribble-render : "The "

'scribble-render syntax property can contain a function. It will be called with the whole syntax object, and must return the syntax for scribble code which will be used in place of that s-expression.

This feature is experimental, and may be changed in future versions.

Added in version 0.2 of package scribble-enhanced.
Changed in version 0.3: Deprecated in favour of scribble-render-as.

NOTE: This syntax property is deprecated; use scribble-render-as, instead. Deprecated as of scribble-enhanced version 0.3, because 'scribble-render only supports single-line replacements. The new 'scribble-render-as property is more flexible.

syntax property

scribble-render-as : "The "

'scribble-render-as syntax property can contain a function. It will be called with six argumens:

procedure

(scribble-render-as-proc self    
  id    
  typeset-expr    
  uncode-id    
  d->s-expr    
  stx-prop-expr)  stx-list?
  self : syntax?
  id : identifier?
  typeset-expr : syntax?
  uncode-id : identifier?
  d->s-expr : syntax?
  stx-prop-expr : syntax?

The first argument, self, is the whole syntax object bearing the 'scribble-render-as property. The other arguments are the (quoted syntax form of) the arguments passed to the define-code macro which generated the form currently rendering the code. The most useful argument is uncode, indicating which identifier should be used in place of unsyntax to escape the current form, which will be racketblock, RACKETBLOCK or another similar form.

The function must return a syntax object which will be spliced in place of the original when rendering. Note that the returned syntax object will be spliced, i.e. the outer pair of parentheses removed. If the original syntax object must be replaced by foo, then #'foo must be returned. The splicing operation allows several tokens to be rendered. For example, in (racketblock a b c), if b has the 'scribble-render-as property, and the function returns #'(x y z), then the whole form will be rendered like (racketblock a x y z c).

As an example, here is the 'scribble-render-as procedure used by aful, to render the lambda shorthand notation "#λ(+ % 1)":

(define (aful-scribble-render self id code typeset-code uncode d->s stx-prop)
  (syntax-case self ()
    ;#λ(body) reads as:
    ;(lambda args
    ; (define-syntax % (make-rename-transformer #'%1))
    ; body)
    [(_ _ _ body)
     (with-syntax ([uncode (datum->syntax uncode (syntax-e uncode) self)])
       (syntax/top-loc self
         ((uncode(seclink "_lang_aful"
                          #:doc '(lib "aful/docs/aful.scrbl")
                          (tt "#λ")))
          body)))]))

This feature is experimental, and may be changed in future versions.

Added in version 0.3 of package scribble-enhanced.