[racket] two scribble/srcdoc questions: using scribble/eval examples and in-file provide-extracted
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))))]))