Skip to content

Regex filters containing a space or \s never match under the default ByWordAny option ("hello world" doesn't match "hello world") #122

Description

@matt-edmondson

What's wrong

DoesMatchRegex (TextFilter/TextFilter.cs ~L452) splits the text into words via ExtractTextTokens for ByWordAny/ByWordAll, then runs the regex against each word separately (~L488-496). The pattern isn't split. Since no single word ever contains whitespace, any regex that must match across whitespace (a literal space, \s, a phrase) can never match. Filter/IsMatch default to TextFilterMatchOptions.ByWordAny, so this is the out-of-the-box behavior.

Failure scenario (verified with a console app against the net10.0 build)

TextFilter.IsMatch("hello world", "hello world", TextFilterType.Regex); // False
TextFilter.IsMatch("hello world", "o w",         TextFilterType.Regex); // False

Only ByWholeString matches. In a regex filter box with default options, typing New York or \d+ items hides every item, even though the regex hint says the text must match the pattern.

Suggested fix

Under ByWordAny, also try the pattern against the whole text: regex.IsMatch(text) || tokens.Any(regex.IsMatch). Keeping the per-word check means word-anchored patterns like ^world keep matching. (For ByWordAll the per-word semantics are arguably intended; at minimum document that whitespace-spanning patterns need ByWholeString there.)

Acceptance criteria

Activity

  1. matt-edmondson commented on Sep 27, 2026

    @matt-edmondson
    ContributorAuthor

    Triage

    • Category: Bug
    • Priority: High. ByWordAny is the default for Filter/IsMatch, so any regex that spans whitespace (a literal space, \s, a phrase such as New York) hides every item with default options. The regex filter mode is broken out of the box for a common kind of input.
    • Area / suggested assignee: TextFilter.DoesMatchRegex and ExtractTextTokens in TextFilter/TextFilter.cs. Owner: @matt-edmondson
    • Duplicates / in progress: not a duplicate. Open PRs Let glob * and ? match across / and \ [patch] #119 (glob across separators) and Fold an inline (?i) culture-invariantly too [patch] #121 (culture-invariant inline (?i)) touch the same matcher but don't cover this. It is related to Regex timeout applies per word per item, so one catastrophic-backtracking pattern still freezes Filter() for N seconds (10 items: 10 s) #118: the whole-text evaluation added here must stay under the same timeout budget, so the two fixes would be easiest to land together or in sequence.
    • Next step: under ByWordAny, try the whole text first (regex.IsMatch(text) || tokens.Any(regex.IsMatch)). For ByWordAll, either keep the per-word semantics and document that whitespace-spanning patterns need ByWholeString, or apply the same fallback. Add the acceptance tests for "hello world" and "o\\sw", plus a check that ^world still matches under ByWordAny.

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions