Some extra helper functions
This commit is contained in:
@@ -1,3 +1,18 @@
|
||||
0.1.4
|
||||
|
||||
Replaced files-for-regexp, list-dir-re, list-dir-re-r, and filter-dirs with
|
||||
list-dir/files, list-files, and list-dirs.
|
||||
All three helpers support optional #:recursive #t traversal.
|
||||
Non-recursive results use complete paths so they can be passed directly to
|
||||
rm-f and rm-rf.
|
||||
Updated tests, examples, README, and Scribble documentation.
|
||||
|
||||
0.1.3
|
||||
|
||||
Added recursive and non-recursive regexp directory helpers:
|
||||
files-for-regexp, list-dir-re, list-dir-re-r, and filter-dirs.
|
||||
Added documentation and an example for regexp-based cleanup with rm-f/rm-rf.
|
||||
|
||||
0.1.2
|
||||
|
||||
Makefile loading no longer starts a build automatically.
|
||||
|
||||
@@ -40,7 +40,7 @@ raco pkg install
|
||||
For a versioned archive, give the package name explicitly:
|
||||
|
||||
```text
|
||||
raco pkg install --name racket-makefile racket-makefile-0.1.2.zip
|
||||
raco pkg install --name racket-makefile racket-makefile-0.1.4.zip
|
||||
```
|
||||
|
||||
## Running targets
|
||||
@@ -78,6 +78,36 @@ registers the targets. Then use the Interactions window:
|
||||
Bare identifiers in `make` are target names, so no quote is needed. For
|
||||
example, `(make clean)` selects the target named `clean`.
|
||||
|
||||
## Regexp-based cleanup
|
||||
|
||||
For cleanup rules that need more control than globs, `racket-makefile` also
|
||||
provides small directory/regexp helpers. The results are ordinary path lists,
|
||||
so they can be passed directly to `rm-f` and `rm-rf` with `apply`:
|
||||
|
||||
```racket
|
||||
#lang racket-makefile
|
||||
|
||||
(default-target all)
|
||||
(phony all clean)
|
||||
|
||||
(target all
|
||||
(displayln "use (make clean)"))
|
||||
|
||||
(target clean
|
||||
(display "cleaning up...")
|
||||
(apply rm-rf
|
||||
(list-dirs "." #px"compiled$" #:recursive #t))
|
||||
(apply rm-f
|
||||
(list-files "." #px"(?i:(?:[.]bak|~)$)" #:recursive #t))
|
||||
(displayln "done."))
|
||||
```
|
||||
|
||||
`list-dir/files` returns matching files and directories. `list-files` and
|
||||
`list-dirs` restrict the result to files or directories. All three scan one
|
||||
directory level by default; use `#:recursive #t` to walk the complete tree.
|
||||
Non-recursive results are returned as complete paths, so the lists can be fed
|
||||
directly to `rm-f` or `rm-rf` with `apply`.
|
||||
|
||||
## Generated targets
|
||||
|
||||
Because the rest of the language is ordinary Racket, targets can be generated
|
||||
@@ -101,7 +131,7 @@ with normal definitions and loops:
|
||||
Dependency expressions may produce lists; they are recursively flattened.
|
||||
|
||||
The language adds `target`, `deps`, `phony`, `default-target`, `make`, `run`,
|
||||
`rm-f`, `rm-rf`, `cleanup`, `$target`, `$deps` and `$<`. Everything else is
|
||||
ordinary Racket.
|
||||
`rm-f`, `rm-rf`, `cleanup`, `list-dir/files`, `list-files`, `list-dirs`,
|
||||
`$target`, `$deps` and `$<`. Everything else is ordinary Racket.
|
||||
|
||||
See the installed `racket-makefile` Scribble documentation for the full API.
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#lang racket-makefile
|
||||
|
||||
(default-target all)
|
||||
(phony all clean)
|
||||
|
||||
(target all
|
||||
(displayln "use (make clean)"))
|
||||
|
||||
(target clean
|
||||
(display "cleaning up...")
|
||||
(apply rm-rf
|
||||
(list-dirs "." #px"compiled$" #:recursive #t))
|
||||
(apply rm-f
|
||||
(list-files "." #px"(?i:(?:[.]bak|~)$)" #:recursive #t))
|
||||
(displayln "done."))
|
||||
@@ -1,7 +1,7 @@
|
||||
#lang info
|
||||
|
||||
(define pkg-authors '(hnmdijkema))
|
||||
(define version "0.1.2")
|
||||
(define version "0.1.4")
|
||||
(define license 'MIT)
|
||||
(define collection "racket-makefile")
|
||||
(define pkg-desc
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
rm-f
|
||||
rm-rf
|
||||
cleanup
|
||||
list-dir/files
|
||||
list-files
|
||||
list-dirs
|
||||
$target
|
||||
$deps
|
||||
$<)
|
||||
|
||||
+20
-1
@@ -10,7 +10,10 @@
|
||||
(provide run
|
||||
rm-f
|
||||
rm-rf
|
||||
cleanup)
|
||||
cleanup
|
||||
list-dir/files
|
||||
list-files
|
||||
list-dirs)
|
||||
|
||||
(define (recipe-value who parameter description)
|
||||
(define value (parameter))
|
||||
@@ -80,3 +83,19 @@
|
||||
[(file link) (rm-f path)]
|
||||
[else (void)]))
|
||||
(void))
|
||||
|
||||
(define (list-dir/files directory regexp #:recursive [recursive #f])
|
||||
(filter (lambda (path)
|
||||
(regexp-match? regexp path))
|
||||
(if recursive
|
||||
(for/list ([path (in-directory directory)])
|
||||
path)
|
||||
(directory-list directory #:build? #t))))
|
||||
|
||||
(define (list-files directory regexp #:recursive [recursive #f])
|
||||
(filter file-exists?
|
||||
(list-dir/files directory regexp #:recursive recursive)))
|
||||
|
||||
(define (list-dirs directory regexp #:recursive [recursive #f])
|
||||
(filter directory-exists?
|
||||
(list-dir/files directory regexp #:recursive recursive)))
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
(only-in racket-makefile
|
||||
target deps phony default-target make
|
||||
run rm-f rm-rf cleanup
|
||||
list-dir/files list-files list-dirs
|
||||
$target $deps $<)))
|
||||
|
||||
@title{racket-makefile}
|
||||
@@ -31,7 +32,7 @@ raco pkg install
|
||||
For a versioned archive, specify the package name explicitly:
|
||||
|
||||
@verbatim{
|
||||
raco pkg install --name racket-makefile racket-makefile-0.1.2.zip
|
||||
raco pkg install --name racket-makefile racket-makefile-0.1.4.zip
|
||||
}
|
||||
|
||||
After installation a makefile can start with:
|
||||
@@ -224,6 +225,59 @@ For example:
|
||||
"**.css")))
|
||||
]
|
||||
|
||||
@section{Regexp directory helpers}
|
||||
|
||||
@defproc[(list-dir/files [directory path-string?]
|
||||
[regexp regexp?]
|
||||
[#:recursive recursive any/c #f])
|
||||
list?]{
|
||||
Returns entries below @racket[directory] that match @racket[regexp]. By default
|
||||
only the direct contents of @racket[directory] are inspected. With
|
||||
@racket[#:recursive #t], the complete tree is walked using
|
||||
@racket[in-directory], and both files and directories can be returned.
|
||||
|
||||
For a non-recursive listing, complete paths are built from @racket[directory],
|
||||
so the result can be passed directly to file operations such as
|
||||
@racket[rm-f] and @racket[rm-rf].
|
||||
}
|
||||
|
||||
@defproc[(list-files [directory path-string?]
|
||||
[regexp regexp?]
|
||||
[#:recursive recursive any/c #f])
|
||||
list?]{
|
||||
Like @racket[list-dir/files], but keeps only paths for which
|
||||
@racket[file-exists?] is true.
|
||||
}
|
||||
|
||||
@defproc[(list-dirs [directory path-string?]
|
||||
[regexp regexp?]
|
||||
[#:recursive recursive any/c #f])
|
||||
list?]{
|
||||
Like @racket[list-dir/files], but keeps only paths for which
|
||||
@racket[directory-exists?] is true.
|
||||
}
|
||||
|
||||
These helpers make regexp-based cleanup concise. For example:
|
||||
|
||||
@racketblock[
|
||||
(default-target all)
|
||||
(phony all clean)
|
||||
|
||||
(target all
|
||||
(displayln "use (make clean)"))
|
||||
|
||||
(target clean
|
||||
(display "cleaning up...")
|
||||
(apply rm-rf
|
||||
(list-dirs "." #px"compiled$" #:recursive #t))
|
||||
(apply rm-f
|
||||
(list-files "." #px"(?i:(?:[.]bak|~)$)" #:recursive #t))
|
||||
(displayln "done."))
|
||||
]
|
||||
|
||||
The second regular expression is case-insensitive and matches names ending in
|
||||
@tt{.bak} or @tt{~}.
|
||||
|
||||
@section{Using ordinary Racket}
|
||||
|
||||
No separate make programming language is introduced. Definitions, functions,
|
||||
|
||||
+41
-1
@@ -2,7 +2,9 @@
|
||||
|
||||
(require rackunit
|
||||
racket/file
|
||||
(only-in racket-makefile rm-f rm-rf cleanup))
|
||||
(only-in racket-makefile
|
||||
rm-f rm-rf cleanup
|
||||
list-dir/files list-files list-dirs))
|
||||
|
||||
(define tmp (make-temporary-file "racket-makefile-test~a" 'directory))
|
||||
|
||||
@@ -25,6 +27,44 @@
|
||||
(check-false (file-exists? html))
|
||||
(check-true (file-exists? txt))
|
||||
|
||||
;; Directory/regexp helpers.
|
||||
(define top-bak (build-path tmp "TOP.BAK"))
|
||||
(call-with-output-file top-bak (lambda (out) (display "bak" out)))
|
||||
(define compiled (build-path tmp "a" "compiled"))
|
||||
(make-directory* compiled)
|
||||
(define nested-bak (build-path tmp "a" "nested.bak"))
|
||||
(call-with-output-file nested-bak (lambda (out) (display "bak" out)))
|
||||
|
||||
;; Non-recursive results are complete paths and include both files and dirs.
|
||||
(check-equal? (list-files tmp #px"(?i:[.]bak$)")
|
||||
(list top-bak))
|
||||
(check-equal? (list-dirs tmp #px"a$")
|
||||
(list (build-path tmp "a")))
|
||||
|
||||
;; Recursive variants select the requested kind directly.
|
||||
(define recursive-baks
|
||||
(list-files tmp #px"(?i:[.]bak$)" #:recursive #t))
|
||||
(check-not-false (member top-bak recursive-baks))
|
||||
(check-not-false (member nested-bak recursive-baks))
|
||||
(check-equal? (list-dirs tmp #px"compiled$" #:recursive #t)
|
||||
(list compiled))
|
||||
|
||||
;; list-dir/files returns both matching files and directories.
|
||||
(define all-a
|
||||
(list-dir/files tmp #px"(?i:(?:a|[.]bak))$" #:recursive #t))
|
||||
(check-not-false (member (build-path tmp "a") all-a))
|
||||
(check-not-false (member top-bak all-a))
|
||||
(check-not-false (member nested-bak all-a))
|
||||
|
||||
;; Intended makefile idiom: feed the path lists directly into variadic
|
||||
;; rm-rf and rm-f.
|
||||
(apply rm-rf (list-dirs tmp #px"compiled$" #:recursive #t))
|
||||
(check-false (directory-exists? compiled))
|
||||
|
||||
(apply rm-f (list-files tmp #px"(?i:[.]bak$)" #:recursive #t))
|
||||
(check-false (file-exists? top-bak))
|
||||
(check-false (file-exists? nested-bak))
|
||||
|
||||
(rm-rf (build-path tmp "a"))
|
||||
(check-false (directory-exists? (build-path tmp "a"))))
|
||||
(lambda ()
|
||||
|
||||
Reference in New Issue
Block a user