From c6a2f71457d97279cbe91fd3baf9be5e0808bcfb Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 12 Apr 2019 23:09:34 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D1=8F=20std?= =?UTF-8?q?::stripMargin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 7 +++ .../ownlang/modules/std/StringFunctions.java | 51 ++++++++++++++++++ .../com/annimon/ownlang/modules/std/std.java | 1 + .../resources/modules/std/stripMargin.own | 54 +++++++++++++++++++ 4 files changed, 113 insertions(+) create mode 100644 src/test/resources/modules/std/stripMargin.own diff --git a/build.gradle b/build.gradle index 62f8729..a18c3f0 100644 --- a/build.gradle +++ b/build.gradle @@ -133,4 +133,11 @@ sonarqube { property "sonar.projectKey", "aNNiMON_Own-Programming-Language-Tutorial" property "sonar.host.url", "https://sonarcloud.io" } +} + +test { + testLogging { + events "passed", "skipped", "failed" + exceptionFormat "full" + } } \ No newline at end of file diff --git a/src/main/java/com/annimon/ownlang/modules/std/StringFunctions.java b/src/main/java/com/annimon/ownlang/modules/std/StringFunctions.java index 21d37bb..774bd60 100644 --- a/src/main/java/com/annimon/ownlang/modules/std/StringFunctions.java +++ b/src/main/java/com/annimon/ownlang/modules/std/StringFunctions.java @@ -3,6 +3,7 @@ package com.annimon.ownlang.modules.std; import com.annimon.ownlang.lib.Arguments; import com.annimon.ownlang.lib.ArrayValue; import com.annimon.ownlang.lib.NumberValue; +import com.annimon.ownlang.lib.StringValue; import com.annimon.ownlang.lib.Value; import java.io.UnsupportedEncodingException; @@ -31,4 +32,54 @@ public final class StringFunctions { final int radix = (args.length == 2) ? args[1].asInt() : 10; return NumberValue.of(Long.parseLong(args[0].asString(), radix)); } + + static Value stripMargin(Value[] args) { + Arguments.checkOrOr(1, 2, args.length); + final String input = args[0].asString(); + final String marginPrefix = (args.length == 2) ? args[1].asString() : "|"; + if (!input.contains(marginPrefix)) { + return args[0]; + } + final String[] lines = input.split("\\r?\\n"); + + // First blank line is omitted + final StringBuilder sb = new StringBuilder(); + final int firstLineIndex = (isBlank(lines[0])) ? 1 : 0; + final int lastLineIndex = lines.length - 1; + int index = firstLineIndex; + while (true) { + sb.append(strip(lines[index], marginPrefix)); + if (++index >= lastLineIndex) break; + sb.append('\n'); + } + // Process last line + if (lastLineIndex >= (firstLineIndex + 1) && !isBlank(lines[lastLineIndex])) { + sb.append('\n').append(strip(lines[lastLineIndex], marginPrefix)); + } + return new StringValue(sb.toString()); + } + + private static String strip(String str, String marginPrefix) { + final int nonBlankIndex = firstNonBlankIndex(str); + if (str.startsWith(marginPrefix, nonBlankIndex)) { + return str.substring(nonBlankIndex + marginPrefix.length()); + } else { + return str; + } + } + + private static boolean isBlank(String str) { + return firstNonBlankIndex(str) == str.length(); + } + + private static int firstNonBlankIndex(String str) { + final int length = str.length(); + for (int index = 0; index < length; index++) { + final char ch = str.charAt(index); + if (ch != ' ' && ch != '\t' && !Character.isWhitespace(ch)) { + return index; + } + } + return length; + } } diff --git a/src/main/java/com/annimon/ownlang/modules/std/std.java b/src/main/java/com/annimon/ownlang/modules/std/std.java index 023498a..eca4d2b 100644 --- a/src/main/java/com/annimon/ownlang/modules/std/std.java +++ b/src/main/java/com/annimon/ownlang/modules/std/std.java @@ -55,6 +55,7 @@ public final class std implements Module { Functions.set("replaceFirst", new std_replacefirst()); Functions.set("parseInt", StringFunctions::parseInt); Functions.set("parseLong", StringFunctions::parseLong); + Functions.set("stripMargin", StringFunctions::stripMargin); // Arrays and maps Functions.set("newarray", new std_newarray()); diff --git a/src/test/resources/modules/std/stripMargin.own b/src/test/resources/modules/std/stripMargin.own new file mode 100644 index 0000000..e5ba625 --- /dev/null +++ b/src/test/resources/modules/std/stripMargin.own @@ -0,0 +1,54 @@ +use "std" + +def testStripMargin() { + testCases = [ + "|abc".stripMargin(), + " |abc".stripMargin(), + " + |abc".stripMargin(), + "|abc + ".stripMargin(), + " + |abc + ".stripMargin(), + "abc".stripMargin(""), + "abc".stripMargin(), + "#abc".stripMargin("#"), + "| abc".stripMargin("| "), + " + | abc + ".stripMargin("| "), + "xxxabc".stripMargin("xxx"), + " + xxxabc".stripMargin("xxx"), + " + xxxabc + ".stripMargin("xxx") + ] + for actual : testCases { + assertEquals("abc", actual) + } +} + +def testStripMargin2() { + assertEquals("123\n456\n789", "123 + |456 + |789".stripMargin()) + assertEquals("123\n456\n789", "|123 + |456 + |789".stripMargin()) + assertEquals("123\n456\n789", " + |123 + |456 + |789".stripMargin()) + assertEquals("123\n456\n789", " + |123 + |456 + |789 + ".stripMargin()) + assertEquals("123\n456\n789", " + //123 + //456 + //789 + ".stripMargin("//")) +} \ No newline at end of file