Allow `path-up' to take multiple paths.

svn: r18415
This commit is contained in:
Sam Tobin-Hochstadt 2010-03-01 21:27:03 +00:00
parent 1c1a2dde38
commit 83cdaac011
2 changed files with 36 additions and 30 deletions

View File

@ -68,26 +68,31 @@
(provide path-up) (provide path-up)
(define-require-syntax (path-up stx) (define-require-syntax (path-up stx)
(syntax-case stx () (syntax-case stx ()
[(_ path-stx) [(_ path-stx ...)
(let ([s (syntax-e #'path-stx)]) (and (string? s) (module-path? s))) (for/and ([ps (in-list (syntax->list #'(path-stx ...)))])
(let ([s (syntax-e ps)]) (and (string? s) (module-path? s))))
(let* ([src (syntax-source stx)] (let* ([src (syntax-source stx)]
[dirname (lambda (path) [dirname (lambda (path)
(let-values ([(dir name dir?) (split-path path)]) dir))] (let-values ([(dir name dir?) (split-path path)]) dir))]
[srcdir (if (and (path-string? src) (complete-path? src)) [srcdir (if (and (path-string? src) (complete-path? src))
(dirname src) (dirname src)
(or (current-load-relative-directory) (or (current-load-relative-directory)
(current-directory)))]) (current-directory)))])
(define path (syntax-e #'path-stx)) (with-syntax
(unless (complete-path? srcdir) (error 'path-up "internal error")) ([(paths ...)
(parameterize ([current-directory srcdir]) (for/list ([ps (in-list (syntax->list #'(path-stx ...)))])
(let loop ([dir srcdir] [path (string->path path)] [pathstr path]) (define path (syntax-e ps))
(if (file-exists? path) (unless (complete-path? srcdir) (error 'path-up "internal error"))
(datum->syntax stx pathstr stx) (parameterize ([current-directory srcdir])
(let ([dir (dirname dir)]) (let loop ([dir srcdir] [path (string->path path)] [pathstr path])
(if dir (if (file-exists? path)
(loop dir (build-path 'up path) (datum->syntax stx pathstr stx stx)
(string-append "../" pathstr)) (let ([dir (dirname dir)])
(raise-syntax-error 'path-up (if dir
"file no found in any parent directory" (loop dir (build-path 'up path)
stx #'path-stx)))))))])) (string-append "../" pathstr))
(raise-syntax-error 'path-up
"file no found in any parent directory"
stx ps)))))))])
(syntax/loc stx (combine-in paths ...))))]))

View File

@ -11,7 +11,8 @@
scheme/provide scheme/provide
scheme/nest scheme/nest
scheme/package scheme/package
scheme/splicing)) scheme/splicing
scheme/runtime-path))
@(define require-eval (make-base-eval)) @(define require-eval (make-base-eval))
@(define syntax-eval @(define syntax-eval
@ -1078,11 +1079,11 @@ aliens
will get the @scheme[scheme/base] bindings that match the regexp, will get the @scheme[scheme/base] bindings that match the regexp,
and renamed to use ``camel case.''} and renamed to use ``camel case.''}
@defform[(path-up rel-string)]{ @defform[(path-up rel-string ...)]{
This specifies a path to a module named @scheme[rel-string] in a This specifies paths to module named by the @scheme[rel-string]s in a
similar way to using @scheme[rel-string] directly, except that if the similar way to using the @scheme[rel-string]s directly, except that if the
required module file is not found there, it is searched in the parent required module files are not found there, they are searched for in the parent
directory (in @filepath{../@scheme[_rel-string]}), and then in directory (in @filepath{../@scheme[_rel-string]}), and then in
the grand-parent directory, going all the way up to the root. (Note the grand-parent directory, going all the way up to the root. (Note
that the usual caveats hold for a macro that depends on files that it that the usual caveats hold for a macro that depends on files that it
@ -1092,16 +1093,16 @@ of the compiled form.)
This form is useful in setting up a ``project environment''. For This form is useful in setting up a ``project environment''. For
example, you can write a @filepath{config.ss} file in the root example, you can write a @filepath{config.ss} file in the root
directory of your project with: directory of your project with:
@verbatim[#:indent 2]{ @schememod[
#lang scheme/base scheme/base
(require scheme/require-syntax (for-syntax "utils/in-here.ss")) (require scheme/require-syntax (for-syntax "utils/in-here.ss"))
;; require form for my utilities ;; require form for my utilities
(provide utils-in) (provide utils-in)
(define-require-syntax utils-in in-here-transformer) (define-require-syntax utils-in in-here-transformer)
} ]
and in @filepath{utils/in-here.ss} in the root: and in @filepath{utils/in-here.ss} in the root:
@verbatim[#:indent 2]{ @schememod[
#lang scheme/base scheme/base
(require scheme/runtime-path) (require scheme/runtime-path)
(provide in-here-transformer) (provide in-here-transformer)
(define-runtime-path here ".") (define-runtime-path here ".")
@ -1111,7 +1112,7 @@ and in @filepath{utils/in-here.ss} in the root:
(identifier? #'sym) (identifier? #'sym)
(let ([path (build-path here (format "~a.ss" (syntax-e #'sym)))]) (let ([path (build-path here (format "~a.ss" (syntax-e #'sym)))])
(datum->syntax stx `(file ,(path->string path)) stx))])) (datum->syntax stx `(file ,(path->string path)) stx))]))
} ]
Finally, you can use it via @scheme[path-up]: Finally, you can use it via @scheme[path-up]:
@schemeblock[ @schemeblock[
(require scheme/require (path-up "config.ss") (utils-in foo))] (require scheme/require (path-up "config.ss") (utils-in foo))]