Add greedy charset option to string argument

https://github.com/Mojang/brigadier/pull/131
This commit is contained in:
2024-08-13 01:38:12 +08:00
parent 7ceb01d4e5
commit d2e25c1bfe
4 changed files with 124 additions and 8 deletions
@@ -174,9 +174,21 @@ public class StringReader implements ImmutableStringReader {
|| c == '.' || c == '+'; || c == '.' || c == '+';
} }
public static boolean isAllowedInUnquotedStringGreedy(final char c) {
return c != ' ' && c != SYNTAX_DOUBLE_QUOTE && c != SYNTAX_SINGLE_QUOTE && c != SYNTAX_ESCAPE;
}
public String readUnquotedString() { public String readUnquotedString() {
return readUnquotedString(true);
}
public String readUnquotedStringGreedy() {
return readUnquotedString(false);
}
private String readUnquotedString(boolean asciiOnly) {
final int start = cursor; final int start = cursor;
while (canRead() && isAllowedInUnquotedString(peek())) { while (canRead() && (asciiOnly ? isAllowedInUnquotedString(peek()) : isAllowedInUnquotedStringGreedy(peek()))) {
skip(); skip();
} }
return string.substring(start, cursor); return string.substring(start, cursor);
@@ -220,6 +232,14 @@ public class StringReader implements ImmutableStringReader {
} }
public String readString() throws CommandSyntaxException { public String readString() throws CommandSyntaxException {
return readString(true);
}
public String readStringGreedy() throws CommandSyntaxException {
return readString(false);
}
private String readString(boolean asciiOnly) throws CommandSyntaxException {
if (!canRead()) { if (!canRead()) {
return ""; return "";
} }
@@ -228,7 +248,7 @@ public class StringReader implements ImmutableStringReader {
skip(); skip();
return readStringUntil(next); return readStringUntil(next);
} }
return readUnquotedString(); return readUnquotedString(asciiOnly);
} }
public boolean readBoolean() throws CommandSyntaxException { public boolean readBoolean() throws CommandSyntaxException {
@@ -11,22 +11,32 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
public class StringArgumentType implements ArgumentType<String> { public class StringArgumentType implements ArgumentType<String> {
private final boolean greedyCharset;
private final StringType type; private final StringType type;
private StringArgumentType(final StringType type) { private StringArgumentType(final StringType type, final boolean greedyCharset) {
this.type = type; this.type = type;
this.greedyCharset = greedyCharset;
} }
public static StringArgumentType word() { public static StringArgumentType word() {
return new StringArgumentType(StringType.SINGLE_WORD); return word(false);
}
public static StringArgumentType word(boolean greedyCharset) {
return new StringArgumentType(StringType.SINGLE_WORD, greedyCharset);
} }
public static StringArgumentType string() { public static StringArgumentType string() {
return new StringArgumentType(StringType.QUOTABLE_PHRASE); return string(false);
}
public static StringArgumentType string(boolean greedyCharset) {
return new StringArgumentType(StringType.QUOTABLE_PHRASE, greedyCharset);
} }
public static StringArgumentType greedyString() { public static StringArgumentType greedyString() {
return new StringArgumentType(StringType.GREEDY_PHRASE); return new StringArgumentType(StringType.GREEDY_PHRASE, false);
} }
public static String getString(final CommandContext<?> context, final String name) { public static String getString(final CommandContext<?> context, final String name) {
@@ -37,6 +47,10 @@ public class StringArgumentType implements ArgumentType<String> {
return type; return type;
} }
public boolean hasGreedyCharset() {
return greedyCharset;
}
@Override @Override
public String parse(final StringReader reader) throws CommandSyntaxException { public String parse(final StringReader reader) throws CommandSyntaxException {
if (type == StringType.GREEDY_PHRASE) { if (type == StringType.GREEDY_PHRASE) {
@@ -44,11 +58,19 @@ public class StringArgumentType implements ArgumentType<String> {
reader.setCursor(reader.getTotalLength()); reader.setCursor(reader.getTotalLength());
return text; return text;
} else if (type == StringType.SINGLE_WORD) { } else if (type == StringType.SINGLE_WORD) {
if (this.greedyCharset) {
return reader.readUnquotedStringGreedy();
} else {
return reader.readUnquotedString(); return reader.readUnquotedString();
}
} else {
if (this.greedyCharset) {
return reader.readStringGreedy();
} else { } else {
return reader.readString(); return reader.readString();
} }
} }
}
@Override @Override
public String toString() { public String toString() {
@@ -132,6 +132,30 @@ public class StringReaderTest {
assertThat(reader.getRemaining(), equalTo(" world")); assertThat(reader.getRemaining(), equalTo(" world"));
} }
@Test
public void readUnquotedString_strictCharset() throws Exception {
final StringReader reader = new StringReader("1+1=2 2+2=4");
assertThat(reader.readString(), equalTo("1+1"));
assertThat(reader.getRead(), equalTo("1+1"));
assertThat(reader.getRemaining(), equalTo("=2 2+2=4"));
// Should not be able to read further -- as invalid character is present
assertThat(reader.readString(), equalTo(""));
}
@Test
public void readUnquotedString_strictCharsetQuoted() throws Exception {
final StringReader reader = new StringReader("\"1+1=2\" \"2+2=4\"");
assertThat(reader.readString(), equalTo("1+1=2"));
assertThat(reader.getRead(), equalTo("\"1+1=2\""));
assertThat(reader.getRemaining(), equalTo(" \"2+2=4\""));
reader.skipWhitespace();
assertThat(reader.readString(), equalTo("2+2=4"));
assertThat(reader.getRead(), equalTo("\"1+1=2\" \"2+2=4\""));
}
@Test @Test
public void readUnquotedString_empty() throws Exception { public void readUnquotedString_empty() throws Exception {
final StringReader reader = new StringReader(""); final StringReader reader = new StringReader("");
@@ -148,6 +172,40 @@ public class StringReaderTest {
assertThat(reader.getRemaining(), equalTo(" hello world")); assertThat(reader.getRemaining(), equalTo(" hello world"));
} }
@Test
public void readUnquotedStringGreedy() throws Exception {
final StringReader reader = new StringReader("hello world");
assertThat(reader.readStringGreedy(), equalTo("hello"));
assertThat(reader.getRead(), equalTo("hello"));
assertThat(reader.getRemaining(), equalTo(" world"));
}
@Test
public void readUnquotedStringGreedy_strictCharset() throws Exception {
final StringReader reader = new StringReader("1+1=2 2+2=4");
assertThat(reader.readStringGreedy(), equalTo("1+1=2"));
assertThat(reader.getRead(), equalTo("1+1=2"));
assertThat(reader.getRemaining(), equalTo(" 2+2=4"));
reader.skipWhitespace();
assertThat(reader.readStringGreedy(), equalTo("2+2=4"));
}
@Test
public void readUnquotedStringGreedy_empty() throws Exception {
final StringReader reader = new StringReader("");
assertThat(reader.readUnquotedStringGreedy(), equalTo(""));
assertThat(reader.getRead(), equalTo(""));
assertThat(reader.getRemaining(), equalTo(""));
}
@Test
public void readUnquotedStringGreedy_empty_withRemaining() throws Exception {
final StringReader reader = new StringReader(" hello world");
assertThat(reader.readUnquotedStringGreedy(), equalTo(""));
assertThat(reader.getRead(), equalTo(""));
assertThat(reader.getRemaining(), equalTo(" hello world"));
}
@Test @Test
public void readQuotedString() throws Exception { public void readQuotedString() throws Exception {
final StringReader reader = new StringReader("\"hello world\""); final StringReader reader = new StringReader("\"hello world\"");
@@ -27,6 +27,22 @@ public class StringArgumentTypeTest {
@Mock @Mock
private CommandContextBuilder<Object> context; private CommandContextBuilder<Object> context;
@Test
public void testParseWord_greedyCharset() throws Exception {
final StringReader reader = mock(StringReader.class);
when(reader.readUnquotedStringGreedy()).thenReturn("1+1=2");
assertThat(word(true).parse(reader), equalTo("1+1=2"));
verify(reader).readUnquotedStringGreedy();
}
@Test
public void testParseString_greedyCharset() throws Exception {
final StringReader reader = mock(StringReader.class);
when(reader.readStringGreedy()).thenReturn("1+1=2 2+2=4");
assertThat(string(true).parse(reader), equalTo("1+1=2 2+2=4"));
verify(reader).readStringGreedy();
}
@Test @Test
public void testParseWord() throws Exception { public void testParseWord() throws Exception {
final StringReader reader = mock(StringReader.class); final StringReader reader = mock(StringReader.class);