From f3ee15f97bd47a0bf69775eb05b80d480413957e Mon Sep 17 00:00:00 2001 From: The-Lum <86879521+The-Lum@users.noreply.github.com> Date: Tue, 9 Apr 2024 14:04:18 +0000 Subject: [PATCH] feat: add `%splitstrregex` builtin function From this request: - https://forum.plantuml.net/18827/%25splitstr-please-add-regex-support-as-second-argument Ack. & Ref.: - https://forum.plantuml.net/15374/delimited-string-split-into-an-array - https://forum.plantuml.net/18827/%25splitstr-please-add-regex-support-as-second-argument - https://www.javacodeexamples.com/java-stringtokenizer-using-regex-pattern/3570 --- .../sourceforge/plantuml/tim/TContext.java | 2 + .../plantuml/tim/stdlib/SplitStrRegex.java | 74 +++++++++++++++++++ .../plantuml/tim/TimTestUtils.java | 8 ++ .../tim/stdlib/SplitStrRegexTest.java | 34 +++++++++ .../plantuml/tim/stdlib/SplitStrTest.java | 34 +++++++++ 5 files changed, 152 insertions(+) create mode 100644 src/net/sourceforge/plantuml/tim/stdlib/SplitStrRegex.java create mode 100644 test/net/sourceforge/plantuml/tim/stdlib/SplitStrRegexTest.java create mode 100644 test/net/sourceforge/plantuml/tim/stdlib/SplitStrTest.java diff --git a/src/net/sourceforge/plantuml/tim/TContext.java b/src/net/sourceforge/plantuml/tim/TContext.java index 79188e5ca..3319522ca 100644 --- a/src/net/sourceforge/plantuml/tim/TContext.java +++ b/src/net/sourceforge/plantuml/tim/TContext.java @@ -131,6 +131,7 @@ import net.sourceforge.plantuml.tim.stdlib.ReverseHsluvColor; import net.sourceforge.plantuml.tim.stdlib.SetVariableValue; import net.sourceforge.plantuml.tim.stdlib.Size; import net.sourceforge.plantuml.tim.stdlib.SplitStr; +import net.sourceforge.plantuml.tim.stdlib.SplitStrRegex; import net.sourceforge.plantuml.tim.stdlib.StringFunction; import net.sourceforge.plantuml.tim.stdlib.Strlen; import net.sourceforge.plantuml.tim.stdlib.Strpos; @@ -214,6 +215,7 @@ public class TContext { functionsSet.addFunction(new RandomFunction()); functionsSet.addFunction(new GetAllTheme()); functionsSet.addFunction(new GetAllStdlib()); + functionsSet.addFunction(new SplitStrRegex()); // %standard_exists_function // %str_replace // !exit diff --git a/src/net/sourceforge/plantuml/tim/stdlib/SplitStrRegex.java b/src/net/sourceforge/plantuml/tim/stdlib/SplitStrRegex.java new file mode 100644 index 000000000..16bdfa5c9 --- /dev/null +++ b/src/net/sourceforge/plantuml/tim/stdlib/SplitStrRegex.java @@ -0,0 +1,74 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2024, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + */ +package net.sourceforge.plantuml.tim.stdlib; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import net.sourceforge.plantuml.json.JsonArray; +import net.sourceforge.plantuml.text.StringLocated; +import net.sourceforge.plantuml.tim.EaterException; +import net.sourceforge.plantuml.tim.TContext; +import net.sourceforge.plantuml.tim.TFunctionSignature; +import net.sourceforge.plantuml.tim.TMemory; +import net.sourceforge.plantuml.tim.expression.TValue; + +public class SplitStrRegex extends SimpleReturnFunction { + + public TFunctionSignature getSignature() { + return new TFunctionSignature("%splitstrregex", 2); + } + + @Override + public boolean canCover(int nbArg, Set namedArgument) { + return nbArg == 2; + } + + @Override + public TValue executeReturnFunction(TContext context, TMemory memory, StringLocated location, List values, + Map named) throws EaterException { + final JsonArray result = new JsonArray(); + + final String str = values.get(0).toString(); + final String separator = values.get(1).toString(); + + final String[] parts = str.split(separator); + for(String part : parts) + result.add(part); + + return TValue.fromJson(result); + } +} diff --git a/test/net/sourceforge/plantuml/tim/TimTestUtils.java b/test/net/sourceforge/plantuml/tim/TimTestUtils.java index c71b7d8a3..36b1c50a6 100644 --- a/test/net/sourceforge/plantuml/tim/TimTestUtils.java +++ b/test/net/sourceforge/plantuml/tim/TimTestUtils.java @@ -2,6 +2,7 @@ package net.sourceforge.plantuml.tim; import static org.junit.jupiter.api.Assertions.assertEquals; +import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -33,6 +34,13 @@ public class TimTestUtils { assertEquals(expected, tValue.toString()); } + // Tfunc: (String, String) -> (String) + public static void assertTimExpectedOutputFromInput(TFunction func, String input1, String input2, String expected) throws EaterException { + final List values = Arrays.asList(TValue.fromString(input1), TValue.fromString(input2)); + final TValue tValue = func.executeReturnFunction(null, null, null, values, null); + assertEquals(expected, tValue.toString()); + } + // Tfunc: (JsonValue) -> (String) public static void assertTimExpectedOutputFromInput(TFunction func, JsonValue input, String expected) throws EaterException { List values = Collections.singletonList(TValue.fromJson(input)); diff --git a/test/net/sourceforge/plantuml/tim/stdlib/SplitStrRegexTest.java b/test/net/sourceforge/plantuml/tim/stdlib/SplitStrRegexTest.java new file mode 100644 index 000000000..117422c76 --- /dev/null +++ b/test/net/sourceforge/plantuml/tim/stdlib/SplitStrRegexTest.java @@ -0,0 +1,34 @@ +package net.sourceforge.plantuml.tim.stdlib; + +import static net.sourceforge.plantuml.tim.TimTestUtils.assertTimExpectedOutputFromInput; + +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.api.IndicativeSentencesGeneration; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import net.sourceforge.plantuml.json.JsonValue; +import net.sourceforge.plantuml.tim.EaterException; +import net.sourceforge.plantuml.tim.TFunction; + +/** + * Tests the builtin function. + */ +@IndicativeSentencesGeneration(separator = ": ", generator = ReplaceUnderscores.class) + +class SplitStrRegexTest { + TFunction cut = new SplitStrRegex(); + final String cutName = "SplitStrRegex"; + + @ParameterizedTest(name = "[{index}] " + cutName + "(''{0}'', ''{1}'') = {2}") + @CsvSource(nullValues = "null", value = { + " abc~def~ghi, ~, '[\"abc\",\"def\",\"ghi\"]' ", + " foozbar, z, '[\"foo\",\"bar\"]' ", + " FooBar, (?=[A-Z]), '[\"Foo\",\"Bar\"]' ", + " SomeDumbExample, (?=[A-Z]), '[\"Some\",\"Dumb\",\"Example\"]' ", + }) + void Test_with_String(String input, String regex, String expected) throws EaterException { + assertTimExpectedOutputFromInput(cut, input, regex, expected); + } +} diff --git a/test/net/sourceforge/plantuml/tim/stdlib/SplitStrTest.java b/test/net/sourceforge/plantuml/tim/stdlib/SplitStrTest.java new file mode 100644 index 000000000..bf2be3219 --- /dev/null +++ b/test/net/sourceforge/plantuml/tim/stdlib/SplitStrTest.java @@ -0,0 +1,34 @@ +package net.sourceforge.plantuml.tim.stdlib; + +import static net.sourceforge.plantuml.tim.TimTestUtils.assertTimExpectedOutputFromInput; + +import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; +import org.junit.jupiter.api.IndicativeSentencesGeneration; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import net.sourceforge.plantuml.json.JsonValue; +import net.sourceforge.plantuml.tim.EaterException; +import net.sourceforge.plantuml.tim.TFunction; + +/** + * Tests the builtin function. + */ +@IndicativeSentencesGeneration(separator = ": ", generator = ReplaceUnderscores.class) + +class SplitStrTest { + TFunction cut = new SplitStr(); + final String cutName = "SplitStr"; + + @ParameterizedTest(name = "[{index}] " + cutName + "(''{0}'', ''{1}'') = {2}") + @CsvSource(nullValues = "null", value = { + " abc~def~ghi, ~, '[\"abc\",\"def\",\"ghi\"]' ", + " foozbar, z, '[\"foo\",\"bar\"]' ", + " FooBar, (?=[A-Z]), '[\"FooBar\"]' ", + " SomeDumbExample, (?=[A-Z]), '[\"SomeDumbExample\"]' ", + }) + void Test_with_String(String input, String regex, String expected) throws EaterException { + assertTimExpectedOutputFromInput(cut, input, regex, expected); + } +}