mirror of
https://github.com/ppy/osu
synced 2025-02-26 23:51:04 +00:00
Add support for matching full terms using suffixed !
This commit is contained in:
parent
9b08aaf93f
commit
c423f77d53
@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using osu.Game.Beatmaps;
|
||||
@ -62,7 +63,7 @@ namespace osu.Game.Screens.Select
|
||||
string remainingText = value;
|
||||
|
||||
// First handle quoted segments to ensure we keep inline spaces in exact matches.
|
||||
foreach (Match quotedSegment in Regex.Matches(searchText, "(\"[^\"]+\")"))
|
||||
foreach (Match quotedSegment in Regex.Matches(searchText, "(\"[^\"]+\"[!]?)"))
|
||||
{
|
||||
terms.Add(new OptionalTextFilter { SearchTerm = quotedSegment.Value });
|
||||
remainingText = remainingText.Replace(quotedSegment.Value, string.Empty);
|
||||
@ -138,7 +139,7 @@ namespace osu.Game.Screens.Select
|
||||
{
|
||||
public bool HasFilter => !string.IsNullOrEmpty(SearchTerm);
|
||||
|
||||
public bool Exact { get; private set; }
|
||||
public MatchMode MatchMode { get; private set; }
|
||||
|
||||
public bool Matches(string value)
|
||||
{
|
||||
@ -149,10 +150,18 @@ namespace osu.Game.Screens.Select
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return false;
|
||||
|
||||
if (Exact)
|
||||
return Regex.IsMatch(value, $@"(^|\s){Regex.Escape(searchTerm)}($|\s)", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||
switch (MatchMode)
|
||||
{
|
||||
default:
|
||||
case MatchMode.None:
|
||||
return value.Contains(SearchTerm, StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
return value.Contains(SearchTerm, StringComparison.InvariantCultureIgnoreCase);
|
||||
case MatchMode.IsolatedPhrase:
|
||||
return Regex.IsMatch(value, $@"(^|\s){Regex.Escape(searchTerm)}($|\s)", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||
|
||||
case MatchMode.FullPhrase:
|
||||
return CultureInfo.InvariantCulture.CompareInfo.Compare(value, searchTerm, CompareOptions.IgnoreCase) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
private string searchTerm;
|
||||
@ -162,12 +171,42 @@ namespace osu.Game.Screens.Select
|
||||
get => searchTerm;
|
||||
set
|
||||
{
|
||||
searchTerm = value.Trim('"');
|
||||
Exact = searchTerm != value;
|
||||
searchTerm = value;
|
||||
|
||||
if (searchTerm.EndsWith("\"!", StringComparison.Ordinal))
|
||||
{
|
||||
searchTerm = searchTerm.Trim('!', '\"');
|
||||
MatchMode = MatchMode.FullPhrase;
|
||||
}
|
||||
else if (searchTerm.StartsWith('\"'))
|
||||
{
|
||||
searchTerm = searchTerm.Trim('\"');
|
||||
MatchMode = MatchMode.IsolatedPhrase;
|
||||
}
|
||||
else
|
||||
MatchMode = MatchMode.None;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Equals(OptionalTextFilter other) => SearchTerm == other.SearchTerm;
|
||||
}
|
||||
|
||||
public enum MatchMode
|
||||
{
|
||||
/// <summary>
|
||||
/// Match using a simple "contains" substring match.
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// Match for the search phrase being isolated by spaces, or at the start or end of the text.
|
||||
/// </summary>
|
||||
IsolatedPhrase,
|
||||
|
||||
/// <summary>
|
||||
/// Match for the search phrase matching the full text in completion.
|
||||
/// </summary>
|
||||
FullPhrase,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ namespace osu.Game.Screens.Select
|
||||
public static class FilterQueryParser
|
||||
{
|
||||
private static readonly Regex query_syntax_regex = new Regex(
|
||||
@"\b(?<key>\w+)(?<op>(:|=|(>|<)(:|=)?))(?<value>("".*"")|(\S*))",
|
||||
@"\b(?<key>\w+)(?<op>(:|=|(>|<)(:|=)?))(?<value>("".*""[!]?)|(\S*))",
|
||||
RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
internal static void ApplyQueries(FilterCriteria criteria, string query)
|
||||
|
Loading…
Reference in New Issue
Block a user