Skip to content

Commit f00e215

Browse files
[find-and-replace] Ensure a pattern without any path separators… (#1544)
* [find-and-replace] Ensure a pattern without any path separators… …will be applied against only the filename rather than the entire path. For example: `*.js` should search all JavaScript files, not just the ones at the project root. * (Forgot about negated patterns!) * Fix comment * (I thought I removed this)
1 parent 3808d11 commit f00e215

2 files changed

Lines changed: 36 additions & 4 deletions

File tree

spec/workspace-spec.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2279,6 +2279,20 @@ describe('Workspace', () => {
22792279
atom.workspace.filePathMatchesPatterns(pathB1, ['!b-dir/*.js'])
22802280
).toBe(false);
22812281

2282+
expect(
2283+
atom.workspace.filePathMatchesPatterns(pathA1, ['*.js'])
2284+
).toBe(true);
2285+
expect(
2286+
atom.workspace.filePathMatchesPatterns(pathB1, ['*.js'])
2287+
).toBe(true);
2288+
2289+
expect(
2290+
atom.workspace.filePathMatchesPatterns(pathA1, ['!*.js'])
2291+
).toBe(false);
2292+
expect(
2293+
atom.workspace.filePathMatchesPatterns(pathB1, ['!*.js'])
2294+
).toBe(false);
2295+
22822296
expect(
22832297
atom.workspace.filePathMatchesPatterns(pathA1, positiveGlobs)
22842298
).toBe(false);

src/workspace.js

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,33 @@ function filePathMatchesGlob(filePath, matcher) {
4242
return matcher.negate ? true : false;
4343
}
4444

45-
// Trim trailing path separators from the ends of patterns. This makes it so
46-
// that `foo/` and `foo` are treated identically.
45+
// Transform a pattern prior to handing it off to `minimatch`.
4746
function normalizePattern (rawPath) {
47+
// Strip any trailing path separator.
4848
// The path separator is `\` on Windows, but we also allow usage of `/`;
4949
// hence we check for both here.
5050
if (rawPath.endsWith(path.sep) || rawPath.endsWith('/')) {
51-
return rawPath.substring(0, rawPath.length - 1);
51+
rawPath = rawPath.substring(0, rawPath.length - 1);
5252
}
53-
return rawPath;
53+
54+
// Keep any path negation separate from the rest, since it needs to stay at
55+
// the beginning no matter what.
56+
let negation = '';
57+
if (rawPath.startsWith('!')) {
58+
rawPath = rawPath.slice(1);
59+
negation = '!';
60+
}
61+
62+
// If a user searches for (e.g.) `*.js`, we want to search all `.js` files
63+
// anywhere in the project, not just in the root. That means we should treat
64+
// patterns as implicitly prepending `**/` if they contain no path separators.
65+
//
66+
// NOTE: This is stricter than VS Code's approach, which is to prepend `**/`
67+
// to _all_ patterns unless the user specifically opts out by starting a
68+
// path with `/`. This would make plenty of sense for us, but would be a
69+
// change in behavior, so for now we're going with this as a compromise.
70+
let prefix = (rawPath.includes(path.sep) || rawPath.includes('/')) ? '' : `**${path.sep}`;
71+
return `${negation}${prefix}${rawPath}`;
5472
}
5573

5674
// Given a path pattern like `foo/bar/baz` and a list of the current root path

0 commit comments

Comments
 (0)