summaryrefslogtreecommitdiff
path: root/dicore3/command/src/main/java/io/dico/dicore/command/parameter/IArgumentPreProcessor.java
diff options
context:
space:
mode:
authorDico200 <dico.karssiens@gmail.com>2018-07-25 01:53:23 +0100
committerDico200 <dico.karssiens@gmail.com>2018-07-25 01:53:23 +0100
commit44587e49ff1840219d9bc44844d4a3a6cd8ac5de (patch)
tree276ae9625795e9d79fc7db8592dbcb3a1af60928 /dicore3/command/src/main/java/io/dico/dicore/command/parameter/IArgumentPreProcessor.java
parent5e168847c2624b767deb9da310ecfdf169e0f43c (diff)
Add dicore3-command
Diffstat (limited to 'dicore3/command/src/main/java/io/dico/dicore/command/parameter/IArgumentPreProcessor.java')
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/IArgumentPreProcessor.java126
1 files changed, 126 insertions, 0 deletions
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/IArgumentPreProcessor.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/IArgumentPreProcessor.java
new file mode 100644
index 0000000..4ac9bd3
--- /dev/null
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/IArgumentPreProcessor.java
@@ -0,0 +1,126 @@
+package io.dico.dicore.command.parameter;
+
+/**
+ * An interface to process tokens such as quotes
+ */
+public interface IArgumentPreProcessor {
+
+ /**
+ * Preprocess the arguments without modifying the array.
+ * Might return the same array (in which case no changes were made).
+ *
+ * @param argStart the index within the array where the given arguments start (the part before that identifies the command)
+ * @param args the arguments
+ * @return the arguments after preprocessing
+ */
+ String[] process(int argStart, String[] args);
+
+ IArgumentPreProcessor NONE = (argStart, args) -> args;
+
+ /**
+ * Get an IArgumentPreProcessor that merges arguments between any two tokens
+ *
+ * @param tokens The tokens that the merged arguments should be enclosed by, in subsequent pairs.
+ * Example: []{}""
+ * This would mean the following would be merged: [ hello this is a merged argument]
+ * @param escapeChar the char that can be used to escape the given tokens
+ * @return The IArgumentPreProcessor
+ */
+ static IArgumentPreProcessor mergeOnTokens(String tokens, char escapeChar) {
+ if (tokens.isEmpty() || (tokens.length() & 1) != 0) {
+ throw new IllegalArgumentException();
+ }
+
+ return (argStart, args) -> {
+ if (!(0 <= argStart && argStart <= args.length)) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ args = args.clone();
+ int removeCount = 0;
+ int closingTokenIdx = 0;
+ int sectionStart = -1;
+
+ for (int i = argStart; i < args.length; i++) {
+ String arg = args[i];
+ if (arg == null || arg.isEmpty()) {
+ continue;
+ }
+
+ if (closingTokenIdx != 0) {
+ int idx = tokens.indexOf(arg.charAt(arg.length() - 1));
+ if (idx == closingTokenIdx) {
+
+ // count escape chars
+ int index = arg.length() - 1;
+ int count = 0;
+ while (index > 0 && arg.charAt(--index) == escapeChar) {
+ count++;
+ }
+
+ // remove the final char plus half the count, rounding upwards.
+ args[i] = arg.substring(0, args.length - 1 - (count + 1) / 2);
+
+ if ((count & 1) == 0) {
+ // not escaped
+ StringBuilder concat = new StringBuilder(args[sectionStart].substring(1));
+ for (int j = sectionStart + 1; j <= i; j++) {
+ concat.append(' ').append(args[j]);
+ args[j] = null;
+ removeCount++;
+ }
+
+ args[sectionStart] = concat.toString();
+
+ sectionStart = -1;
+ closingTokenIdx = 0;
+
+ } else {
+ // it's escaped
+ // add final char because it was escaped
+ args[i] += tokens.charAt(closingTokenIdx);
+
+ }
+ }
+
+ if (i == args.length - 1) {
+ // if the closing token isn't found, reset state and start from the index subsequent to the one where the opener was found
+ // it should also undo removal of any escapes... it doesn't do that
+ i = sectionStart + 1;
+ closingTokenIdx = 0;
+ sectionStart = -1;
+ }
+
+ continue;
+ }
+
+ int idx = tokens.indexOf(arg.charAt(0));
+ if (idx == -1 || (idx & 1) != 0) {
+ continue;
+ }
+
+ closingTokenIdx = idx | 1;
+ sectionStart = i;
+
+ // make sure to check from the current index for a closer
+ i--;
+ }
+
+ if (removeCount == 0) {
+ return args;
+ }
+
+ String[] result = new String[args.length - removeCount];
+ int i = 0;
+ for (String arg : args) {
+ if (arg != null) {
+ result[i++] = arg;
+ }
+ }
+
+ return result;
+ };
+
+ }
+
+}