aboutsummaryrefslogtreecommitdiff
path: root/guix/build/utils.scm
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2012-07-07 16:25:10 +0200
committerLudovic Courtès <ludo@gnu.org>2012-07-07 16:25:10 +0200
commit10c87717bd70c9d7e47a13753dc2756a97f00e35 (patch)
tree0285a8c55f1db2d58a9388e2366201a2cba75c7d /guix/build/utils.scm
parentd767288490c0d2edc1b64fb99994571ddcc08f0f (diff)
downloadgnu-guix-10c87717bd70c9d7e47a13753dc2756a97f00e35.tar
gnu-guix-10c87717bd70c9d7e47a13753dc2756a97f00e35.tar.gz
utils: Introduce `substitute*', for easier sed-like syntax.
* guix/build/utils.scm (let-matches, substitute*): New macros. * distro/base.scm (guile-1.8): Use `substitute*' instead of `substitute'. Remove the #:modules argument.
Diffstat (limited to 'guix/build/utils.scm')
-rw-r--r--guix/build/utils.scm40
1 files changed, 39 insertions, 1 deletions
diff --git a/guix/build/utils.scm b/guix/build/utils.scm
index 1808c63ce5..19728e6015 100644
--- a/guix/build/utils.scm
+++ b/guix/build/utils.scm
@@ -28,7 +28,8 @@
alist-cons-before
alist-cons-after
alist-replace
- substitute))
+ substitute
+ substitute*))
;;;
@@ -175,6 +176,43 @@ MATCH OUTPUT-PORT)."
(lambda (key . args)
(false-if-exception (delete-file template))))))
+
+(define-syntax let-matches
+ ;; Helper macro for `substitute*'.
+ (syntax-rules (_)
+ ((let-matches index match (_ vars ...) body ...)
+ (let-matches (+ 1 index) match (vars ...)
+ body ...))
+ ((let-matches index match (var vars ...) body ...)
+ (let ((var (match:substring match index)))
+ (let-matches (+ 1 index) match (vars ...)
+ body ...)))
+ ((let-matches index match () body ...)
+ (begin body ...))))
+
+(define-syntax-rule (substitute* file (regexp whole-match match ...)
+ body ...)
+ "Substitute REGEXP in FILE by the string returned by BODY. BODY is
+evaluated with each MATCH-VAR bound to the corresponding positional regexp
+sub-expression. For example:
+
+ (substitute* file (\"foo([a-z]+)bar(.*)$\" all letters end)
+ (string-append \"baz\" letters end))
+
+Here, anytime a line of FILE matches the regexp, ALL is bound to the complete
+match, LETTERS is bound to the first sub-expression, and END is bound to the
+last one. Alternatively, given that `all' is not used, one can write:
+
+ (substitute* file (\"foo([a-z]+)bar(.*)$\" _ letters end)
+ (string-append \"baz\" letter end))
+
+"
+ (substitute file regexp
+ (lambda (m p)
+ (let-matches 0 m (whole-match match ...)
+ (display (begin body ...) p)))))
+
+
;;; Local Variables:
;;; eval: (put 'call-with-output-file/atomic 'scheme-indent-function 1)
;;; eval: (put 'with-throw-handler 'scheme-indent-function 1)