olson-sean-k / wax

Opinionated and portable globs that can be matched against paths and directory trees.
https://glob.guide
MIT License
112 stars 10 forks source link

How to represent "don't match" #55

Closed milesj closed 8 months ago

milesj commented 8 months ago

@olson-sean-k

I'm trying to convert some JS globs to an equivalent wax glob and they support a concept of "matching anything but this / don't match this pattern" using the syntax !(pat): https://github.com/micromatch/picomatch#extglobs

For the other ext globs, I can use <pat:x,x> but the don't match doesn't seem possible, since <pat:0,0> is not allowed? Is there a way to achieve this in wax?

olson-sean-k commented 8 months ago

Wax does not support negations in glob expressions with the sole exception of character classes (e.g., [!0-9]). Negations are supported in APIs, but these negations are complete and cannot isolate sub-expressions. This means that some picomatch globs cannot be directly represented in Wax.

If the globs you're porting are static or you otherwise know ahead of time whether or not they require negations, then it may be possible to express them as a positive glob and some number of negative globs. From there, matching against a directory tree can be done with walk and not while matching against a particular path can be done with is_match and an appropriate Boolean expression.

For example, the extglob !(foo).!(bar) can be decomposed into the positive glob *.* and the negative glob foo?bar. To match against a directory tree:

let positive = Glob::new("*.*").unwrap();
let negative = Glob::new("foo?bar").unwrap();

for entry in positive.walk(".").not([negative]).unwrap() { ... }

And to match against a particular path:

let candidate = Path::new("foo.bar");

let positive = Glob::new("*.*").unwrap();
let negative = Glob::new("foo?bar").unwrap();

if positive.is_match(&candidate) && !negative.is_match(&candidate) { ... }

I don't currently plan to support patterns like !(pattern) as seen in picomatch. Wax targets regex, which intentionally does not support this for (worst-case) performance reasons. Performance is of course not always a problem or concern (and file paths are typically a very small haystack), but I'd prefer to continue targeting regex and tend to agree with its choice.

milesj commented 8 months ago

Thanks for the insightful and deep response! I assumed it was because of some limitation/decision. We can definitely work around this.

I'll close this since it's been answered.