[racket] How `scribble` resolves relative paths

From: Greg Hendershott (greghendershott at gmail.com)
Date: Sun Sep 7 21:02:45 EDT 2014

>> Separately, I think one gotcha with your original macro will be if you
>> use it more than once? I think you need to provide a fresh id to each
>> define-runtime-path, like so:
>
> I thought that would be the case too, though it does work without `generate-temporaries`. (Looking at the macro expansion, it seems each time the macro operates, it assigns a unique subscript to each "rp" identifier so they don't collide). But I can't tell if that's just lucky behavior. `Generate-temporaries` is clearly the right way to do things.
>

Hmm, it definitely errors for me. And I see it expand duplicating the
identifier.


>> If you don't mind requiring that `name` be supplied first, you could
>> simply pass the remaining args through unchanged:
>
> For my purposes that's fine, though it's still a bit of a cheat. And cheating may not be an option next time ...

Here's another attempt that cheats a bit less. ;)  I do make the image
file name a required keyword argument, `#:path`:

#lang racket/base

(require (for-syntax racket/base
                     racket/function
                     racket/syntax
                     syntax/parse)
         racket/pretty
         racket/runtime-path
         scribble/base)

(define-syntax (image/rp stx)
  (define-splicing-syntax-class arg
    (pattern (~seq kw:keyword e:expr))
    (pattern (~seq e:expr)))
  (syntax-parse stx
    [(_ arg:arg ...)
     (define all-args (syntax->list #'(arg ...)))
     (define (path-arg stx)
       (syntax-parse stx
         [(#:path path:expr) #'path]
         [_ #f]))
     (with-syntax
         ([id (generate-temporary)]
          [path (ormap path-arg all-args)]
          [((other-args ...) ...) (filter (negate path-arg) all-args)])
       (unless (syntax-e #'path)
         (raise-syntax-error 'image/rp
                             "Required keyword argument #:path is missing"))
       #'(begin
           (define-runtime-path id path)
           (image id other-args ... ...)))]))

Examples:

  (image/rp #:path "here.png")

  (image/rp #:scale 1.0 #:suffixes '() #:path "there.png")))))

;; =>

  (begin
    (define-runtime-path g1 "here.png")
    (image g1))

  (begin
    (define-runtime-path g2 "there.png")
    (image g2 #:scale 1.0 #:suffixes '()))


Posted on the users mailing list.