Skip to content

Commit

Permalink
Reduce the number of times the search string needs to be made lower c…
Browse files Browse the repository at this point in the history
…ase when searching, and remove an extra level of bouncing when there is a single search query
  • Loading branch information
pupnewfster committed Feb 3, 2025
1 parent e940be7 commit 0a3d801
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 31 deletions.
40 changes: 19 additions & 21 deletions src/main/java/mekanism/common/content/qio/SearchQueryParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ public class SearchQueryParser {

private static final Set<Character> TERMINATORS = Set.of('|', '(', '\"', '\'');

/**
* @param query Expected to be lower case
*/
public static ISearchQuery parse(String query) {
if (query == null || query.isEmpty()) {
return ISearchQuery.INVALID;
Expand All @@ -44,7 +47,7 @@ public static ISearchQuery parseOrdered(String query) {
if (query == null || query.isEmpty()) {
return ISearchQuery.INVALID;
}
return parse(query, new LinkedHashSet<>());
return parse(query.trim().toLowerCase(Locale.ROOT), new LinkedHashSet<>());
}

private static ISearchQuery parse(String query, Set<SearchQuery> ret) {
Expand Down Expand Up @@ -79,9 +82,14 @@ private static ISearchQuery parse(String query, Set<SearchQuery> ret) {
i = keyListResult.index();
}
if (!curQuery.isEmpty()) {
if (ret.isEmpty()) {
return curQuery;
}
ret.add(curQuery);
} else if (ret.size() == 1) {
return ret.iterator().next();
}
return new SearchQuerySet(ret);
return ret.isEmpty() ? ISearchQuery.INVALID : new SearchQuerySet(ret);
}

private static KeyListResult readKeyList(String query, int start, QueryType type, SearchQuery curQuery) {
Expand Down Expand Up @@ -201,26 +209,22 @@ public enum QueryType {
NAME('~') {
@Override
public boolean matches(@Nullable Level level, @Nullable Player player, String key, ItemStack stack) {
return stack.getHoverName().getString().toLowerCase(Locale.ROOT).contains(key.toLowerCase(Locale.ROOT));
return stack.getHoverName().getString().toLowerCase(Locale.ROOT).contains(key);
}
},
MOD_ID('@') {
@Override
public boolean matches(@Nullable Level level, @Nullable Player player, String key, ItemStack stack) {
return MekanismUtils.getModId(stack).toLowerCase(Locale.ROOT).contains(key.toLowerCase(Locale.ROOT));
return MekanismUtils.getModId(stack).toLowerCase(Locale.ROOT).contains(key);
}
},
TOOLTIP('$') {
@Override
public boolean matches(@Nullable Level level, @Nullable Player player, String key, ItemStack stack) {
List<Component> tooltipLines = stack.getTooltipLines(Item.TooltipContext.of(level), player, Default.NORMAL);
if (!tooltipLines.isEmpty()) {
String lowerKey = key.toLowerCase(Locale.ROOT);
for (Component tooltipLine : tooltipLines) {
String tooltip = tooltipLine.getString().toLowerCase(Locale.ROOT);
if (tooltip.contains(lowerKey)) {
return true;
}
for (Component tooltipLine : stack.getTooltipLines(Item.TooltipContext.of(level), player, Default.NORMAL)) {
String tooltip = tooltipLine.getString().toLowerCase(Locale.ROOT);
if (tooltip.contains(key)) {
return true;
}
}
return false;
Expand All @@ -229,13 +233,9 @@ public boolean matches(@Nullable Level level, @Nullable Player player, String ke
TAG('#') {
@Override
public boolean matches(@Nullable Level level, @Nullable Player player, String key, ItemStack stack) {
List<String> itemTags = TagCache.getItemTags(stack);
if (!itemTags.isEmpty()) {
String lowerKey = key.toLowerCase(Locale.ROOT);
for (String tag : itemTags) {
if (tag.toLowerCase(Locale.ROOT).contains(lowerKey)) {
return true;
}
for (String tag : TagCache.getItemTags(stack)) {
if (tag.toLowerCase(Locale.ROOT).contains(key)) {
return true;
}
}
return false;
Expand Down Expand Up @@ -272,8 +272,6 @@ public static CharSet getPrefixChars() {
public static class SearchQuery implements ISearchQuery {

//TODO: Do we want to allow adding to query strings of a query type after the fact and instead force using an query set if you don't want to use parenthesis
//TODO: As it seems all QueryType's end up doing a toLowerCase(Locale.ROOT) on the key, do we want to try and move that upwards and have the input expect
// it to be lower case. That way we don't have to convert them to lower case so much?
private final Map<QueryType, List<String>> queryStrings = new EnumMap<>(QueryType.class);

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
Expand Down Expand Up @@ -623,7 +624,9 @@ public void updateSearch(@Nullable Level level, String queryText, boolean skipSa
// searches should only be updated on the client-side
if (level == null || !level.isClientSide()) {
return;
} else if (skipSameQuery && rawSearchQuery.equals(queryText)) {
}
queryText = queryText.trim().toLowerCase(Locale.ROOT);
if (skipSameQuery && rawSearchQuery.equals(queryText)) {
//Short circuit and skip updating the search if we already have the results
//TODO: Do we want to compare if the search queries are equal here instead of just the raw text?
// That way we can potentially handle ignoring things like lower vs uppercase of the same letter.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ void testMultiQueries() {
@DisplayName("Test key lists")
void testLists() {
// test long list
queryAssert("(test | test1 | test2 test3 | test4)", "[{NAME=[test, test1, test2 test3, test4]}]");
queryAssert("(test | test1 | test2 test3 | test4)", "{NAME=[test, test1, test2 test3, test4]}");
// test two queries, both with lists
queryAssert("(test | test1) | (test2 | test3)", "[{NAME=[test, test1]}, {NAME=[test2, test3]}]");
// test various query types in lists
queryAssert("@(mod | mod1) (test | test1) $(tool | tool1) #(tag | tag1)", "[{NAME=[test, test1], MOD_ID=[mod, mod1], TOOLTIP=[tool, tool1], TAG=[tag, tag1]}]");
queryAssert("@(mod | mod1) (test | test1) $(tool | tool1) #(tag | tag1)", "{NAME=[test, test1], MOD_ID=[mod, mod1], TOOLTIP=[tool, tool1], TAG=[tag, tag1]}");
}

@Test
@DisplayName("Test quotes")
void testQuotes() {
queryAssert("\"test with (parentheses)\"", "[{NAME=[test with (parentheses)]}]");
queryAssert("\"test with (parentheses)\"", "{NAME=[test with (parentheses)]}");
queryAssert("\"test with (parentheses)\" | \"test2\"", "[{NAME=[test with (parentheses)]}, {NAME=[test2]}]");
queryInvalid("\"no end quote");
queryInvalid("quote at end\"");
Expand All @@ -43,21 +43,21 @@ void testQuotes() {
@Test
@DisplayName("Test various query types")
void testQueryTypes() {
queryAssert("@mod #tag $tool test", "[{NAME=[test], MOD_ID=[mod], TOOLTIP=[tool], TAG=[tag]}]");
queryAssert("@mod #tag $tool test", "{NAME=[test], MOD_ID=[mod], TOOLTIP=[tool], TAG=[tag]}");
// with quotes
queryAssert("#tag $\"this is a tooltip\" @mod", "[{MOD_ID=[mod], TOOLTIP=[this is a tooltip], TAG=[tag]}]");
queryAssert("#tag $\"this is a tooltip\" @mod", "{MOD_ID=[mod], TOOLTIP=[this is a tooltip], TAG=[tag]}");
// with list
queryAssert("$tool #(tag1 | tag2) test name", "[{NAME=[test name], TOOLTIP=[tool], TAG=[tag1, tag2]}]");
queryAssert("$tool #(tag1 | tag2) test name", "{NAME=[test name], TOOLTIP=[tool], TAG=[tag1, tag2]}");
// quotes + list
queryAssert("$\"tooltip test\" test name #(tag1 | tag2) @mod", "[{NAME=[test name], MOD_ID=[mod], TOOLTIP=[tooltip test], TAG=[tag1, tag2]}]");
queryAssert("$\"tooltip test\" test name #(tag1 | tag2) @mod", "{NAME=[test name], MOD_ID=[mod], TOOLTIP=[tooltip test], TAG=[tag1, tag2]}");
}

@Test
@DisplayName("Test weird spacing")
void testSpacing() {
queryAssert(" test ", "[{NAME=[test]}]");
queryAssert(" test ", "{NAME=[test]}");
// key immediately following quote of other type
queryAssert("@\"test mod\"mod", "[{NAME=[mod], MOD_ID=[test mod]}]");
queryAssert("@\"test mod\"mod", "{NAME=[mod], MOD_ID=[test mod]}");
}

@Test
Expand Down

0 comments on commit 0a3d801

Please sign in to comment.