diff --git a/packages/core/src/utils/filesearch/fileSearch.test.ts b/packages/core/src/utils/filesearch/fileSearch.test.ts index 2deea82d..316f17ec 100644 --- a/packages/core/src/utils/filesearch/fileSearch.test.ts +++ b/packages/core/src/utils/filesearch/fileSearch.test.ts @@ -566,6 +566,35 @@ describe('FileSearch', () => { expect(limitedResults).toEqual(['file1.js', 'file2.js']); }); + it('should handle file paths with special characters that need escaping', async () => { + tmpDir = await createTmpDir({ + src: { + 'file with (special) chars.txt': '', + 'another-file.txt': '', + }, + }); + + const fileSearch = FileSearchFactory.create({ + projectRoot: tmpDir, + useGitignore: false, + useGeminiignore: false, + ignoreDirs: [], + cache: false, + cacheTtl: 0, + enableRecursiveFileSearch: true, + }); + + await fileSearch.initialize(); + + // Search for the file using a pattern that contains special characters. + // The `unescapePath` function should handle the escaped path correctly. + const results = await fileSearch.search( + 'src/file with \\(special\\) chars.txt', + ); + + expect(results).toEqual(['src/file with (special) chars.txt']); + }); + describe('DirectoryFileSearch', () => { it('should search for files in the current directory', async () => { tmpDir = await createTmpDir({ diff --git a/packages/core/src/utils/filesearch/fileSearch.ts b/packages/core/src/utils/filesearch/fileSearch.ts index fa36dab4..876d37f0 100644 --- a/packages/core/src/utils/filesearch/fileSearch.ts +++ b/packages/core/src/utils/filesearch/fileSearch.ts @@ -10,6 +10,7 @@ import { Ignore, loadIgnoreRules } from './ignore.js'; import { ResultCache } from './result-cache.js'; import { crawl } from './crawler.js'; import { AsyncFzf, FzfResultItem } from 'fzf'; +import { unescapePath } from '../paths.js'; export interface FileSearchOptions { projectRoot: string; @@ -116,7 +117,7 @@ class RecursiveFileSearch implements FileSearch { throw new Error('Engine not initialized. Call initialize() first.'); } - pattern = pattern || '*'; + pattern = unescapePath(pattern) || '*'; let filteredCandidates; const { files: candidates, isExactMatch } =