[racket] using scribble's evaluator for planet packages

From: Danny Yoo (dyoo at cs.wpi.edu)
Date: Fri Jun 3 16:21:54 EDT 2011

I survived in scribbling some documentation for a simple PLaneT
package.  Here's a transcript of the struggle, just in case someone
else is having similar issues.  Maybe I went about this in a
convoluted way, in which case hopefully someone can show me the easy
way to do this.

---

I want to include examples in the documentation of my shiny new PLaneT
package.  But in order to use the examples form,

    http://docs.racket-lang.org/scribble/eval.html#(form._((lib._scribble/eval..rkt)._examples))

I'll probably need to give it an evaluator that knows about my planet
package, because when I try this:

    ;;;; in manual.scrbl
    #lang scribble/manual
    @(require planet/scribble planet/version planet/resolver scribble/eval
                   (this-package-in main)
                   (for-label (this-package-in main)))
    @defmodule/this-package[main]
    @examples[(closure-compile "alert('hello ' + 'world');")]}

the scribbled output contains:

    reference to undefined identifier: closure-compile

It fails because the basic, default evaluator doesn't know about my
PLaneT package's bindings.


Ok, let me try this.

;;; manual.scribl
#lang scribble/manual
@(require planet/scribble planet/version planet/resolver scribble/eval)
@(define my-evaluator
   (let ([p (resolve-planet-path `(planet ,
(this-package-version-symbol main)))])
     ((make-eval-factory (list `(file ,(path->string p)))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


But I see the following error message when I try using this:

################################################################
../../../../gpfs/data/pro/plt-data/software/racket/5.1.1/std/collects/racket/private/map.rkt:45:11:
namespace-attach-module: a different module with the same name is
already in the destination namespace, for name:
"/research/plt/software/racket/5.1.1/std/collects/racket/contract.rkt"
################################################################


Ok, so that didn't work, and the error message looks crazy to me.  Let
me try something else.  Maybe I can make the evaluator directly, and
avoid whatever internal weirdness is happening there.  I'll use
racket/sandbox.


I know my PLaneT package needs to touch the file system in somewhat
unrestricted ways, so I need to use
call-with-trusted-sandbox-configuration to get me a fairly
unrestricted evaluator.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#lang scribble/manual
@(require planet/scribble planet/version planet/resolver scribble/eval
racket/sandbox)
@(define my-evaluator
   (call-with-trusted-sandbox-configuration
    (lambda ()
      (make-evaluator 'racket/base
                              #:requires (list (resolve-planet-path
`(planet , (this-package-version-symbol main))))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Ok, that gets me the evaluator.  Let me see if it runs ok.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> (my-evaluator '(closure-compile "alert('hello, I see: ' + (3 + 4) + '!');"))
"alert(\"hello, I see: 7!\");\n"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



Ok, awesome; I have an evaluator that should work here.  Now let me
use it in an examples form.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 @examples[#:eval my-evaluator
                   (closure-compile "alert('hello' + 'world');")]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Doh.  I get another error message from somewhere internal to Scribble.
 Here's what I see.


    ../../../../gpfs/data/pro/plt-data/software/racket/5.1.1/std/collects/scribble/eval.rkt:126:11:
string=?: expects type <string> as 2nd argument, given: #f; other
arguments were: ""


Ugh.  What did I do wrong here?


(Some time passes; I read the evaluator section in the scribble
documentation a few more times.)


Oh.  Ok, so I need to do something extra with the evaluator setup; it
looks like I've forgotten to tell it to feed sandbox output and
sandbox-error-output, as described in
http://docs.racket-lang.org/scribble/eval.html.  Ok, let me try that
next.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@(define my-evaluator
   (call-with-trusted-sandbox-configuration
    (lambda ()
      (parameterize ([sandbox-output 'string]
                     [sandbox-error-output 'string])
        (make-evaluator
         'racket/base
         #:requires
         (list (resolve-planet-path `(planet ,
(this-package-version-symbol main)))))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


I try again, and I finally get good Scribble output.
(http://planet.racket-lang.org/package-source/dyoo/closure-compile.plt/1/1/planet-docs/manual/index.html)
 Huzzah.


Still, that seems a lot more painful than it should have been.


Posted on the users mailing list.