Skip to content

Commit 53e16aa

Browse files
committed
include negated patterns
1 parent 01426c8 commit 53e16aa

File tree

1 file changed

+26
-12
lines changed

1 file changed

+26
-12
lines changed

extensions/cli/src/tools/searchCode.ts

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,25 @@ import { Tool } from "./types.js";
99

1010
const execPromise = util.promisify(child_process.exec);
1111

12-
async function getGitignorePatterns() {
12+
async function getGitignorePatterns(): Promise<{
13+
ignorePatterns: string[];
14+
negatedPatterns: string[];
15+
}> {
1316
const gitIgnorePath = await findUp(".gitignore");
14-
if (!gitIgnorePath) return [];
17+
if (!gitIgnorePath) return { ignorePatterns: [], negatedPatterns: [] };
1518
const content = fs.readFileSync(gitIgnorePath, "utf-8");
16-
const ignorePatterns = [];
19+
const ignorePatterns: string[] = [];
20+
const negatedPatterns: string[] = [];
1721
for (let line of content.trim().split("\n")) {
1822
line = line.trim();
19-
if (line.startsWith("#") || line === "") continue; // ignore comments and empty line
20-
if (line.startsWith("!")) continue; // ignore negated ignores
21-
ignorePatterns.push(line);
23+
if (line.startsWith("#") || line === "") continue;
24+
if (line.startsWith("!")) {
25+
negatedPatterns.push(line.slice(1));
26+
} else {
27+
ignorePatterns.push(line);
28+
}
2229
}
23-
return ignorePatterns;
30+
return { ignorePatterns, negatedPatterns };
2431
}
2532

2633
// procedure 1: search with ripgrep
@@ -44,10 +51,13 @@ async function searchWithRipgrep(
4451
command += ` -g "${filePattern}"`;
4552
}
4653

47-
const ignorePatterns = await getGitignorePatterns();
54+
const { ignorePatterns, negatedPatterns } = await getGitignorePatterns();
4855
for (const ignorePattern of ignorePatterns) {
4956
command += ` -g "!${ignorePattern}"`;
5057
}
58+
for (const negatedPattern of negatedPatterns) {
59+
command += ` -g "${negatedPattern}"`;
60+
}
5161

5262
command += ` "${searchPath}"`;
5363
const { stdout, stderr } = await execPromise(command);
@@ -61,20 +71,24 @@ async function searchWithGrepOrFindstr(
6171
filePattern?: string,
6272
) {
6373
const isWindows = process.platform === "win32";
64-
const ignorePatterns = await getGitignorePatterns();
74+
const { ignorePatterns, negatedPatterns } = await getGitignorePatterns();
6575
let command: string;
6676
if (isWindows) {
6777
const fileSpec = filePattern ? filePattern : "*";
6878
command = `findstr /S /N /P /R "${pattern}" "${fileSpec}"`; // findstr does not support ignoring patterns
6979
} else {
7080
let excludeArgs = "";
7181
for (const ignorePattern of ignorePatterns) {
72-
excludeArgs += ` --exclude="${ignorePattern}" --exclude-dir="${ignorePattern}"`; // use both exclude and exclude-dir because ignorePattern can be a file or directory
82+
excludeArgs += ` --exclude="${ignorePattern}" --exclude-dir="${ignorePattern}"`;
83+
}
84+
let includeArgs = "";
85+
for (const negatedPattern of negatedPatterns) {
86+
includeArgs += ` --include="${negatedPattern}"`;
7387
}
7488
if (filePattern) {
75-
command = `find . -type f -path "${filePattern}" -print0 | xargs -0 grep -nH -I${excludeArgs} "${pattern}"`;
89+
command = `grep -R -n -H -I${excludeArgs}${includeArgs} --include="${filePattern}" "${pattern}" .`;
7690
} else {
77-
command = `grep -R -n -H -I${excludeArgs} "${pattern}" .`;
91+
command = `grep -R -n -H -I${excludeArgs}${includeArgs} "${pattern}" .`;
7892
}
7993
}
8094
return await execPromise(command, { cwd: searchPath });

0 commit comments

Comments
 (0)