picomatch
picomatch copied to clipboard
The scan method returns empty parts for pattern with only a forward slash
Environment
- Windows 10
- Node.js 12.13
-
picomatch@master
Code sample
const pm = require('.');
const a = pm.scan('/', { parts: true }).parts;
console.dir(a, { colors: true });
const b = pm.isMatch('/', '/');
console.dir(b, { colors: true });
Expected behaviour
['', '']
I expect to see a representation of the pattern with each of its segments. Without empty parts of the pattern, we will not be able to apply it correctly.
For example, the current pattern must be matched only for /
(left side — <empty>
, right side — <empty>
).
Actual behaviour
[]
Similar behaviour for the following patterns:
pm.scan('/a', { parts: true }).parts → []
pm.scan('/a/b', { parts: true }).parts → [ '/a', 'b' ]
pm.scan('(!(b/a))', { parts: true }).parts → []
thanks for the issue, I'm working on it. This feedback helps.
@mrmlnc here is what I'd expect for these patterns:
pm.scan('/', { parts: true }).parts → ['', '']
pm.scan('/a', { parts: true }).parts → ['', 'a']
pm.scan('/a/b', { parts: true }).parts → ['', 'a', 'b']
pm.scan('(!(b/a))', { parts: true }).parts → ['']
I'll need to think more about the last pattern. I assume the goal is probably to create matchers for each section of a glob pattern so that you can limit fs
operations, by progressively disqualifying directories. To do that properly with extglobs, we would probably need to return a proper AST so that you can create matchers around nodes in a way that just isn't possible with a flattened array of tokens.
Edit: I have a patch ready to push up once we come to consensus on what the results should be.
IMHO, the (!(b/a))
pattern is a difficult pattern and cannot be correctly represented by parts. But in this case, you need to explicitly indicate that this is not an array with a single item with an empty string (probably bug, an empty pattern, …), but a null
or []
(empty array at all).
I correctly understand that the (a|b)/c
now will be ['(a|b)', 'c']
?
I correctly understand that the
(a|b)/c
now will be['(a|b)', 'c']
?
yes, that's correct.
you need to explicitly indicate that this is not an array with a single item with an empty string
For the pattern (!(b/a))
, IMHO the result should be ['(!(b/a))']
since the scan
method returns the segments of a pattern that can be split by un-nested slashes.
Yeah, you're quite right there. I didn't think that only one segment of the pattern should be matched to all parts of the path.
I think I have this working. I'm adding some unit tests to see if I can kill more edge cases before I push up. Please let me know if you come up with any patterns that you think are tricky and you want me to test. thx
Another case is ./directory/(a|b)/*.js
:
parts: ['directory', '(a|b)/*.js' ]
I expect that (a|b)
must be a separated part.
Source: https://github.com/mrmlnc/fast-glob/issues/263
Thank you for the additional test case.
However, do you mean that (a|b)
should actually be split into two path segments? I don't think that's right. (a|b)
is a regular expression (alternation capture group), but even if it was an extglob I don't think we'd split that pattern. IMHO, it would make more sense to do {a, b}
and use brace expansion first if that is the goal.
Thoughts?
Oh, nevermind, I completely missed the fact that there was a slash in that segment.