Some extra helper functions

This commit is contained in:
2026-08-08 23:36:35 +02:00
parent 57707e5fc0
commit b563d359f0
8 changed files with 183 additions and 7 deletions
+15
View File
@@ -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.
+33 -3
View File
@@ -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.
+15
View File
@@ -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 -1
View File
@@ -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
+3
View File
@@ -17,6 +17,9 @@
rm-f
rm-rf
cleanup
list-dir/files
list-files
list-dirs
$target
$deps
$<)
+20 -1
View File
@@ -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)))
+55 -1
View File
@@ -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
View File
@@ -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 ()