diff options
15 files changed, 286 insertions, 35 deletions
diff --git a/api/src/main/java/me/shedaniel/rei/api/ConfigObject.java b/api/src/main/java/me/shedaniel/rei/api/ConfigObject.java index d8210bbc2..c84075e79 100644 --- a/api/src/main/java/me/shedaniel/rei/api/ConfigObject.java +++ b/api/src/main/java/me/shedaniel/rei/api/ConfigObject.java @@ -159,4 +159,7 @@ public interface ConfigObject { @ApiStatus.Experimental double getVerticalEntriesBoundaries(); + + @ApiStatus.Experimental + SyntaxHighlightingMode getSyntaxHighlightingMode(); } diff --git a/api/src/main/java/me/shedaniel/rei/gui/config/SyntaxHighlightingMode.java b/api/src/main/java/me/shedaniel/rei/gui/config/SyntaxHighlightingMode.java new file mode 100644 index 000000000..23aac1f44 --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/gui/config/SyntaxHighlightingMode.java @@ -0,0 +1,43 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.gui.config; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.resources.language.I18n; + +import java.util.Locale; + +@Environment(EnvType.CLIENT) +public enum SyntaxHighlightingMode { + PLAIN, + PLAIN_UNDERSCORED, + COLORFUL, + COLORFUL_UNDERSCORED; + + @Override + public String toString() { + return I18n.get("config.roughlyenoughitems.syntaxHighlightingMode." + name().toLowerCase(Locale.ROOT)); + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/OverlaySearchField.java b/runtime/src/main/java/me/shedaniel/rei/gui/OverlaySearchField.java index 9edb9880f..cd7477859 100644 --- a/runtime/src/main/java/me/shedaniel/rei/gui/OverlaySearchField.java +++ b/runtime/src/main/java/me/shedaniel/rei/gui/OverlaySearchField.java @@ -31,6 +31,7 @@ import me.shedaniel.math.Color; import me.shedaniel.math.Point; import me.shedaniel.math.impl.PointHelper; import me.shedaniel.rei.api.ConfigObject; +import me.shedaniel.rei.gui.config.SyntaxHighlightingMode; import me.shedaniel.rei.gui.widget.TextFieldWidget; import me.shedaniel.rei.impl.OverlaySearchFieldSyntaxHighlighter; import me.shedaniel.rei.impl.ScreenHelper; @@ -74,23 +75,29 @@ public class OverlaySearchField extends TextFieldWidget implements TextFieldWidg @Override public FormattedCharSequence format(TextFieldWidget widget, String text, int index) { + boolean isPlain = ConfigObject.getInstance().getSyntaxHighlightingMode() == SyntaxHighlightingMode.PLAIN || ConfigObject.getInstance().getSyntaxHighlightingMode() == SyntaxHighlightingMode.PLAIN_UNDERSCORED; + boolean hasUnderscore = ConfigObject.getInstance().getSyntaxHighlightingMode() == SyntaxHighlightingMode.PLAIN_UNDERSCORED || ConfigObject.getInstance().getSyntaxHighlightingMode() == SyntaxHighlightingMode.COLORFUL_UNDERSCORED; return TextTransformations.forwardWithTransformation(text, (s, charIndex, c) -> { byte arg = highlighter.highlighted[charIndex + index]; - Style style; + Style style = Style.EMPTY; if (arg > 0) { - Argument<?, ?> argument = ArgumentsRegistry.ARGUMENT_LIST.get(arg - 1); - style = argument.getHighlightedStyle(); + Argument<?, ?> argument = ArgumentsRegistry.ARGUMENT_LIST.get((arg - 1) / 2); + if (!isPlain) { + style = argument.getHighlightedStyle(); + } if (argument instanceof TextArgument) { if (isMain && ContainerScreenOverlay.getEntryListWidget().getAllStacks().isEmpty() && !getText().isEmpty()) { style = ERROR_STYLE; } + } else if (hasUnderscore && arg % 2 == 1) { + style = style.withUnderlined(true); + } + } else if (!isPlain) { + if (arg == -1) { + style = SPLITTER_STYLE; + } else if (arg == -2) { + style = QUOTES_STYLE; } - } else if (arg == -1) { - style = SPLITTER_STYLE; - } else if (arg == -2) { - style = QUOTES_STYLE; - } else { - style = Style.EMPTY; } diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/PreRecipeViewingScreen.java b/runtime/src/main/java/me/shedaniel/rei/gui/PreRecipeViewingScreen.java index bc114868b..1bf8173e8 100644 --- a/runtime/src/main/java/me/shedaniel/rei/gui/PreRecipeViewingScreen.java +++ b/runtime/src/main/java/me/shedaniel/rei/gui/PreRecipeViewingScreen.java @@ -53,7 +53,6 @@ import java.util.List; @ApiStatus.Internal public class PreRecipeViewingScreen extends Screen { - private static final ResourceLocation IDENTIFIER = new ResourceLocation("roughlyenoughitems", "textures/gui/screenshot.png"); private final List<Widget> widgets; protected long start; diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/SearchFilterSyntaxHighlightingScreen.java b/runtime/src/main/java/me/shedaniel/rei/gui/SearchFilterSyntaxHighlightingScreen.java new file mode 100644 index 000000000..0ecdbcd6f --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/gui/SearchFilterSyntaxHighlightingScreen.java @@ -0,0 +1,39 @@ +package me.shedaniel.rei.gui; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.*; +import com.mojang.math.Matrix4f; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.ApiStatus; + +@ApiStatus.Internal +public class SearchFilterSyntaxHighlightingScreen extends Screen { + protected SearchFilterSyntaxHighlightingScreen(Component component) { + super(component); + } + + + + @Override + public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { + renderHoleBackground(matrices, 0, height, 32, 255, 255); + super.render(matrices, mouseX, mouseY, delta); + + } + + protected void renderHoleBackground(PoseStack matrices, int y1, int y2, int tint, int alpha1, int alpha2) { + Tesselator tesselator = Tesselator.getInstance(); + BufferBuilder buffer = tesselator.getBuilder(); + this.minecraft.getTextureManager().bind(BACKGROUND_LOCATION); + Matrix4f matrix = matrices.last().pose(); + RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); + float float_1 = 32.0F; + buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR); + buffer.vertex(matrix, 0, y2, 0.0F).uv(0.0F, y2 / 32.0F).color(tint, tint, tint, alpha2).endVertex(); + buffer.vertex(matrix, this.width, y2, 0.0F).uv(this.width / 32.0F, y2 / 32.0F).color(tint, tint, tint, alpha2).endVertex(); + buffer.vertex(matrix, this.width, y1, 0.0F).uv(this.width / 32.0F, y1 / 32.0F).color(tint, tint, tint, alpha1).endVertex(); + buffer.vertex(matrix, 0, y1, 0.0F).uv(0.0F, y1 / 32.0F).color(tint, tint, tint, alpha1).endVertex(); + tesselator.end(); + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringScreen.java b/runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringScreen.java index dbbb9fbf4..4c08d6d76 100644 --- a/runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringScreen.java +++ b/runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringScreen.java @@ -189,8 +189,8 @@ public class FilteringScreen extends Screen { } protected void renderHoleBackground(PoseStack matrices, int y1, int y2, int tint, int alpha1, int alpha2) { - Tesselator tessellator = Tesselator.getInstance(); - BufferBuilder buffer = tessellator.getBuilder(); + Tesselator tesselator = Tesselator.getInstance(); + BufferBuilder buffer = tesselator.getBuilder(); this.minecraft.getTextureManager().bind(BACKGROUND_LOCATION); Matrix4f matrix = matrices.last().pose(); RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); @@ -200,7 +200,7 @@ public class FilteringScreen extends Screen { buffer.vertex(matrix, this.width, y2, 0.0F).uv(this.width / 32.0F, y2 / 32.0F).color(tint, tint, tint, alpha2).endVertex(); buffer.vertex(matrix, this.width, y1, 0.0F).uv(this.width / 32.0F, y1 / 32.0F).color(tint, tint, tint, alpha1).endVertex(); buffer.vertex(matrix, 0, y1, 0.0F).uv(0.0F, y1 / 32.0F).color(tint, tint, tint, alpha1).endVertex(); - tessellator.end(); + tesselator.end(); } @Override diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/config/entry/SearchFilterSyntaxHighlightingEntry.java b/runtime/src/main/java/me/shedaniel/rei/gui/config/entry/SearchFilterSyntaxHighlightingEntry.java new file mode 100644 index 000000000..15e127c1d --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/gui/config/entry/SearchFilterSyntaxHighlightingEntry.java @@ -0,0 +1,115 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.gui.config.entry; + +import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.platform.Window; +import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.clothconfig2.gui.entries.TooltipListEntry; +import me.shedaniel.rei.gui.config.SyntaxHighlightingMode; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.chat.NarratorChatListener; +import net.minecraft.client.gui.components.AbstractButton; +import net.minecraft.client.gui.components.AbstractWidget; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.chat.TranslatableComponent; + +import java.util.List; +import java.util.Optional; +import java.util.function.Consumer; + +public class SearchFilterSyntaxHighlightingEntry extends TooltipListEntry<SyntaxHighlightingMode> { + private final SyntaxHighlightingMode original; + private SyntaxHighlightingMode type; + private SyntaxHighlightingMode defaultValue; + private Consumer<SyntaxHighlightingMode> save; + private final AbstractWidget buttonWidget = new AbstractButton(0, 0, 0, 20, NarratorChatListener.NO_TITLE) { + @Override + public void onPress() { + + } + + @Override + public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { + setMessage(new TextComponent(type.toString())); + super.render(matrices, mouseX, mouseY, delta); + } + }; + private final List<GuiEventListener> children = ImmutableList.of(buttonWidget); + + @SuppressWarnings("deprecation") + public SearchFilterSyntaxHighlightingEntry(Component fieldName, SyntaxHighlightingMode type, SyntaxHighlightingMode defaultValue, Consumer<SyntaxHighlightingMode> save) { + super(fieldName, null); + this.original = type; + this.type = type; + this.defaultValue = defaultValue; + this.save = save; + } + + @Override + public boolean isEdited() { + return super.isEdited() || getValue() != original; + } + + @Override + public SyntaxHighlightingMode getValue() { + return type; + } + + @Override + public Optional<SyntaxHighlightingMode> getDefaultValue() { + return Optional.ofNullable(defaultValue); + } + + @Override + public void save() { + save.accept(type); + } + + @Override + public List<? extends GuiEventListener> children() { + return children; + } + + @Override + public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isSelected, float delta) { + super.render(matrices, index, y, x, entryWidth, entryHeight, mouseX, mouseY, isSelected, delta); + Window window = Minecraft.getInstance().getWindow(); + this.buttonWidget.active = this.isEditable(); + this.buttonWidget.y = y; + Component displayedFieldName = this.getDisplayedFieldName(); + if (Minecraft.getInstance().font.isBidirectional()) { + Minecraft.getInstance().font.drawShadow(matrices, displayedFieldName.getVisualOrderText(), window.getGuiScaledWidth() - x - Minecraft.getInstance().font.width(displayedFieldName), y + 6, 16777215); + this.buttonWidget.x = x; + } else { + Minecraft.getInstance().font.drawShadow(matrices, displayedFieldName.getVisualOrderText(), x, y + 6, this.getPreferredTextColor()); + this.buttonWidget.x = x + entryWidth - 150; + } + + this.buttonWidget.setWidth(150); + this.buttonWidget.render(matrices, mouseX, mouseY, delta); + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/ConfigManagerImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/ConfigManagerImpl.java index 90a99b45f..20761c828 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/ConfigManagerImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/ConfigManagerImpl.java @@ -57,10 +57,8 @@ import me.shedaniel.rei.gui.ContainerScreenOverlay; import me.shedaniel.rei.gui.TransformingScreen; import me.shedaniel.rei.gui.WarningAndErrorScreen; import me.shedaniel.rei.gui.config.RecipeScreenType; -import me.shedaniel.rei.gui.config.entry.FilteringEntry; -import me.shedaniel.rei.gui.config.entry.NoFilteringEntry; -import me.shedaniel.rei.gui.config.entry.RecipeScreenTypeEntry; -import me.shedaniel.rei.gui.config.entry.ReloadPluginsEntry; +import me.shedaniel.rei.gui.config.SyntaxHighlightingMode; +import me.shedaniel.rei.gui.config.entry.*; import me.shedaniel.rei.gui.credits.CreditsScreen; import me.shedaniel.rei.impl.filtering.FilteringRule; import me.shedaniel.rei.impl.filtering.rules.ManualFilteringRule; @@ -172,6 +170,9 @@ public class ConfigManagerImpl implements ConfigManager { Collections.singletonList(new RecipeScreenTypeEntry(220, new TranslatableComponent(i13n), getUnsafely(field, config, RecipeScreenType.UNSET), getUnsafely(field, defaults), type -> setUnsafely(field, config, type))) , (field) -> field.getType() == RecipeScreenType.class, ConfigObjectImpl.UseSpecialRecipeTypeScreen.class); guiRegistry.registerAnnotationProvider((i13n, field, config, defaults, guiProvider) -> + Collections.singletonList(new SearchFilterSyntaxHighlightingEntry( new TranslatableComponent(i13n), getUnsafely(field, config, SyntaxHighlightingMode.COLORFUL), getUnsafely(field, defaults), type -> setUnsafely(field, config, type))) + , (field) -> field.getType() == SyntaxHighlightingMode.class, ConfigObjectImpl.UseSpecialSearchFilterSyntaxHighlightingScreen.class); + guiRegistry.registerAnnotationProvider((i13n, field, config, defaults, guiProvider) -> REIHelper.getInstance().getPreviousContainerScreen() == null || Minecraft.getInstance().getConnection() == null || Minecraft.getInstance().getConnection().getRecipeManager() == null ? Collections.singletonList(new NoFilteringEntry(220, getUnsafely(field, config, new ArrayList<>()), getUnsafely(field, defaults), list -> setUnsafely(field, config, list))) : diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/ConfigObjectImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/ConfigObjectImpl.java index fa69e8a66..aee2abfe4 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/ConfigObjectImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/ConfigObjectImpl.java @@ -346,6 +346,11 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { return Mth.clamp(appearance.verticalEntriesBoundaries, 0.1,1); } + @Override + public SyntaxHighlightingMode getSyntaxHighlightingMode() { + return appearance.syntaxHighlightingMode; + } + @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) @interface DontApplyFieldName {} @@ -356,6 +361,10 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) + @interface UseSpecialSearchFilterSyntaxHighlightingScreen {} + + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD}) @interface UseFilteringScreen {} @Retention(RetentionPolicy.RUNTIME) @@ -413,6 +422,7 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { @UsePercentage(min = 0.1, max = 1.0, prefix = "Limit: ") private double horizontalEntriesBoundaries = 1.0; @UsePercentage(min = 0.1, max = 1.0, prefix = "Limit: ") private double verticalEntriesBoundaries = 1.0; + @UseSpecialSearchFilterSyntaxHighlightingScreen private SyntaxHighlightingMode syntaxHighlightingMode = SyntaxHighlightingMode.COLORFUL; } public static class Functionality { diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/OverlaySearchFieldSyntaxHighlighter.java b/runtime/src/main/java/me/shedaniel/rei/impl/OverlaySearchFieldSyntaxHighlighter.java index c63895f2c..3d8a8ba97 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/OverlaySearchFieldSyntaxHighlighter.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/OverlaySearchFieldSyntaxHighlighter.java @@ -2,9 +2,10 @@ package me.shedaniel.rei.impl; import me.shedaniel.rei.gui.OverlaySearchField; import me.shedaniel.rei.impl.search.ArgumentsRegistry; +import net.minecraft.util.IntRange; import org.jetbrains.annotations.ApiStatus; -import java.util.List; +import java.util.Collection; import java.util.function.Consumer; @ApiStatus.Internal @@ -20,27 +21,29 @@ public class OverlaySearchFieldSyntaxHighlighter implements Consumer<String> { @Override public void accept(String text) { this.highlighted = new byte[text.length()]; - SearchArgument.ProcessedSink sink = new SearchArgument.ProcessedSink() { + SearchArgument.processSearchTerm(text, new SearchArgument.ProcessedSink() { @Override public void addQuote(int index) { highlighted[index] = -2; } - + @Override public void addSplitter(int index) { highlighted[index] = -1; } - }; - List<SearchArgument.SearchArguments> arguments = SearchArgument.processSearchTerm(text, sink); - for (SearchArgument.SearchArguments argument : arguments) { - if (!argument.isAlways()) { - for (SearchArgument<?, ?> searchArgument : argument.getArguments()) { - int argIndex = ArgumentsRegistry.ARGUMENT_LIST.indexOf(searchArgument.getArgument()) + 1; - for (int i = searchArgument.start(); i < searchArgument.end(); i++) { - highlighted[i] = (byte) argIndex; + + @Override + public void addPart(SearchArgument<?, ?> argument, Collection<IntRange> grammarRanges, int index) { + int argIndex = ArgumentsRegistry.ARGUMENT_LIST.indexOf(argument.getArgument()) * 2 + 1; + for (int i = argument.start(); i < argument.end(); i++) { + highlighted[i] = (byte) argIndex; + } + for (IntRange grammarRange : grammarRanges) { + for (int i = grammarRange.getMinInclusive(); i <= grammarRange.getMaxInclusive(); i++) { + highlighted[i + index] = (byte) (argIndex + 1); } } } - } + }); } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/SearchArgument.java b/runtime/src/main/java/me/shedaniel/rei/impl/SearchArgument.java index 78798ac87..8746bcb91 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/SearchArgument.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/SearchArgument.java @@ -37,6 +37,7 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.Minecraft; import net.minecraft.network.chat.Component; +import net.minecraft.util.IntRange; import net.minecraft.util.Unit; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.mutable.Mutable; @@ -44,6 +45,7 @@ import org.apache.commons.lang3.mutable.MutableObject; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; +import java.util.Collection; import java.util.List; import java.util.Locale; import java.util.regex.Matcher; @@ -87,6 +89,8 @@ public class SearchArgument<T, R> { void addQuote(int index); void addSplitter(int index); + + void addPart(SearchArgument<?, ?> argument, Collection<IntRange> grammarRanges, int index); } @ApiStatus.Internal @@ -107,8 +111,9 @@ public class SearchArgument<T, R> { for (Argument<?, ?> argument : ArgumentsRegistry.ARGUMENT_LIST) { MatchStatus status = argument.matchesArgumentPrefix(term); if (status.isMatched()) { + SearchArgument<?, ?> searchArgument; if (terms.group(1) != null) { - arguments.add(new SearchArgument<>(argument, status.getText(), !status.isInverted(), terms.start(1) + tokenStartIndex, terms.end(1) + tokenStartIndex, !status.shouldPreserveCasing())); + arguments.add(searchArgument = new SearchArgument<>(argument, status.getText(), !status.isInverted(), terms.start(1) + tokenStartIndex, terms.end(1) + tokenStartIndex, !status.shouldPreserveCasing())); if (sink != null) { sink.addQuote(terms.start() + tokenStartIndex); if (terms.end() - 1 + tokenStartIndex < searchTerm.length()) { @@ -116,7 +121,10 @@ public class SearchArgument<T, R> { } } } else { - arguments.add(new SearchArgument<>(argument, status.getText(), !status.isInverted(), terms.start(2) + tokenStartIndex, terms.end(2) + tokenStartIndex, !status.shouldPreserveCasing())); + arguments.add(searchArgument = new SearchArgument<>(argument, status.getText(), !status.isInverted(), terms.start(2) + tokenStartIndex, terms.end(2) + tokenStartIndex, !status.shouldPreserveCasing())); + } + if (sink != null) { + sink.addPart(searchArgument, status.grammarRanges(), terms.start() + tokenStartIndex); } break; } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/search/Argument.java b/runtime/src/main/java/me/shedaniel/rei/impl/search/Argument.java index 2806f2d52..e1769abfe 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/search/Argument.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/search/Argument.java @@ -53,9 +53,9 @@ public abstract class Argument<T, R> { public MatchStatus matchesArgumentPrefix(String text) { String prefix = getPrefix(); if (prefix == null) return MatchStatus.unmatched(); - if (text.startsWith("-" + prefix)) return MatchStatus.invertMatched(text.substring(1 + prefix.length())); - if (text.startsWith(prefix + "-")) return MatchStatus.invertMatched(text.substring(1 + prefix.length())); - if (text.startsWith(prefix)) return MatchStatus.matched(text.substring(prefix.length())); + if (text.startsWith("-" + prefix)) return MatchStatus.invertMatched(text.substring(1 + prefix.length())).grammar(0, prefix.length() + 1); + if (text.startsWith(prefix + "-")) return MatchStatus.invertMatched(text.substring(1 + prefix.length())).grammar(0, prefix.length() + 1); + if (text.startsWith(prefix)) return MatchStatus.matched(text.substring(prefix.length())).grammar(0, prefix.length()); return MatchStatus.unmatched(); } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/search/MatchStatus.java b/runtime/src/main/java/me/shedaniel/rei/impl/search/MatchStatus.java index 8f56715d1..5642502bb 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/search/MatchStatus.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/search/MatchStatus.java @@ -23,10 +23,13 @@ package me.shedaniel.rei.impl.search; +import net.minecraft.util.IntRange; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; @ApiStatus.Internal @@ -36,6 +39,7 @@ public final class MatchStatus { @Nullable private final String text; private final boolean preserveCasing; + private final List<IntRange> grammarRanges = new ArrayList<>(); private MatchStatus(MatchType type, @Nullable String text, boolean preserveCasing) { this.type = type; @@ -67,6 +71,17 @@ public final class MatchStatus { return new MatchStatus(!inverted ? MatchType.MATCHED : MatchType.INVERT_MATCHED, Objects.requireNonNull(text), preserveCasing); } + public List<IntRange> grammarRanges() { + return grammarRanges; + } + + public MatchStatus grammar(int start, int end) { + if (end - 1 >= start) { + this.grammarRanges.add(IntRange.of(start, end - 1)); + } + return this; + } + public MatchStatus invert() { if (isMatched()) { this.type = isInverted() ? MatchType.MATCHED : MatchType.INVERT_MATCHED; diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/search/RegexArgument.java b/runtime/src/main/java/me/shedaniel/rei/impl/search/RegexArgument.java index aeba0bc50..43f591cc7 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/search/RegexArgument.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/search/RegexArgument.java @@ -57,7 +57,9 @@ public final class RegexArgument extends Argument<@Nullable Pattern, String> { matchText = matchText.substring(1); } if (matchText.length() >= 3 && matchText.startsWith("r/") && matchText.endsWith("/")) - return MatchStatus.result(matchText.substring(2, matchText.length() - 1), true, inverted); + return MatchStatus.result(matchText.substring(2, matchText.length() - 1), true, inverted) + .grammar(0, inverted ? 3 : 2) + .grammar(text.length() - 1, text.length()); return MatchStatus.unmatched(); } diff --git a/src/main/resources/assets/roughlyenoughitems/lang/en_us.json b/src/main/resources/assets/roughlyenoughitems/lang/en_us.json index 828b6248e..dc786d240 100755 --- a/src/main/resources/assets/roughlyenoughitems/lang/en_us.json +++ b/src/main/resources/assets/roughlyenoughitems/lang/en_us.json @@ -212,6 +212,12 @@ "config.roughlyenoughitems.scrollingEntryListWidget.boolean.false": "Paginated", "config.roughlyenoughitems.horizontalEntriesBoundaries": "Horizontal Entries Boundaries:", "config.roughlyenoughitems.verticalEntriesBoundaries": "Vertical Entries Boundaries:", + "config.roughlyenoughitems.syntaxHighlightingMode": "Syntax Highlighting Mode:", + "config.roughlyenoughitems.syntaxHighlightingMode.config": "%s", + "config.roughlyenoughitems.syntaxHighlightingMode.plain": "Plain", + "config.roughlyenoughitems.syntaxHighlightingMode.plain_underscored": "Plain (Underscored)", + "config.roughlyenoughitems.syntaxHighlightingMode.colorful": "Colorful", + "config.roughlyenoughitems.syntaxHighlightingMode.colorful_underscored": "Colorful (Underscored)", "config.roughlyenoughitems.filteringScreen": "Customized Filtering", "config.roughlyenoughitems.filteringRulesScreen": "Customized Filtering Rules", "config.roughlyenoughitems.filteringRulesScreen.new": "Create Filtering Rule", |
