What's wrong
The Fuzzy arm of IsMatch (TextFilter/TextFilter.cs:242) passes the filter to the fuzzy matcher exactly as typed:
TextFilterType.Fuzzy => Fuzzy.Contains(text.AsSpan(), filter.AsSpan(), out score),
A leading or trailing space therefore becomes a character the text must contain.
The other filter types don't behave this way. Glob and Regex split the filter into tokens, so padding has no effect. IsMatch itself already treats a filter that is only whitespace as "match everything". Fuzzy is the one type where a stray space changes the result.
Failure scenario
In a filter box, the user types a word, then a space before the next word. Every item without a space disappears. Leading spaces from a paste do the same.
With items {"hello world", "helium", "help", "yellow"}:
| Filter |
Type |
Result |
Expected |
"hel" |
Fuzzy |
[help, helium, hello world] |
same |
"hel " |
Fuzzy |
[hello world] |
[help, helium, hello world] |
" hel" |
Fuzzy |
[] |
[help, helium, hello world] |
" hel*" |
Glob |
[hello world, helium, help] |
same |
IsMatch("abcdef", "abc", Fuzzy) is true, but "abc " and " abc" both return false. Rank is unaffected, because it ignores the match result.
These results come from a scratch program built from the current TextFilter.cs against the pinned ktsu.FuzzySearch:
Fuzzy filter='hel' -> [help, helium, hello world]
Fuzzy filter='hel ' -> [hello world]
Fuzzy filter=' hel' -> []
Suggested fix
- Trim the filter before the fuzzy match:
Fuzzy.Contains(text.AsSpan(), filter.AsSpan().Trim(), out score).
- Optionally, go further and apply
TextFilterMatchOptions to fuzzy matching: split on whitespace and match each token, the way the glob path does. That would make "bar foo" fuzzy-match "foo bar". Today the match-options argument is silently ignored for Fuzzy.
Acceptance criteria
IsMatch(x, "hel ", Fuzzy) and IsMatch(x, " hel", Fuzzy) return the same result as IsMatch(x, "hel", Fuzzy) for every x.
- Regression tests cover leading and trailing padding in
Filter and IsMatch for Fuzzy.
What's wrong
The Fuzzy arm of
IsMatch(TextFilter/TextFilter.cs:242) passes the filter to the fuzzy matcher exactly as typed:A leading or trailing space therefore becomes a character the text must contain.
The other filter types don't behave this way. Glob and Regex split the filter into tokens, so padding has no effect.
IsMatchitself already treats a filter that is only whitespace as "match everything". Fuzzy is the one type where a stray space changes the result.Failure scenario
In a filter box, the user types a word, then a space before the next word. Every item without a space disappears. Leading spaces from a paste do the same.
With items
{"hello world", "helium", "help", "yellow"}:"hel"[help, helium, hello world]"hel "[hello world][help, helium, hello world]" hel"[][help, helium, hello world]" hel*"[hello world, helium, help]IsMatch("abcdef", "abc", Fuzzy)istrue, but"abc "and" abc"both returnfalse.Rankis unaffected, because it ignores the match result.These results come from a scratch program built from the current
TextFilter.csagainst the pinned ktsu.FuzzySearch:Suggested fix
Fuzzy.Contains(text.AsSpan(), filter.AsSpan().Trim(), out score).TextFilterMatchOptionsto fuzzy matching: split on whitespace and match each token, the way the glob path does. That would make"bar foo"fuzzy-match"foo bar". Today the match-options argument is silently ignored for Fuzzy.Acceptance criteria
IsMatch(x, "hel ", Fuzzy)andIsMatch(x, " hel", Fuzzy)return the same result asIsMatch(x, "hel", Fuzzy)for everyx.FilterandIsMatchfor Fuzzy.