Skip to content

Conversation

@dmitrivMS
Copy link
Contributor

@dmitrivMS dmitrivMS commented Oct 29, 2025

Second step towards fixing #10633 and many related duplicates.

This PR adds an option to enable case-insensitive ripgrep and file search, in part by using case-insensitive glob support.
The new option is not used here and default behavior is the same as before.
The option will be used by follow up PRs to enable case-insensitive behavior in various features.

Copilot AI review requested due to automatic review settings October 29, 2025 02:18
@dmitrivMS dmitrivMS self-assigned this Oct 29, 2025
@dmitrivMS dmitrivMS linked an issue Oct 29, 2025 that may be closed by this pull request
@dmitrivMS dmitrivMS added the file-glob File glob engine label Oct 29, 2025
@dmitrivMS dmitrivMS added the search Search widget and operation issues label Oct 29, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for case-insensitive glob pattern matching in the search functionality. The main changes include:

  • Adding ignoreGlobPatternCase property to query interfaces and type definitions
  • Passing ignoreCase options to glob parsing and matching functions
  • Using case-insensitive string comparisons where appropriate
  • Fixing several spelling errors in comments (e.g., "sibilings" → "siblings", "shoudn't" → "shouldn't", "naieve" → "naive", "Preservering" → "Preserving", "expectred" → "expected", "ouside" → "outside")

Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/vs/workbench/services/search/worker/localFileSearch.ts Adds ignoreGlobPatternCase to glob options, passes to IgnoreFile, and fixes "siblings" typo
src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts Passes ignoreGlobPatternCase to ripgrep options and adds glob-case-insensitive flags
src/vs/workbench/services/search/node/ripgrepSearchProvider.ts Combines ignoreGlobPatternCase from multiple sources
src/vs/workbench/services/search/node/ripgrepFileSearch.ts Adds case-insensitive glob flags for ripgrep
src/vs/workbench/services/search/node/fileSearch.ts Uses strings.equals for case-insensitive file pattern matching
src/vs/workbench/services/search/common/textSearchManager.ts Fixes "shouldn't" typo and passes ignoreGlobPatternCase to options
src/vs/workbench/services/search/common/searchExtTypes.ts Adds ignoreGlobPatternCase documentation to interfaces
src/vs/workbench/services/search/common/search.ts Adds ignoreGlobPatternCase to query interfaces and uses in path matching
src/vs/workbench/services/search/common/queryBuilder.ts Adds ignoreGlobPatternCase to query builder options
src/vs/workbench/services/search/common/ignoreFile.ts Adds ignoreCase parameter and fixes multiple spelling errors
src/vs/workbench/services/search/common/fileSearchManager.ts Uses strings.equals for case-insensitive comparisons

dmitrivMS and others added 17 commits October 28, 2025 23:45
Rename `ChatService.getHistory` to `getLocalSessionHistory`
Consolidate duplicated UpdateTracker code in promptsServiceImpl.ts
…aquamarine

Update merge and diff-multiple icons in codicons
Noticed this when working on edit sessions, this seems like what the intended behavior should be
…rsor (#273833)

* Initial plan

* Fix cursor navigation in wrapped lines

Change cursor position check to only enable history navigation when cursor is at line 1, column 1. This prevents accidental history navigation when pressing up arrow on wrapped lines.

Co-authored-by: alexdima <5047891+alexdima@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: alexdima <5047891+alexdima@users.noreply.github.com>
…am-tan

titlebar: reduce Command Center spacer icon horizontal padding to 8px
searchService: ISearchService
): Promise<{ folders: URI[]; files: URI[] }> {
const segmentMatchPattern = caseInsensitiveGlobPattern(fuzzyMatch ? fuzzyMatchingGlobPattern(pattern) : continousMatchingGlobPattern(pattern));
const segmentMatchPattern = fuzzyMatch ? fuzzyMatchingGlobPattern(pattern) : continuousMatchingGlobPattern(pattern);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

caseInsensitiveGlobPattern() was used to make case-insensitive glob matching. Removed this method and passing { ignoreCase: true } to the glob.match() call below instead.

cacheKey,
excludePattern: searchExcludePattern,
sortByScore: true,
ignoreGlobPatternCase: true
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on glob case-insensitivity, assuming that we want case-insensitive search here, so passing ignoreGlobPatternCase: true to the search service.

private async searchInWorkspace(patternLowercase: string, root: ExplorerItem, rootIndex: number, isFuzzyMatch: boolean, token: CancellationToken): Promise<{ explorerRoot: ExplorerItem; files: URI[]; directories: URI[]; hitMaxResults: boolean }> {
const segmentMatchPattern = caseInsensitiveGlobPattern(isFuzzyMatch ? fuzzyMatchingGlobPattern(patternLowercase) : continousMatchingGlobPattern(patternLowercase));
private async searchInWorkspace(pattern: string, root: ExplorerItem, rootIndex: number, isFuzzyMatch: boolean, token: CancellationToken): Promise<{ explorerRoot: ExplorerItem; files: URI[]; directories: URI[]; hitMaxResults: boolean }> {
const segmentMatchPattern = isFuzzyMatch ? fuzzyMatchingGlobPattern(pattern) : continuousMatchingGlobPattern(pattern);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

caseInsensitiveGlobPattern() was used to make case-insensitive glob matching. Removed this method and passing { ignoreCase: true } to the glob.match() call below instead.

shouldGlobMatchFilePattern: true,
cacheKey: `explorerfindprovider:${root.name}:${rootIndex}:${this.sessionId}`,
excludePattern: searchExcludePattern,
ignoreGlobPatternCase: true
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on glob case-insensitivity, assuming that we want case-insensitive search here, so passing ignoreGlobPatternCase: true to the search service.

const uri = URI.file(path);
if (extUri.isEqualOrParent(uri, searchPath)) {
const folderGlobOptions = { ignoreCase: queryProps.ignoreGlobPatternCase || fq.ignoreGlobPatternCase };
if (extUri.isEqualOrParent(uri, searchPath, folderGlobOptions.ignoreCase)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added ignoreCase argument to isEqualOrParent() call because it is related to glob matching.

else {
this.filesWalked++;
if (currentRelativePath === this.filePattern) {
if (strings.equals(currentRelativePath, this.filePattern, ignoreCase)) {
Copy link
Contributor Author

@dmitrivMS dmitrivMS Oct 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added ignoreCase argument to string comparison because it is related to glob matching.

// are searching for and we want to include the result in that case anyway
const currentRelativePath = relativeParentPath ? [relativeParentPath, file].join(path.sep) : file;
if (this.folderExcludePatterns.get(folderQuery.folder.fsPath)!.test(currentRelativePath, file, this.config.filePattern !== file ? hasSibling : undefined)) {
if (this.folderExcludePatterns.get(folderQuery.folder.fsPath)!.test(currentRelativePath, file, !strings.equals(this.config.filePattern, file, ignoreCase) ? hasSibling : undefined)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added ignoreCase argument to string comparison because it is related to glob matching.

} else {
self.filesWalked++;
if (relativePath === filePattern) {
if (strings.equals(relativePath, filePattern, ignoreCase)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added ignoreCase argument to string comparison because it is related to glob matching.

// to ignore filtering by siblings because the user seems to know what they
// are searching for and we want to include the result in that case anyway
if (excludePattern.test(relativePath, basename, filePattern !== basename ? hasSibling : undefined)) {
if (excludePattern.test(relativePath, basename, !strings.equals(filePattern, basename, ignoreCase) ? hasSibling : undefined)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added ignoreCase argument to string comparison because it is related to glob matching.

return !!queryProps.folderQueries && queryProps.folderQueries.some(fq => {
const searchPath = fq.folder.fsPath;
if (extpath.isEqualOrParent(fsPath, searchPath)) {
if (extpath.isEqualOrParent(fsPath, searchPath, globOptions.ignoreCase)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added ignoreCase argument to isEqualOrParent() call because it is related to glob matching.

private addDirectoryEntries({ pathToEntries }: IDirectoryTree, base: URI, relativeFile: string, onResult: (result: IInternalFileMatch) => void) {
// Support relative paths to files from a root resource (ignores excludes)
if (relativeFile === this.filePattern) {
if (this.filePattern !== undefined && strings.equals(relativeFile, this.filePattern, this.config.ignoreGlobPatternCase)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added ignoreCase argument to string comparison because it is related to glob matching.

// to ignore filtering by siblings because the user seems to know what they
// are searching for and we want to include the result in that case anyway
if (queryTester.matchesExcludesSync(relativePath, basename, filePattern !== basename ? hasSibling : undefined)) {
if (queryTester.matchesExcludesSync(relativePath, basename, !strings.equals(filePattern, basename, ignoreCase) ? hasSibling : undefined)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added ignoreCase argument to string comparison because it is related to glob matching.

matchDirectory(sub);
} else {
if (relativePath === filePattern) {
if (strings.equals(relativePath, filePattern, ignoreCase)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added ignoreCase argument to string comparison because it is related to glob matching.

@dmitrivMS
Copy link
Contributor Author

Closing, will open a new one in its place.

@dmitrivMS dmitrivMS closed this Nov 5, 2025
@vs-code-engineering vs-code-engineering bot locked and limited conversation to collaborators Dec 21, 2025
@dmitrivMS dmitrivMS deleted the dev/dmitriv/glob-2 branch January 29, 2026 23:42
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

file-glob File glob engine search Search widget and operation issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Glob matching should be case insensitive