diff --git a/README.md b/README.md index 22e589c..ce0f4bc 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,42 @@ relative to a base the same way. It also has some functions to work with the It assumes either Windows or POSIX-style separators. +### Glob matching + +`matches?` checks a path against a glob pattern, and `matching` keeps the paths +in an array that match one, in order. Both are lexical as well and never touch +the filesystem, and both take the path first, like everything else here — note +that this is the opposite of `Pattern.matches?` in core. + +```clojure +(Path.matches? "src/main.carp" "src/*.carp") ; => true +(Path.matching &[@"a.carp" @"b.c"] "*.carp") ; => [@"a.carp"] +(Path.matching &[@"a.carp" @"t/b.carp"] "**/*.carp") ; => [@"a.carp" @"t/b.carp"] +``` + +| Form | Meaning | +|----------|------------------------------------------------------| +| `?` | exactly one character, never a separator | +| `*` | zero or more characters, never a separator | +| `**` | zero or more whole segments, as an entire segment | +| `[abc]` | one of the characters in the class | +| `[a-z]` | one character from the range | +| `[!abc]` | one character not in the class (`[^abc]` also works) | +| `\*` | a literal `*`, on POSIX | + +`**` is only a segment wildcard when it is the whole segment, so `**/*.carp` +matches both `a.carp` and `x/y/a.carp`, while `a**b` is just `a*b`. On POSIX a +`\` escapes the next pattern character; on Windows `\` is a separator, so +escaping is disabled there. A trailing `\` and an unterminated `[` are matched +as literal characters, which is why `matches?` is a plain `Bool` and not a +`Result`. Separators are structural and cannot be escaped away: `a\/b` splits +into segments just like `a/b`, and a class holding one, such as `[a/]`, matches +its other members but never the separator. + +Leading dots are not special: `*` matches `.hidden`. Matching happens on the +path exactly as given, with no normalization, so run it through `normalize` +first if `.`, `..` or repeated separators should not get in the way. + Look at [the documentation](https://carpentry.dev/path) for more information.
+ (Fn [(Ref String a), (Ref String b)] Bool) +
++ (matches? p pattern) ++
+
checks whether the path p matches the glob pattern.
The path comes first, like everywhere else in this module — note that this is
+the opposite of Pattern.matches? in core:
(matches? "src/main.carp" "src/*.carp") ; => true
+
+The pattern language is:
+? exactly one character, never a separator
+* zero or more characters, never a separator
+** zero or more whole segments, as an entire segment
+[abc] one of the characters in the class
+[a-z] one character from the range
+[!abc] one character not in the class ([^abc] works too)
+\* a literal *, on POSIX (see below)
+
+** is only a segment wildcard when it is the whole segment, so **/*.carp
+matches both a.carp and x/y/a.carp, while a**b is just a*b. Inside a
+class, a ] directly after the [ (or after the !/^) is a literal ], and
+a - first or last is a literal -.
On POSIX a \ escapes the next pattern character. On Windows \ is a
+separator, so escaping is disabled there. A trailing \ and an unterminated
+[ are matched as literal characters, which is why this is a total function and
+not a Result.
Separators are structural and cannot be escaped away: a\/b splits into
+segments just like a/b, and a class holding one, such as [a/], matches its
+other members but never the separator.
Leading dots are not special: * matches .hidden. Matching happens on the
+path exactly as given, with no normalization and no collapsing of repeated
+separators — run it through normalize first if you want that.
+ (Fn [(Ref (Array String) a), (Ref String b)] (Array String)) +
++ (matching ps pattern) ++
+
keeps the paths in ps that match the glob pattern,
+preserving their order.
It is matches? over an array, which is usually what you want:
+(matching &[@"a.carp" @"a.c"] "*.carp") ; => [@"a.carp"]
+
+
+
+