Skip to content

Comments

File search now has filters#42141

Merged
michaeljolley merged 7 commits intomainfrom
dev/mjolley/file-search-filters
Oct 25, 2025
Merged

File search now has filters#42141
michaeljolley merged 7 commits intomainfrom
dev/mjolley/file-search-filters

Conversation

@michaeljolley
Copy link
Contributor

Closes #39260

Search for all files & folders, folders only, or files only.

Enjoy.

Screen.Recording.2025-10-01.160524.mp4

@michaeljolley michaeljolley added the Product-Command Palette Refers to the Command Palette utility label Oct 1, 2025
@michaeljolley
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@Jay-o-Way
Copy link
Collaborator

I would use even simpler strings myself: Files, Folders, Files and folders.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions
Copy link

@check-spelling-bot Report

🔴 Please review

See the 📂 files view, the 📜action log, or 📝 job summary for details.

Unrecognized words (4)

dfx
fdx
nullref
worktree

These words are not needed and should be removed DFX Worktree

To accept these unrecognized words as correct and remove the previously acknowledged and now absent words, you could run the following commands

... in a clone of the git@github.com:microsoft/PowerToys.git repository
on the dev/mjolley/file-search-filters branch (ℹ️ how do I use this?):

curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/c635c2f3f714eec2fcf27b643a1919b9a811ef2e/apply.pl' |
perl - 'https://github.com/microsoft/PowerToys/actions/runs/18477177460/attempts/1' &&
git commit -m 'Update check-spelling metadata'
If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

@michaeljolley
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jiripolasek
Copy link
Collaborator

jiripolasek commented Oct 21, 2025

@michaeljolley LGTM

The only issue with this is that Windows treats archives as folders. A bunch of .gz files mixed with folders looked like a mistake at first glance.

Tested on Windows 11 25H2, Release, and Release + AOT (after manually merging main to incorporate the fix for filters).

image

@michaeljolley michaeljolley merged commit 20188bd into main Oct 25, 2025
14 checks passed
@michaeljolley michaeljolley deleted the dev/mjolley/file-search-filters branch October 25, 2025 00:16
vanzue pushed a commit that referenced this pull request Oct 27, 2025
@yeelam-gordon yeelam-gordon requested a review from Copilot November 7, 2025 01:57
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 filter functionality to the Indexer extension in Command Palette, allowing users to filter search results by file type (all files and folders, folders only, or files only).

  • Adds three filter options: "Files and folders", "Folders", and "Files"
  • Integrates filters into the search query using Windows Search syntax (kind:folders and kind:NOT folders)
  • Changes the Icons class from sealed to static (appropriate since it only contains static members)

Reviewed Changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
Resources.resx Adds three new localized string resources for filter labels
Resources.Designer.cs Auto-generated designer code for the new resource strings
IndexerPage.cs Integrates filter functionality, refactors search logic into PerformSearch method, and adds FullSearchString method to append filter keywords
SearchFilters.cs New class defining the available filters (all, folders, files) with appropriate icons
Icons.cs Changes class from sealed to static and adds two new icon definitions for filters
Files not reviewed (1)
  • src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.Designer.cs: Language not supported

var actualSearch = FullSearchString(newSearch);
_ = Task.Run(() =>
{
_isEmptyQuery = string.IsNullOrWhiteSpace(actualSearch);
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

The _isEmptyQuery check now uses actualSearch (which includes filter keywords) instead of the original newSearch input. This means that even when a user hasn't entered any query text, if they've selected the "folders" or "files" filter, _isEmptyQuery will be false because actualSearch will contain "kind:folders" or "kind:NOT folders".

This could affect the EmptyContent property behavior - users might see "no results" message instead of the "no search query" message when they select a filter without entering any search text. Consider checking newSearch directly instead:

_isEmptyQuery = string.IsNullOrWhiteSpace(newSearch);
Suggested change
_isEmptyQuery = string.IsNullOrWhiteSpace(actualSearch);
_isEmptyQuery = string.IsNullOrWhiteSpace(newSearch);

Copilot uses AI. Check for mistakes.
Comment on lines +41 to +43
var filters = new SearchFilters();
filters.PropChanged += Filters_PropChanged;
Filters = filters;
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

The filter initialization logic (lines 41-43 and 59-61) is duplicated across both constructors. This violates the DRY (Don't Repeat Yourself) principle and could lead to maintenance issues if the initialization logic needs to change.

Consider extracting this to a shared initialization method:

private void InitializeFilters()
{
    var filters = new SearchFilters();
    filters.PropChanged += Filters_PropChanged;
    Filters = filters;
}

Then call InitializeFilters(); in both constructors.

Copilot uses AI. Check for mistakes.
Comment on lines +131 to +139
switch (Filters.CurrentFilterId)
{
case "folders":
return $"{query} kind:folders";
case "files":
return $"{query} kind:NOT folders";
case "all":
default:
return query;
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

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

The FullSearchString method can produce unintended results when the query is empty or whitespace-only. For example, with the "folders" filter and an empty query, it would return " kind:folders" (note the leading space), and with the "files" filter, it would return " kind:NOT folders". This could lead to unexpected search behavior.

Consider trimming the result or checking if the query is empty before appending the filter:

private string FullSearchString(string query)
{
    var trimmedQuery = query?.Trim() ?? string.Empty;
    
    switch (Filters.CurrentFilterId)
    {
        case "folders":
            return string.IsNullOrWhiteSpace(trimmedQuery) 
                ? "kind:folders" 
                : $"{trimmedQuery} kind:folders";
        case "files":
            return string.IsNullOrWhiteSpace(trimmedQuery) 
                ? "kind:NOT folders" 
                : $"{trimmedQuery} kind:NOT folders";
        case "all":
        default:
            return trimmedQuery;
    }
}
Suggested change
switch (Filters.CurrentFilterId)
{
case "folders":
return $"{query} kind:folders";
case "files":
return $"{query} kind:NOT folders";
case "all":
default:
return query;
var trimmedQuery = query?.Trim() ?? string.Empty;
switch (Filters.CurrentFilterId)
{
case "folders":
return string.IsNullOrWhiteSpace(trimmedQuery)
? "kind:folders"
: $"{trimmedQuery} kind:folders";
case "files":
return string.IsNullOrWhiteSpace(trimmedQuery)
? "kind:NOT folders"
: $"{trimmedQuery} kind:NOT folders";
case "all":
default:
return trimmedQuery;

Copilot uses AI. Check for mistakes.
mirmirmirr pushed a commit to mirmirmirr/PowerToys that referenced this pull request Nov 9, 2025
@yeelam-gordon yeelam-gordon added this to the PowerToys 0.96 milestone Nov 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Product-Command Palette Refers to the Command Palette utility

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Searching exclusively for folders

4 participants