blob: 4ac9bd369b9b17fb4ac046326b024d94b7c43c9b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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;
};
}
}
|