]> gitweb.factorcode.org Git - factor.git/blobdiff - basis/globs/globs.factor
basis: use lint.vocabs tool to trim using lists
[factor.git] / basis / globs / globs.factor
index e72cd007d6dd344bc706282da421e01f1dcd6301..3cb4ed094e0bbe0c608710b448063ef324b374bf 100644 (file)
@@ -1,15 +1,18 @@
 ! Copyright (C) 2007, 2009 Slava Pestov, Daniel Ehrenberg.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays combinators combinators.short-circuit
-io.directories io.files io.files.info io.pathnames kernel locals
+io.directories io.files io.files.info io.pathnames kernel
 make peg.ebnf regexp regexp.combinators sequences strings system
-unicode ;
+unicode multiline ;
 IN: globs
 
 : not-path-separator ( -- sep )
-    os windows? R/ [^\\/\\]/ R/ [^\\/]/ ? ; foldable
+    os windows? R/ [^\/\\]/ R/ [^\/]/ ? ; foldable
 
-EBNF: <glob>
+: wild-path-separator ( -- sep )
+    os windows? R/ [^\/\\][\/\\]|[^\/\\]/ R/ [^\/][\/]|[^\/]/ ? ; foldable
+
+EBNF: <glob> [=[
 
 Character = "\\" .:c => [[ c 1string <literal> ]]
           | !(","|"}") . => [[ 1string <literal> ]]
@@ -29,7 +32,8 @@ CharClass = "^"?:n Ranges:e => [[ e <or> n [ <not> ] when ]]
 AlternationBody = Concatenation:c "," AlternationBody:a => [[ a c prefix ]]
                 | Concatenation => [[ 1array ]]
 
-Element = "*" => [[ not-path-separator <zero-or-more> ]]
+Element = "**" => [[ wild-path-separator <zero-or-more> ]]
+        | "*" => [[ not-path-separator <zero-or-more> ]]
         | "?" => [[ not-path-separator ]]
         | "[" CharClass:c "]" => [[ c ]]
         | "{" AlternationBody:b "}" => [[ b <or> ]]
@@ -41,7 +45,7 @@ End = !(.)
 
 Main = Concatenation End
 
-;EBNF
+]=]
 
 : glob-matches? ( input glob -- ? )
     [ >case-fold ] bi@ <glob> matches? ;
@@ -56,16 +60,16 @@ Main = Concatenation End
 ! TODO: make case-fold an option, off by default
 ! TODO: maybe make case-fold an option on regexp
 
-DEFER: glob-directory%
+DEFER: glob%
 
 : glob-entries ( path -- entries )
     directory-entries [ name>> "." head? ] reject ;
 
-: ?glob-directory% ( root remaining entry -- )
+: ?glob% ( root remaining entry -- )
     over empty? [
         2drop ,
     ] [
-        directory? [ glob-directory% ] [ 2drop ] if
+        directory? [ glob% ] [ 2drop ] if
     ] if ;
 
 :: glob-wildcard% ( root globs -- )
@@ -90,7 +94,7 @@ DEFER: glob-directory%
                          dup ,
                     ] [
                         entry directory? [
-                            dupd glob-directory%
+                            dupd glob%
                         ] [
                             drop
                         ] if
@@ -100,7 +104,7 @@ DEFER: glob-directory%
         } cond
 
         { [ entry directory? ] [ next-glob ] } 0&& [
-            globs glob-directory%
+            globs glob%
         ] [
             drop
         ] if
@@ -112,20 +116,20 @@ DEFER: glob-directory%
     root glob-entries [| entry |
         entry name>> >case-fold glob matches? [
             root entry name>> append-path
-            remaining entry ?glob-directory%
+            remaining entry ?glob%
         ] when
     ] each ;
 
 :: glob-literal% ( root globs -- )
     globs unclip :> ( remaining glob )
 
-    root glob append-path dup exists? [
-        remaining over file-info ?glob-directory%
+    root glob append-path dup file-exists? [
+        remaining over file-info ?glob%
     ] [
         drop
     ] if ;
 
-: glob-directory% ( root globs -- )
+: glob% ( root globs -- )
     dup ?first {
         { f [ 2drop ] }
         { "**" [ glob-wildcard% ] }
@@ -151,5 +155,7 @@ DEFER: glob-directory%
 
 PRIVATE>
 
-: glob-directory ( glob -- files )
-    glob-path [ glob-directory% ] { } make ;
+: glob ( glob -- files )
+    glob-path [
+        [ 1array f swap ] when-empty glob%
+    ] { } make ;