add an 'include' form to scribble/text

svn: r8909

original commit: fb493745279014f2829b64f2ed6c1fd7cfeac430
This commit is contained in:
Eli Barzilay 2008-03-06 23:00:28 +00:00
parent 3b66001cdc
commit 2d702a109b
3 changed files with 64 additions and 6 deletions

View File

@ -1,9 +1,9 @@
#lang scheme/base
(require scheme/promise)
(require scheme/promise (for-syntax scheme/base))
(provide (all-from-out scheme/base scheme/promise))
(define (show x p)
(define (show x [p (current-output-port)])
(let show ([x x])
(cond [(or (void? x) (not x) (null? x)) (void)]
[(pair? x) (show (car x)) (show (cdr x))]
@ -32,3 +32,29 @@
;; (require (prefix-in * "text/lang/reader.ss"))
;; (current-prompt-read
;; (lambda () (parameterize ([read-accept-reader #t]) (*read-syntax))))
;; Utilities
(require (prefix-in at: "reader.ss"))
(provide at:read-inside at:read-inside-syntax)
(provide include)
(define-syntax (include stx)
(syntax-case stx ()
[(_ filename)
(let* ([source (syntax-source stx)]
[dir (or (and source
(let-values ([(base file dir?) (split-path source)])
(and (path? base) base)))
(current-load-relative-directory)
(current-directory))])
(with-syntax ([ns (if source
#`(module->namespace #,source)
#'(current-namespace))]
[dir dir])
#'(let ([contents
(with-input-from-file (path->complete-path filename dir)
at:read-inside-syntax)])
(parameterize ([current-namespace ns])
(for ([expr (syntax->list contents)])
(show (eval expr)))))))]))

View File

@ -1,15 +1,15 @@
#lang scheme/base
(require (prefix-in s: "../../reader.ss"))
(require "../../text.ss")
(provide (rename-out [*read read])
(rename-out [*read-syntax read-syntax]))
(define (*read [inp (current-input-port)])
(wrap inp (s:read-inside inp)))
(wrap inp (at:read-inside inp)))
(define (*read-syntax [src #f] [port (current-input-port)])
(wrap port (s:read-inside-syntax src port)))
(wrap port (at:read-inside-syntax src port)))
(define (wrap port body)
(define (strip-leading-newlines stxs)
@ -29,4 +29,4 @@
[body (if (syntax? body)
(strip-leading-newlines (syntax->list body))
body)])
`(module ,name scribble/text (#%module-begin . ,body))))
`(module ,name scribble/text . ,body)))

View File

@ -40,3 +40,35 @@ it through @exec{mzscheme}. Here is a sample file:
}|
(Note how @litchar["@;"] is used to avoid empty lines in the output.)
@;--------------------------------------------------------------------
@section{Using External Files}
Using additional files that contain code for your preprocessing is
trivial: the preprocessor source is a plain Scheme file, so you can
@scheme[require] additional files as usual.
However, things can become tricky if you want to include an external
file that should also be preprocessed. Using @scheme[require] with a
text file (that uses the @scheme[scribble/text] language) almost
works, but when a module is required, it is invoked before the current
module, which means that the required file will be preprocessed before
the current file regardless of where the @scheme[require] expression
happens to be. Alternatively, you can use @scheme[dynamic-require]
with @scheme[#f] for the last argument (which makes it similar to a
plain @scheme[load])---but remember that the path will be relative to
the current directory, not to the source file.
Finally, there is a convenient syntax for including text files to be
processed:
@defform[(include filename)]{
Preprocess the @scheme[filename] using the same syntax as
@scheme[scribble/text]. This is similar to using @scheme[load] in a
namespace that can access names bound in the current file so included
code can refer to bindings from the including module. Note, however,
that the including module cannot refer to names that are bound the
included file because it is still a plain scheme module---for such
uses you should still use @scheme[require] as usual.}