diff options
| -rw-r--r-- | gnu/build/linux-modules.scm | 4 | ||||
| -rw-r--r-- | guix/glob.scm | 51 | ||||
| -rw-r--r-- | tests/glob.scm | 12 |
3 files changed, 41 insertions, 26 deletions
diff --git a/gnu/build/linux-modules.scm b/gnu/build/linux-modules.scm index e97c9c95f17..87d2e98edf9 100644 --- a/gnu/build/linux-modules.scm +++ b/gnu/build/linux-modules.scm | |||
| @@ -329,7 +329,7 @@ The modules corresponding to these aliases can then be found using | |||
| 329 | list of alias/module pairs where each alias is a glob pattern as like the | 329 | list of alias/module pairs where each alias is a glob pattern as like the |
| 330 | result of: | 330 | result of: |
| 331 | 331 | ||
| 332 | (compile-glob-pattern \"scsi:t-0x01*\") | 332 | (string->compiled-sglob \"scsi:t-0x01*\") |
| 333 | 333 | ||
| 334 | and each module is a module name like \"snd_hda_intel\"." | 334 | and each module is a module name like \"snd_hda_intel\"." |
| 335 | (define (comment? str) | 335 | (define (comment? str) |
| @@ -354,7 +354,7 @@ and each module is a module name like \"snd_hda_intel\"." | |||
| 354 | (line | 354 | (line |
| 355 | (match (tokenize line) | 355 | (match (tokenize line) |
| 356 | (("alias" alias module) | 356 | (("alias" alias module) |
| 357 | (loop (alist-cons (compile-glob-pattern alias) module | 357 | (loop (alist-cons (string->compiled-sglob alias) module |
| 358 | aliases))) | 358 | aliases))) |
| 359 | (() ;empty line | 359 | (() ;empty line |
| 360 | (loop aliases))))))) | 360 | (loop aliases))))))) |
diff --git a/guix/glob.scm b/guix/glob.scm index 29c335ca1df..a9fc7448021 100644 --- a/guix/glob.scm +++ b/guix/glob.scm | |||
| @@ -18,7 +18,9 @@ | |||
| 18 | 18 | ||
| 19 | (define-module (guix glob) | 19 | (define-module (guix glob) |
| 20 | #:use-module (ice-9 match) | 20 | #:use-module (ice-9 match) |
| 21 | #:export (compile-glob-pattern | 21 | #:export (string->sglob |
| 22 | compile-sglob | ||
| 23 | string->compiled-sglob | ||
| 22 | glob-match?)) | 24 | glob-match?)) |
| 23 | 25 | ||
| 24 | ;;; Commentary: | 26 | ;;; Commentary: |
| @@ -37,9 +39,9 @@ | |||
| 37 | (lst | 39 | (lst |
| 38 | `(set ,@lst)))) | 40 | `(set ,@lst)))) |
| 39 | 41 | ||
| 40 | (define (compile-glob-pattern str) | 42 | (define (string->sglob str) |
| 41 | "Return an sexp that represents the compiled form of STR, a glob pattern | 43 | "Return an sexp, called an \"sglob\", that represents the compiled form of |
| 42 | such as \"foo*\" or \"foo??bar\"." | 44 | STR, a glob pattern such as \"foo*\" or \"foo??bar\"." |
| 43 | (define flatten | 45 | (define flatten |
| 44 | (match-lambda | 46 | (match-lambda |
| 45 | (((? string? str)) str) | 47 | (((? string? str)) str) |
| @@ -83,9 +85,33 @@ such as \"foo*\" or \"foo??bar\"." | |||
| 83 | ((chr . rest) | 85 | ((chr . rest) |
| 84 | (loop rest (cons chr pending) brackets result))))) | 86 | (loop rest (cons chr pending) brackets result))))) |
| 85 | 87 | ||
| 88 | (define (compile-sglob sglob) | ||
| 89 | "Compile SGLOB into a more efficient representation." | ||
| 90 | (if (string? sglob) | ||
| 91 | sglob | ||
| 92 | (let loop ((sglob sglob) | ||
| 93 | (result '())) | ||
| 94 | (match sglob | ||
| 95 | (() | ||
| 96 | (reverse result)) | ||
| 97 | (('? . rest) | ||
| 98 | (loop rest (cons char-set:full result))) | ||
| 99 | ((('range start end) . rest) | ||
| 100 | (loop rest (cons (ucs-range->char-set | ||
| 101 | (char->integer start) | ||
| 102 | (+ 1 (char->integer end))) | ||
| 103 | result))) | ||
| 104 | ((('set . chars) . rest) | ||
| 105 | (loop rest (cons (list->char-set chars) result))) | ||
| 106 | ((head . rest) | ||
| 107 | (loop rest (cons head result))))))) | ||
| 108 | |||
| 109 | (define string->compiled-sglob | ||
| 110 | (compose compile-sglob string->sglob)) | ||
| 111 | |||
| 86 | (define (glob-match? pattern str) | 112 | (define (glob-match? pattern str) |
| 87 | "Return true if STR matches PATTERN, a compiled glob pattern as returned by | 113 | "Return true if STR matches PATTERN, a compiled glob pattern as returned by |
| 88 | 'compile-glob-pattern'." | 114 | 'compile-sglob'." |
| 89 | (let loop ((pattern pattern) | 115 | (let loop ((pattern pattern) |
| 90 | (str str)) | 116 | (str str)) |
| 91 | (match pattern | 117 | (match pattern |
| @@ -101,21 +127,10 @@ such as \"foo*\" or \"foo??bar\"." | |||
| 101 | (index (loop rest | 127 | (index (loop rest |
| 102 | (string-drop str | 128 | (string-drop str |
| 103 | (+ index (string-length suffix))))))) | 129 | (+ index (string-length suffix))))))) |
| 104 | (('? . rest) | 130 | (((? char-set? cs) . rest) |
| 105 | (and (>= (string-length str) 1) | ||
| 106 | (loop rest (string-drop str 1)))) | ||
| 107 | ((('range start end) . rest) | ||
| 108 | (and (>= (string-length str) 1) | ||
| 109 | (let ((chr (string-ref str 0))) | ||
| 110 | (and (char-set-contains? (ucs-range->char-set | ||
| 111 | (char->integer start) | ||
| 112 | (+ 1 (char->integer end))) | ||
| 113 | chr) | ||
| 114 | (loop rest (string-drop str 1)))))) | ||
| 115 | ((('set . chars) . rest) | ||
| 116 | (and (>= (string-length str) 1) | 131 | (and (>= (string-length str) 1) |
| 117 | (let ((chr (string-ref str 0))) | 132 | (let ((chr (string-ref str 0))) |
| 118 | (and (char-set-contains? (list->char-set chars) chr) | 133 | (and (char-set-contains? cs chr) |
| 119 | (loop rest (string-drop str 1)))))) | 134 | (loop rest (string-drop str 1)))))) |
| 120 | ((prefix . rest) | 135 | ((prefix . rest) |
| 121 | (and (string-prefix? prefix str) | 136 | (and (string-prefix? prefix str) |
diff --git a/tests/glob.scm b/tests/glob.scm index 71e2d3fce07..31340697899 100644 --- a/tests/glob.scm +++ b/tests/glob.scm | |||
| @@ -23,14 +23,14 @@ | |||
| 23 | 23 | ||
| 24 | (test-begin "glob") | 24 | (test-begin "glob") |
| 25 | 25 | ||
| 26 | (define-syntax test-compile-glob-pattern | 26 | (define-syntax test-string->sglob |
| 27 | (syntax-rules (=>) | 27 | (syntax-rules (=>) |
| 28 | ((_ pattern => result rest ...) | 28 | ((_ pattern => result rest ...) |
| 29 | (begin | 29 | (begin |
| 30 | (test-equal (format #f "compile-glob-pattern, ~s" pattern) | 30 | (test-equal (format #f "string->sglob, ~s" pattern) |
| 31 | result | 31 | result |
| 32 | (compile-glob-pattern pattern)) | 32 | (string->sglob pattern)) |
| 33 | (test-compile-glob-pattern rest ...))) | 33 | (test-string->sglob rest ...))) |
| 34 | ((_) | 34 | ((_) |
| 35 | #t))) | 35 | #t))) |
| 36 | 36 | ||
| @@ -39,14 +39,14 @@ | |||
| 39 | ((_ (pattern-string matches strings ... (and not others ...)) rest ...) | 39 | ((_ (pattern-string matches strings ... (and not others ...)) rest ...) |
| 40 | (begin | 40 | (begin |
| 41 | (test-assert (format #f "glob-match? ~s" pattern-string) | 41 | (test-assert (format #f "glob-match? ~s" pattern-string) |
| 42 | (let ((pattern (compile-glob-pattern pattern-string))) | 42 | (let ((pattern (string->compiled-sglob pattern-string))) |
| 43 | (and (glob-match? pattern strings) ... | 43 | (and (glob-match? pattern strings) ... |
| 44 | (not (glob-match? pattern others)) ...))) | 44 | (not (glob-match? pattern others)) ...))) |
| 45 | (test-glob-match rest ...))) | 45 | (test-glob-match rest ...))) |
| 46 | ((_) | 46 | ((_) |
| 47 | #t))) | 47 | #t))) |
| 48 | 48 | ||
| 49 | (test-compile-glob-pattern | 49 | (test-string->sglob |
| 50 | "foo" => "foo" | 50 | "foo" => "foo" |
| 51 | "?foo*" => '(? "foo" *) | 51 | "?foo*" => '(? "foo" *) |
| 52 | "foo[1-5]" => '("foo" (range #\1 #\5)) | 52 | "foo[1-5]" => '("foo" (range #\1 #\5)) |
