1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-13 20:33:35 +08:00

Fix song select search not matching results when punctuation marks surround the searched double-quoted phrase (#37034)

Fixes #36645

The IsolatedPhrase match mode in FilterCriteria used \s (whitespace) as
word boundaries, meaning a search term had to be surrounded by spaces
(or start/end of string) to match.

This caused songs with titles like
'Music Theme "Some Artist"' to not appear when searching for "Some
Artist", since the phrase was bounded by quote characters rather than
spaces.

This change extends the boundary pattern to also accept Unicode
punctuation (\p{P}) alongside whitespace, so terms surrounded by quotes,
commas are correctly matched as isolated phrases.

Tests have been added to cover searching for terms adjacent to
punctuation boundaries
(TestCriteriaMatchingTermsAdjacentToPunctuation).

Tests cover the example mentioned above.
Code inspector with no errors and tests passing.
This commit is contained in:
Simão Caixas
2026-03-23 07:12:46 +00:00
committed by GitHub
Unverified
parent c5dd95851c
commit f3c9dd7f3b
2 changed files with 41 additions and 1 deletions
@@ -219,6 +219,46 @@ namespace osu.Game.Tests.NonVisual.Filtering
ClassicAssert.AreEqual(filtered, carouselItem.Filtered.Value);
}
[Test]
[TestCase("\"quoted words\"", false)]
[TestCase("\"the artist\"", false)]
[TestCase("the artist \"quoted words\"", false)]
[TestCase("\"unknown\"", true)]
public void TestCriteriaMatchingTermsAdjacentToPunctuation(string terms, bool filtered)
{
var exampleBeatmapInfo = getExampleBeatmap();
exampleBeatmapInfo.Metadata.Title = "the artist \"quoted words\"";
var criteria = new FilterCriteria
{
Ruleset = new RulesetInfo { OnlineID = 6 },
AllowConvertedBeatmaps = true,
SearchText = terms
};
var carouselItem = new CarouselBeatmap(exampleBeatmapInfo);
carouselItem.Filter(criteria);
ClassicAssert.AreEqual(filtered, carouselItem.Filtered.Value);
}
[Test]
[TestCase("~quoted words~", false)]
[TestCase("the artist", false)]
[TestCase("the artist ~quoted words~", false)]
[TestCase("~unknown~", true)]
public void TestCriteriaMatchingTermsAdjacentToMathSymbols(string terms, bool filtered)
{
var exampleBeatmapInfo = getExampleBeatmap();
exampleBeatmapInfo.Metadata.Title = "the artist ~quoted words~";
var criteria = new FilterCriteria
{
Ruleset = new RulesetInfo { OnlineID = 6 },
AllowConvertedBeatmaps = true,
SearchText = terms
};
var carouselItem = new CarouselBeatmap(exampleBeatmapInfo);
carouselItem.Filter(criteria);
ClassicAssert.AreEqual(filtered, carouselItem.Filtered.Value);
}
[Test]
[TestCase("", false)]
[TestCase("Goes", false)]
+1 -1
View File
@@ -219,7 +219,7 @@ namespace osu.Game.Screens.Select
break;
case MatchMode.IsolatedPhrase:
result = Regex.IsMatch(value, $@"(^|\s){Regex.Escape(searchTerm)}($|\s)", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
result = Regex.IsMatch(value, $@"(^|\b){Regex.Escape(searchTerm)}($|\b)", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
break;
case MatchMode.FullPhrase: