chore: add proper pluralization handling for match in grep tool (#2344)
Co-authored-by: Allen Hutchison <adh@google.com>
This commit is contained in:
parent
25cdf9b762
commit
9665928860
|
@ -159,7 +159,7 @@ The Gemini CLI provides a comprehensive suite of tools for interacting with the
|
||||||
- Returns a list of matching lines, each prefixed with its file path (relative to the search directory) and line number.
|
- Returns a list of matching lines, each prefixed with its file path (relative to the search directory) and line number.
|
||||||
- **Output (`llmContent`):** A formatted string of matches, e.g.:
|
- **Output (`llmContent`):** A formatted string of matches, e.g.:
|
||||||
```
|
```
|
||||||
Found 3 match(es) for pattern "myFunction" in path "." (filter: "*.ts"):
|
Found 3 matches for pattern "myFunction" in path "." (filter: "*.ts"):
|
||||||
---
|
---
|
||||||
File: src/utils.ts
|
File: src/utils.ts
|
||||||
L15: export function myFunction() {
|
L15: export function myFunction() {
|
||||||
|
|
|
@ -115,38 +115,38 @@ describe('GrepTool', () => {
|
||||||
const params: GrepToolParams = { pattern: 'world' };
|
const params: GrepToolParams = { pattern: 'world' };
|
||||||
const result = await grepTool.execute(params, abortSignal);
|
const result = await grepTool.execute(params, abortSignal);
|
||||||
expect(result.llmContent).toContain(
|
expect(result.llmContent).toContain(
|
||||||
'Found 3 match(es) for pattern "world" in path "."',
|
'Found 3 matches for pattern "world" in path "."',
|
||||||
);
|
);
|
||||||
expect(result.llmContent).toContain('File: fileA.txt');
|
expect(result.llmContent).toContain('File: fileA.txt');
|
||||||
expect(result.llmContent).toContain('L1: hello world');
|
expect(result.llmContent).toContain('L1: hello world');
|
||||||
expect(result.llmContent).toContain('L2: second line with world');
|
expect(result.llmContent).toContain('L2: second line with world');
|
||||||
expect(result.llmContent).toContain('File: sub/fileC.txt');
|
expect(result.llmContent).toContain('File: sub/fileC.txt');
|
||||||
expect(result.llmContent).toContain('L1: another world in sub dir');
|
expect(result.llmContent).toContain('L1: another world in sub dir');
|
||||||
expect(result.returnDisplay).toBe('Found 3 matche(s)');
|
expect(result.returnDisplay).toBe('Found 3 matches');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find matches in a specific path', async () => {
|
it('should find matches in a specific path', async () => {
|
||||||
const params: GrepToolParams = { pattern: 'world', path: 'sub' };
|
const params: GrepToolParams = { pattern: 'world', path: 'sub' };
|
||||||
const result = await grepTool.execute(params, abortSignal);
|
const result = await grepTool.execute(params, abortSignal);
|
||||||
expect(result.llmContent).toContain(
|
expect(result.llmContent).toContain(
|
||||||
'Found 1 match(es) for pattern "world" in path "sub"',
|
'Found 1 match for pattern "world" in path "sub"',
|
||||||
);
|
);
|
||||||
expect(result.llmContent).toContain('File: fileC.txt'); // Path relative to 'sub'
|
expect(result.llmContent).toContain('File: fileC.txt'); // Path relative to 'sub'
|
||||||
expect(result.llmContent).toContain('L1: another world in sub dir');
|
expect(result.llmContent).toContain('L1: another world in sub dir');
|
||||||
expect(result.returnDisplay).toBe('Found 1 matche(s)');
|
expect(result.returnDisplay).toBe('Found 1 match');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find matches with an include glob', async () => {
|
it('should find matches with an include glob', async () => {
|
||||||
const params: GrepToolParams = { pattern: 'hello', include: '*.js' };
|
const params: GrepToolParams = { pattern: 'hello', include: '*.js' };
|
||||||
const result = await grepTool.execute(params, abortSignal);
|
const result = await grepTool.execute(params, abortSignal);
|
||||||
expect(result.llmContent).toContain(
|
expect(result.llmContent).toContain(
|
||||||
'Found 1 match(es) for pattern "hello" in path "." (filter: "*.js")',
|
'Found 1 match for pattern "hello" in path "." (filter: "*.js")',
|
||||||
);
|
);
|
||||||
expect(result.llmContent).toContain('File: fileB.js');
|
expect(result.llmContent).toContain('File: fileB.js');
|
||||||
expect(result.llmContent).toContain(
|
expect(result.llmContent).toContain(
|
||||||
'L2: function baz() { return "hello"; }',
|
'L2: function baz() { return "hello"; }',
|
||||||
);
|
);
|
||||||
expect(result.returnDisplay).toBe('Found 1 matche(s)');
|
expect(result.returnDisplay).toBe('Found 1 match');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find matches with an include glob and path', async () => {
|
it('should find matches with an include glob and path', async () => {
|
||||||
|
@ -161,11 +161,11 @@ describe('GrepTool', () => {
|
||||||
};
|
};
|
||||||
const result = await grepTool.execute(params, abortSignal);
|
const result = await grepTool.execute(params, abortSignal);
|
||||||
expect(result.llmContent).toContain(
|
expect(result.llmContent).toContain(
|
||||||
'Found 1 match(es) for pattern "hello" in path "sub" (filter: "*.js")',
|
'Found 1 match for pattern "hello" in path "sub" (filter: "*.js")',
|
||||||
);
|
);
|
||||||
expect(result.llmContent).toContain('File: another.js');
|
expect(result.llmContent).toContain('File: another.js');
|
||||||
expect(result.llmContent).toContain('L1: const greeting = "hello";');
|
expect(result.llmContent).toContain('L1: const greeting = "hello";');
|
||||||
expect(result.returnDisplay).toBe('Found 1 matche(s)');
|
expect(result.returnDisplay).toBe('Found 1 match');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return "No matches found" when pattern does not exist', async () => {
|
it('should return "No matches found" when pattern does not exist', async () => {
|
||||||
|
@ -181,7 +181,7 @@ describe('GrepTool', () => {
|
||||||
const params: GrepToolParams = { pattern: 'foo.*bar' }; // Matches 'const foo = "bar";'
|
const params: GrepToolParams = { pattern: 'foo.*bar' }; // Matches 'const foo = "bar";'
|
||||||
const result = await grepTool.execute(params, abortSignal);
|
const result = await grepTool.execute(params, abortSignal);
|
||||||
expect(result.llmContent).toContain(
|
expect(result.llmContent).toContain(
|
||||||
'Found 1 match(es) for pattern "foo.*bar" in path "."',
|
'Found 1 match for pattern "foo.*bar" in path "."',
|
||||||
);
|
);
|
||||||
expect(result.llmContent).toContain('File: fileB.js');
|
expect(result.llmContent).toContain('File: fileB.js');
|
||||||
expect(result.llmContent).toContain('L1: const foo = "bar";');
|
expect(result.llmContent).toContain('L1: const foo = "bar";');
|
||||||
|
@ -191,7 +191,7 @@ describe('GrepTool', () => {
|
||||||
const params: GrepToolParams = { pattern: 'HELLO' };
|
const params: GrepToolParams = { pattern: 'HELLO' };
|
||||||
const result = await grepTool.execute(params, abortSignal);
|
const result = await grepTool.execute(params, abortSignal);
|
||||||
expect(result.llmContent).toContain(
|
expect(result.llmContent).toContain(
|
||||||
'Found 2 match(es) for pattern "HELLO" in path "."',
|
'Found 2 matches for pattern "HELLO" in path "."',
|
||||||
);
|
);
|
||||||
expect(result.llmContent).toContain('File: fileA.txt');
|
expect(result.llmContent).toContain('File: fileA.txt');
|
||||||
expect(result.llmContent).toContain('L1: hello world');
|
expect(result.llmContent).toContain('L1: hello world');
|
||||||
|
|
|
@ -213,7 +213,10 @@ export class GrepTool extends BaseTool<GrepToolParams, ToolResult> {
|
||||||
{} as Record<string, GrepMatch[]>,
|
{} as Record<string, GrepMatch[]>,
|
||||||
);
|
);
|
||||||
|
|
||||||
let llmContent = `Found ${matches.length} match(es) for pattern "${params.pattern}" in path "${searchDirDisplay}"${params.include ? ` (filter: "${params.include}")` : ''}:\n---\n`;
|
const matchCount = matches.length;
|
||||||
|
const matchTerm = matchCount === 1 ? 'match' : 'matches';
|
||||||
|
|
||||||
|
let llmContent = `Found ${matchCount} ${matchTerm} for pattern "${params.pattern}" in path "${searchDirDisplay}"${params.include ? ` (filter: "${params.include}")` : ''}:\n---\n`;
|
||||||
|
|
||||||
for (const filePath in matchesByFile) {
|
for (const filePath in matchesByFile) {
|
||||||
llmContent += `File: ${filePath}\n`;
|
llmContent += `File: ${filePath}\n`;
|
||||||
|
@ -226,7 +229,7 @@ export class GrepTool extends BaseTool<GrepToolParams, ToolResult> {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
llmContent: llmContent.trim(),
|
llmContent: llmContent.trim(),
|
||||||
returnDisplay: `Found ${matches.length} matche(s)`,
|
returnDisplay: `Found ${matchCount} ${matchTerm}`,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error during GrepLogic execution: ${error}`);
|
console.error(`Error during GrepLogic execution: ${error}`);
|
||||||
|
|
Loading…
Reference in New Issue