diff --git a/cloud-core/src/main/java/cloud/commandframework/arguments/standard/StringArgument.java b/cloud-core/src/main/java/cloud/commandframework/arguments/standard/StringArgument.java index 34d8c4e1..7a4adab6 100644 --- a/cloud-core/src/main/java/cloud/commandframework/arguments/standard/StringArgument.java +++ b/cloud-core/src/main/java/cloud/commandframework/arguments/standard/StringArgument.java @@ -30,6 +30,7 @@ import cloud.commandframework.captions.CaptionVariable; import cloud.commandframework.captions.StandardCaptionKeys; import cloud.commandframework.context.CommandContext; import cloud.commandframework.exceptions.parsing.ParserException; +import cloud.commandframework.util.StringUtils; import org.checkerframework.checker.nullness.qual.NonNull; import java.util.Collections; @@ -317,19 +318,30 @@ public final class StringArgument extends CommandArgument { } final String string = sj.toString(); - Matcher matcher = QUOTED_DOUBLE.matcher(string); + final Matcher doubleMatcher = QUOTED_DOUBLE.matcher(string); + String doubleMatch = null; + if (doubleMatcher.find()) { + doubleMatch = doubleMatcher.group("inner"); + } + final Matcher singleMatcher = QUOTED_SINGLE.matcher(string); + String singleMatch = null; + if (singleMatcher.find()) { + singleMatch = singleMatcher.group("inner"); + } + String inner = null; - if (matcher.find()) { - inner = matcher.group("inner"); - } else { - matcher = QUOTED_SINGLE.matcher(string); - if (matcher.find()) { - inner = matcher.group("inner"); - } + if (singleMatch != null && doubleMatch != null) { + final int singleIndex = string.indexOf(singleMatch); + final int doubleIndex = string.indexOf(doubleMatch); + inner = doubleIndex < singleIndex ? doubleMatch : singleMatch; + } else if (singleMatch == null && doubleMatch != null) { + inner = doubleMatch; + } else if (singleMatch != null) { + inner = singleMatch; } if (inner != null) { - final int numSpaces = (int) inner.chars().filter(c -> c == ' ').count(); + final int numSpaces = StringUtils.countCharOccurrences(inner, ' '); for (int i = 0; i <= numSpaces; i++) { inputQueue.remove(); } @@ -341,7 +353,7 @@ public final class StringArgument extends CommandArgument { } } - inner = inner.replace("\\\"", "\"").replace("\\\'", "\""); + inner = inner.replace("\\\"", "\"").replace("\\'", "'"); return ArgumentParseResult.success(inner); } diff --git a/cloud-core/src/main/java/cloud/commandframework/util/StringUtils.java b/cloud-core/src/main/java/cloud/commandframework/util/StringUtils.java new file mode 100644 index 00000000..b1ab4b9a --- /dev/null +++ b/cloud-core/src/main/java/cloud/commandframework/util/StringUtils.java @@ -0,0 +1,53 @@ +// +// MIT License +// +// Copyright (c) 2020 Alexander Söderberg & Contributors +// +// 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 cloud.commandframework.util; + +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * String utilities + */ +public final class StringUtils { + + private StringUtils() { + } + + /** + * Count the occurrences of a character in a string + * + * @param haystack The string to search in + * @param needle The character to count for + * @return Number of occurrences + */ + public static int countCharOccurrences(final @NonNull String haystack, final char needle) { + int occurrences = 0; + for (int i = 0; i < haystack.length(); i++) { + if (haystack.charAt(i) == needle) { + occurrences++; + } + } + return occurrences; + } + +} diff --git a/cloud-core/src/main/java/cloud/commandframework/util/package-info.java b/cloud-core/src/main/java/cloud/commandframework/util/package-info.java new file mode 100644 index 00000000..225ff2bb --- /dev/null +++ b/cloud-core/src/main/java/cloud/commandframework/util/package-info.java @@ -0,0 +1,28 @@ +// +// MIT License +// +// Copyright (c) 2020 Alexander Söderberg & Contributors +// +// 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. +// + +/** + * Utility classes + */ +package cloud.commandframework.util;