From e90bcb53565bbf17ad9341c9eb1343fb2450008e Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Sun, 25 Jun 2023 18:17:52 -0400 Subject: [PATCH 1/4] add Formatter#join --- .../minimessage/tag/resolver/Formatter.java | 49 +++++++++++++++++++ .../text/minimessage/tag/FormatterTest.java | 18 +++++++ 2 files changed, 67 insertions(+) diff --git a/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java index d0bf61a27..2f626eaea 100644 --- a/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java +++ b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java @@ -29,7 +29,12 @@ import java.text.NumberFormat; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAccessor; +import java.util.Arrays; import java.util.Locale; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ComponentLike; +import net.kyori.adventure.text.JoinConfiguration; import net.kyori.adventure.text.minimessage.tag.Tag; import net.kyori.adventure.text.minimessage.tag.TagPattern; import org.jetbrains.annotations.NotNull; @@ -139,4 +144,48 @@ public static TagResolver booleanChoice(@TagPattern final @NotNull String key, f return Tag.inserting(context.deserialize(value ? trueCase : falseCase)); }); } + + /** + * Creates a replacement that inserts a list of components. These components are joined together by {@link Component#join(JoinConfiguration.Builder, ComponentLike...)}. + * + *

This tag expects a separator as the first argument. A last separator may optionally be provided.

+ * + *

This replacement is auto-closing, so its style will not influence the style of following components.

+ * + * @param key the key + * @param components the components to join + * @return the placeholder + * @since 4.14.0 + */ + public static TagResolver join(@TagPattern final @NotNull String key, final @NotNull Iterable components) { + return TagResolver.resolver(key, (argumentQueue, context) -> { + final String separator = argumentQueue.popOr("Separator expected.").value(); + final JoinConfiguration.Builder configBuilder = JoinConfiguration.builder().separator(context.deserialize(separator)); + + if (argumentQueue.hasNext()) { + final String lastSeparator = argumentQueue.pop().value(); + configBuilder.lastSeparator(context.deserialize(lastSeparator)); + } + + JoinConfiguration config = configBuilder.build(); + return Tag.inserting(Component.join(config, components)); + }); + } + + /** + * Creates a replacement that inserts a list of components. These components are joined together by {@link Component#join(JoinConfiguration.Builder, ComponentLike...)}. + * + *

This tag expects a separator as the first argument. A last separator may optionally be provided.

+ * + *

This replacement is auto-closing, so its style will not influence the style of following components.

+ * + * @param key the key + * @param components the components to join + * @return the placeholder + * @since 4.14.0 + */ + public static TagResolver join(@TagPattern final @NotNull String key, final @NotNull ComponentLike@NotNull... components) { + return join(key, Arrays.asList(components)); + } + } diff --git a/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/FormatterTest.java b/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/FormatterTest.java index b37de3b39..828310568 100644 --- a/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/FormatterTest.java +++ b/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/FormatterTest.java @@ -25,7 +25,10 @@ import java.time.LocalDateTime; import java.time.Month; +import java.util.Arrays; + import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.JoinConfiguration; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.minimessage.AbstractTest; import org.junit.jupiter.api.Test; @@ -34,6 +37,7 @@ import static net.kyori.adventure.text.minimessage.tag.resolver.Formatter.booleanChoice; import static net.kyori.adventure.text.minimessage.tag.resolver.Formatter.choice; import static net.kyori.adventure.text.minimessage.tag.resolver.Formatter.date; +import static net.kyori.adventure.text.minimessage.tag.resolver.Formatter.join; import static net.kyori.adventure.text.minimessage.tag.resolver.Formatter.number; public class FormatterTest extends AbstractTest { @@ -125,4 +129,18 @@ void testBooleanChoice() { final Component expected = text("bah"); this.assertParsedEquals(expected, input, booleanChoice("first", true), booleanChoice("second", true), booleanChoice("third", true)); } + + @Test + void testJoinSeparator() { + final String input = ""; + final Component expected = Component.join(JoinConfiguration.separator(text(", ")), Arrays.asList(text("one"), text("two"), text("three"))); + this.assertParsedEquals(expected, input, join("list", text("one"), text("two"), text("three"))); + } + + @Test + void testJoinSeparatorWithLastSeparator() { + final String input = ""; + final Component expected = Component.join(JoinConfiguration.separators(text(", "), text(" and ")), Arrays.asList(text("one"), text("two"), text("three"))); + this.assertParsedEquals(expected, input, join("list", text("one"), text("two"), text("three"))); + } } From c2a11b2ed9d7f32337687dd4d3278bf1fdd93e9f Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Sun, 25 Jun 2023 18:43:23 -0400 Subject: [PATCH 2/4] correct version, join -> joining, checkstyle fixes --- .../text/minimessage/tag/resolver/Formatter.java | 13 ++++++------- .../text/minimessage/tag/FormatterTest.java | 7 +++---- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java index 2f626eaea..ad3915c5e 100644 --- a/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java +++ b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java @@ -31,7 +31,6 @@ import java.time.temporal.TemporalAccessor; import java.util.Arrays; import java.util.Locale; - import net.kyori.adventure.text.Component; import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.JoinConfiguration; @@ -155,9 +154,9 @@ public static TagResolver booleanChoice(@TagPattern final @NotNull String key, f * @param key the key * @param components the components to join * @return the placeholder - * @since 4.14.0 + * @since 4.15.0 */ - public static TagResolver join(@TagPattern final @NotNull String key, final @NotNull Iterable components) { + public static TagResolver joining(@TagPattern final @NotNull String key, final @NotNull Iterable components) { return TagResolver.resolver(key, (argumentQueue, context) -> { final String separator = argumentQueue.popOr("Separator expected.").value(); final JoinConfiguration.Builder configBuilder = JoinConfiguration.builder().separator(context.deserialize(separator)); @@ -167,7 +166,7 @@ public static TagResolver join(@TagPattern final @NotNull String key, final @Not configBuilder.lastSeparator(context.deserialize(lastSeparator)); } - JoinConfiguration config = configBuilder.build(); + final JoinConfiguration config = configBuilder.build(); return Tag.inserting(Component.join(config, components)); }); } @@ -182,10 +181,10 @@ public static TagResolver join(@TagPattern final @NotNull String key, final @Not * @param key the key * @param components the components to join * @return the placeholder - * @since 4.14.0 + * @since 4.15.0 */ - public static TagResolver join(@TagPattern final @NotNull String key, final @NotNull ComponentLike@NotNull... components) { - return join(key, Arrays.asList(components)); + public static TagResolver joining(@TagPattern final @NotNull String key, final @NotNull ComponentLike@NotNull... components) { + return joining(key, Arrays.asList(components)); } } diff --git a/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/FormatterTest.java b/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/FormatterTest.java index 828310568..97d86dc69 100644 --- a/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/FormatterTest.java +++ b/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/FormatterTest.java @@ -26,7 +26,6 @@ import java.time.LocalDateTime; import java.time.Month; import java.util.Arrays; - import net.kyori.adventure.text.Component; import net.kyori.adventure.text.JoinConfiguration; import net.kyori.adventure.text.format.NamedTextColor; @@ -37,7 +36,7 @@ import static net.kyori.adventure.text.minimessage.tag.resolver.Formatter.booleanChoice; import static net.kyori.adventure.text.minimessage.tag.resolver.Formatter.choice; import static net.kyori.adventure.text.minimessage.tag.resolver.Formatter.date; -import static net.kyori.adventure.text.minimessage.tag.resolver.Formatter.join; +import static net.kyori.adventure.text.minimessage.tag.resolver.Formatter.joining; import static net.kyori.adventure.text.minimessage.tag.resolver.Formatter.number; public class FormatterTest extends AbstractTest { @@ -134,13 +133,13 @@ void testBooleanChoice() { void testJoinSeparator() { final String input = ""; final Component expected = Component.join(JoinConfiguration.separator(text(", ")), Arrays.asList(text("one"), text("two"), text("three"))); - this.assertParsedEquals(expected, input, join("list", text("one"), text("two"), text("three"))); + this.assertParsedEquals(expected, input, joining("list", text("one"), text("two"), text("three"))); } @Test void testJoinSeparatorWithLastSeparator() { final String input = ""; final Component expected = Component.join(JoinConfiguration.separators(text(", "), text(" and ")), Arrays.asList(text("one"), text("two"), text("three"))); - this.assertParsedEquals(expected, input, join("list", text("one"), text("two"), text("three"))); + this.assertParsedEquals(expected, input, joining("list", text("one"), text("two"), text("three"))); } } From 40fa72aed66b9763648e65d76f27a7053dd4da35 Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Sun, 16 Jul 2023 14:40:27 -0400 Subject: [PATCH 3/4] lastSeparatorIfSerial argument --- .../minimessage/tag/resolver/Formatter.java | 5 ++++ .../text/minimessage/tag/FormatterTest.java | 27 ++++++++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java index ad3915c5e..9edf0fc37 100644 --- a/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java +++ b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java @@ -166,6 +166,11 @@ public static TagResolver joining(@TagPattern final @NotNull String key, final @ configBuilder.lastSeparator(context.deserialize(lastSeparator)); } + if (argumentQueue.hasNext()) { + final String lastSeparatorIfSerial = argumentQueue.pop().value(); + configBuilder.lastSeparatorIfSerial(context.deserialize(lastSeparatorIfSerial)); + } + final JoinConfiguration config = configBuilder.build(); return Tag.inserting(Component.join(config, components)); }); diff --git a/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/FormatterTest.java b/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/FormatterTest.java index 97d86dc69..8d491dca3 100644 --- a/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/FormatterTest.java +++ b/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/FormatterTest.java @@ -132,14 +132,33 @@ void testBooleanChoice() { @Test void testJoinSeparator() { final String input = ""; - final Component expected = Component.join(JoinConfiguration.separator(text(", ")), Arrays.asList(text("one"), text("two"), text("three"))); - this.assertParsedEquals(expected, input, joining("list", text("one"), text("two"), text("three"))); + final Iterable components = Arrays.asList(text("one"), text("two"), text("three")); + final Component expected = Component.join(JoinConfiguration.separator(text(", ")), components); + this.assertParsedEquals(expected, input, joining("list", components)); } @Test void testJoinSeparatorWithLastSeparator() { final String input = ""; - final Component expected = Component.join(JoinConfiguration.separators(text(", "), text(" and ")), Arrays.asList(text("one"), text("two"), text("three"))); - this.assertParsedEquals(expected, input, joining("list", text("one"), text("two"), text("three"))); + final Iterable components = Arrays.asList(text("one"), text("two"), text("three")); + final Component expected = Component.join(JoinConfiguration.separators(text(", "), text(" and ")), components); + this.assertParsedEquals(expected, input, joining("list", components)); } + + @Test + void testJoinSeparatorWithLastSeparatorIfSerialAndManyComponents() { + final String input = ""; + final Iterable components = Arrays.asList(text("one"), text("two"), text("three")); + final Component expected = Component.join(JoinConfiguration.builder().separator(text(", ")).lastSeparator(text(" and ")).lastSeparatorIfSerial(text(", and ")), components); + this.assertParsedEquals(expected, input, joining("list", components)); + } + + @Test + void testJoinSeparatorWithLastSeparatorIfSerialAndTwoComponents() { + final String input = ""; + final Iterable components = Arrays.asList(text("one"), text("two")); + final Component expected = Component.join(JoinConfiguration.builder().separator(text(", ")).lastSeparator(text(" and ")).lastSeparatorIfSerial(text(", and ")), components); + this.assertParsedEquals(expected, input, joining("list", components)); + } + } From 73c9e85256b245493f0f454c071afc4b98cb1972 Mon Sep 17 00:00:00 2001 From: Kieran Wallbanks Date: Wed, 30 Oct 2024 17:33:09 +0000 Subject: [PATCH 4/4] Update docs and make the first separator optional --- .../minimessage/tag/resolver/Formatter.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java index 9edf0fc37..dbeeae4e2 100644 --- a/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java +++ b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/resolver/Formatter.java @@ -147,18 +147,25 @@ public static TagResolver booleanChoice(@TagPattern final @NotNull String key, f /** * Creates a replacement that inserts a list of components. These components are joined together by {@link Component#join(JoinConfiguration.Builder, ComponentLike...)}. * - *

This tag expects a separator as the first argument. A last separator may optionally be provided.

+ *

This tag has three optional arguments; a separator, a last separator, and a last separator if serial. + * Each argument must be provided in order, with all preceding arguments present. + * The exact use of these three separators is documented in {@link JoinConfiguration}.

* *

This replacement is auto-closing, so its style will not influence the style of following components.

* * @param key the key * @param components the components to join * @return the placeholder - * @since 4.15.0 + * @see JoinConfiguration + * @since 4.18.0 */ public static TagResolver joining(@TagPattern final @NotNull String key, final @NotNull Iterable components) { return TagResolver.resolver(key, (argumentQueue, context) -> { - final String separator = argumentQueue.popOr("Separator expected.").value(); + if (!argumentQueue.hasNext()) { + return Tag.inserting(Component.join(JoinConfiguration.noSeparators(), components)); + } + + final String separator = argumentQueue.pop().value(); final JoinConfiguration.Builder configBuilder = JoinConfiguration.builder().separator(context.deserialize(separator)); if (argumentQueue.hasNext()) { @@ -179,14 +186,17 @@ public static TagResolver joining(@TagPattern final @NotNull String key, final @ /** * Creates a replacement that inserts a list of components. These components are joined together by {@link Component#join(JoinConfiguration.Builder, ComponentLike...)}. * - *

This tag expects a separator as the first argument. A last separator may optionally be provided.

+ *

This tag has three optional arguments; a separator, a last separator, and a last separator if serial. + * Each argument must be provided in order, with all preceding arguments present. + * The exact use of these three separators is documented in {@link JoinConfiguration}.

* *

This replacement is auto-closing, so its style will not influence the style of following components.

* * @param key the key * @param components the components to join * @return the placeholder - * @since 4.15.0 + * @see JoinConfiguration + * @since 4.18.0 */ public static TagResolver joining(@TagPattern final @NotNull String key, final @NotNull ComponentLike@NotNull... components) { return joining(key, Arrays.asList(components));