[racket] two scribble/srcdoc questions: using scribble/eval examples and in-file provide-extracted

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Fri May 18 17:46:04 EDT 2012

On May 18, 2012, at 8:47 AM, Uri Zarfaty wrote:

> Hi all,
> 
> I've been trying to use scribble/srcdoc for in-source documentation, and have a couple of hopefully straightforward questions.
> 
> 1) Is it possible to use scribble/eval examples in proc-doc/names? Trying this naively results in an undefined identifier error, presumably since the function binding was not introduced to the source file that defines it using a require.
> 
> 2) Is it possible to use include-previously-extracted without requiring an additional file for provide-extracted (e.g. by having the provide-extracted in either the source or documentation file)?
> 
> Answers that only work in 5.3 (e.g. using submodules) are fine. Thanks!

I created a provide-and-scribble macro parallel to Matthew's effort on srcdoc. I stopped (not because I saw his, but because I have too many things to do at once.) 

My goal is to provide documentation for the HtDP teachpacks that always shows at least one interaction with the documented function i.e. a use of @interaction. 

Here is the idea, sketched out: 

;; provide-and-scribble.rkt 
;; the macros 
#lang at-exp racket

(require (for-syntax syntax/parse) scribble/manual scribble/eval racket/sandbox)

(provide 
 define-module-local-eval 
 provide-and-scribble
 )

;; ---------------------------------------------------------------------------------------------------

(define-for-syntax add-sections #f)

(define-syntax (provide-and-scribble stx)
  (syntax-parse stx #:literals (defproc)
    [(provide-and-scribble (title (defproc (name args ...) range desc ...) ...) ...)
     (define add-docs-and-provide
       ;; **********************************************************************************
       ;; this needs something like a @defmodule[localname] but perhaps
       ;; this should be added when I require the doc submodule
       ;; **********************************************************************************
       #`((module+ doc (#,add-sections title (list (defproc (name args ...) range desc ...) ...)))
          ...
          (provide name ... ...)))
     (cond 
       [add-sections add-docs-and-provide]
       [else
        (set! add-sections (syntax-local-introduce #'add-sections))
        #`(begin 
            (module+ doc 
                     (provide docs)
                     (define *sections '())
                     (define (#,add-sections stitle scontent)
                       (set! *sections (cons (list stitle scontent) *sections)))
                     (define (docs)
                       (reverse *sections)))
            #, at add-docs-and-provide)])]))


;; (define-module-local-eval name-of-evaluator)
;; a make-base-eval whose namespace is initialized with the module where the macro is used 
(define-syntax-rule 
  (define-module-local-eval name)
  (begin
    (define-namespace-anchor ns)
    (define name 
      (parameterize ([sandbox-namespace-specs (list (lambda () (namespace-anchor->namespace ns)))]
                     [sandbox-error-output 'string]
                     [sandbox-output 'string])
        (make-base-eval)))))

---------------------------------------------------------------------------------------

;; provide-and-define.rkt 
;; a sample library that uses provide-and-scribble with @interaction 
#lang at-exp racket

(require "provide-and-scribble.rkt" scribble/manual scribble/eval)

(define-module-local-eval my-eval)

(define (f x) `(f ,x))
(define (g x) `(g ,x))
(define (h x) `(h ,x))

(provide-and-scribble
 ("Numbers"
  @defproc[(f [x number?]) number?]{hello world @interaction[#:eval my-eval (f 10)]}
  @defproc[(g [x number?]) number?]{hello world @interaction[#:eval my-eval (g 10)]}
  )
 ("Strings"
  @defproc[(h [x number?]) number?]{hello world @interaction[#:eval my-eval (h "hello")]}
  ))

---------------------------------------------------------------------------------------

;; provide-and-test.scrbl 
;; the scribble document that uses the docs 
#lang scribble/manual

@(require (submod "provide-and-define.rkt" doc))

@(let loop ([s (docs)])
   (cond
     [(null? s) '()]
     [else 
      (define-values (section-title stuff) (apply values (car s)))
      (cons @section{@section-title}
            (cons @stuff (loop (cdr s))))]))

Posted on the users mailing list.