diff --git a/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/SelectorTag.java b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/SelectorTag.java new file mode 100644 index 000000000..33f45fa68 --- /dev/null +++ b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/SelectorTag.java @@ -0,0 +1,78 @@ +/* + * This file is part of adventure, licensed under the MIT License. + * + * Copyright (c) 2017-2022 KyoriPowered + * + * 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 net.kyori.adventure.text.minimessage.tag.standard; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ComponentLike; +import net.kyori.adventure.text.SelectorComponent; +import net.kyori.adventure.text.minimessage.Context; +import net.kyori.adventure.text.minimessage.ParsingException; +import net.kyori.adventure.text.minimessage.internal.serializer.Emitable; +import net.kyori.adventure.text.minimessage.internal.serializer.SerializableResolver; +import net.kyori.adventure.text.minimessage.tag.Tag; +import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import org.jetbrains.annotations.Nullable; + +/** + * Insert a selector component into the result. + * + * @since 4.11.0 + */ +final class SelectorTag { + private static final String SEL = "sel"; + private static final String SELECTOR = "selector"; + + static final TagResolver RESOLVER = SerializableResolver.claimingComponent( + StandardTags.names(SEL, SELECTOR), + SelectorTag::create, + SelectorTag::claim + ); + + private SelectorTag() { + } + + static Tag create(final ArgumentQueue args, final Context ctx) throws ParsingException { + final String key = args.popOr("A selection key is required").value(); + ComponentLike separator = null; + if (args.hasNext()) { + separator = ctx.deserialize(args.pop().value()); + } + + return Tag.inserting(Component.selector(key, separator)); + } + + static @Nullable Emitable claim(final Component input) { + if (!(input instanceof SelectorComponent)) return null; + + final SelectorComponent st = (SelectorComponent) input; + return emit -> { + emit.tag(SEL); + emit.argument(st.pattern()); + if (st.separator() != null) { + emit.argument(st.separator()); + } + }; + } +} diff --git a/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/StandardTags.java b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/StandardTags.java index 3674d5802..1b87c0d67 100644 --- a/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/StandardTags.java +++ b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/StandardTags.java @@ -59,7 +59,8 @@ private StandardTags() { RainbowTag.RESOLVER, ResetTag.RESOLVER, NewlineTag.RESOLVER, - TransitionTag.RESOLVER + TransitionTag.RESOLVER, + SelectorTag.RESOLVER ) .build(); @@ -214,6 +215,18 @@ public static TagResolver transition() { return NewlineTag.RESOLVER; } + /** + * Get a resolver for the {@value SelectorTag#SELECTOR} tag. + * + *

This tag also responds to {@value SelectorTag#SEL}.

+ * + * @return a resolver for the {@value SelectorTag#SELECTOR} tag + * @since 4.11.0 + */ + public static @NotNull TagResolver selector() { + return SelectorTag.RESOLVER; + } + /** * Get a resolver that handles all default standard tags. * diff --git a/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/standard/SelectorTagTest.java b/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/standard/SelectorTagTest.java new file mode 100644 index 000000000..f046bf1f1 --- /dev/null +++ b/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/standard/SelectorTagTest.java @@ -0,0 +1,68 @@ +/* + * This file is part of adventure, licensed under the MIT License. + * + * Copyright (c) 2017-2022 KyoriPowered + * + * 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 net.kyori.adventure.text.minimessage.tag.standard; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.minimessage.AbstractTest; +import org.junit.jupiter.api.Test; + +import static net.kyori.adventure.text.Component.selector; +import static net.kyori.adventure.text.Component.text; + +class SelectorTagTest extends AbstractTest { + @Test + void testSerializeSelector() { + final String expected = "Hello there, !"; + + final TextComponent.Builder builder = text() + .content("Hello there, ") + .append(selector("@s")) + .append(text("!")); + + this.assertSerializedEquals(expected, builder); + } + + @Test + void testSelector() { + final String input = "Hello there, !"; + final Component expected = text() + .content("Hello there, ") + .append(selector("@s")) + .append(text("!")).build(); + + this.assertParsedEquals(expected, input); + } + + @Test + void testSeparator() { + final String input = "Hello there, !"; + final Component expected = text() + .content("Hello there, ") + .append(selector("@s", text("separator"))) + .append(text("!")).build(); + + this.assertParsedEquals(expected, input); + } +}