Fixed and cleaned up CommandContext.

- Removed all the inefficient removePortionOfArray stuff and replaced it by ArrayLists that accumulate content instead.
- Added new tests
- Swapped the arguments to assertEquals everywhere. First argument is "expected".
- Fixed warnings in the test case
- I put my original flag parser back and added support for putting flags anywhere. Looks and works better than that undocumented mindfuck zml put there.
This commit is contained in:
TomyLobo 2011-09-19 23:01:57 +02:00
parent c78e8a10d7
commit 2d86b1b40d
2 changed files with 78 additions and 33 deletions

View File

@ -18,12 +18,13 @@
package com.sk89q.minecraft.util.commands; package com.sk89q.minecraft.util.commands;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import static com.sk89q.util.ArrayUtil.removePortionOfArray;
public class CommandContext { public class CommandContext {
protected final String[] args; protected final String[] args;
@ -48,11 +49,18 @@ public class CommandContext {
* @throws CommandException This is thrown if flag fails for some reason. * @throws CommandException This is thrown if flag fails for some reason.
*/ */
public CommandContext(String[] args, Set<Character> valueFlags) throws CommandException { public CommandContext(String[] args, Set<Character> valueFlags) throws CommandException {
if (valueFlags == null) {
valueFlags = Collections.emptySet();
}
final String command = args[0];
List<String> argList = new ArrayList<String>(args.length);
argList.add(command);
// Go through empty args and multiword args first // Go through empty args and multiword args first
for (int i = 1; i < args.length; ++i) { for (int i = 1; i < args.length; ++i) {
final String arg = args[i]; String arg = args[i];
if (arg.isEmpty()) { if (arg.isEmpty()) {
args = removePortionOfArray(args, i, i, null);
continue; continue;
} }
@ -61,6 +69,7 @@ public class CommandContext {
case '"': case '"':
final StringBuilder build = new StringBuilder(); final StringBuilder build = new StringBuilder();
final char quotedChar = arg.charAt(0); final char quotedChar = arg.charAt(0);
int endIndex; int endIndex;
for (endIndex = i; endIndex < args.length; ++endIndex) { for (endIndex = i; endIndex < args.length; ++endIndex) {
final String arg2 = args[endIndex]; final String arg2 = args[endIndex];
@ -74,50 +83,62 @@ public class CommandContext {
build.append(' ').append(arg2); build.append(' ').append(arg2);
} }
} }
if (endIndex < args.length) args = removePortionOfArray(args, i, endIndex, build.toString());
if (endIndex < args.length) {
arg = build.toString();
i = endIndex;
} }
// else raise exception about hanging quotes?
}
argList.add(arg);
} }
if (valueFlags == null) { List<String> argList2 = new ArrayList<String>(argList.size());
valueFlags = Collections.emptySet(); argList2.add(command);
}
// Then flags // Then flags
for (int i = 1; i < args.length; ++i) { int nextArg = 1;
final String arg = args[i];
if (arg.charAt(0) != '-') { while (nextArg < argList.size()) {
// Fetch argument
String arg = argList.get(nextArg++);
// No more flags?
if (arg.charAt(0) != '-' || arg.length() == 1 || !arg.matches("^-[a-zA-Z]+$")) {
argList2.add(arg);
continue; continue;
} }
// Handle flag parsing terminator --
if (arg.equals("--")) { if (arg.equals("--")) {
args = removePortionOfArray(args, i, i, null); while (nextArg < argList.size()) {
argList2.add(argList.get(nextArg++));
}
break; break;
} }
if (!arg.matches("^-[a-zA-Z]+$")) { // Go through the flags
continue; for (int i = 1; i < arg.length(); ++i) {
} char flagName = arg.charAt(i);
int index = i;
for (int k = 1; k < arg.length(); ++k) {
final char flagName = arg.charAt(k);
if (valueFlags.contains(flagName)) { if (valueFlags.contains(flagName)) {
if (this.valueFlags.containsKey(flagName)) { if (this.valueFlags.containsKey(flagName)) {
throw new CommandException("Value flag '" + flagName + "' already given"); throw new CommandException("Value flag '" + flagName + "' already given");
} }
index++;
if (index >= args.length) {
throw new CommandException("Value flag '" + flagName + "' specified without value");
}
this.valueFlags.put(flagName, args[index]); if (nextArg >= argList.size())
} else { throw new CommandException("No value specified for the '-"+flagName+"' flag.");
// If it is a value flag, read another argument and add it
this.valueFlags.put(flagName, argList.get(nextArg++));
}
else {
booleanFlags.add(flagName); booleanFlags.add(flagName);
} }
} }
args = removePortionOfArray(args, i, index, null);
} }
this.args = args;
this.args = args = argList2.toArray(new String[argList2.size()]);
} }
public String getCommand() { public String getCommand() {

View File

@ -52,9 +52,9 @@ public class CommandContextTest {
String command = firstCommand.getCommand(); String command = firstCommand.getCommand();
String argOne = firstCommand.getString(0); String argOne = firstCommand.getString(0);
String joinedArg = firstCommand.getJoinedStrings(0); String joinedArg = firstCommand.getJoinedStrings(0);
assertEquals(command, "herpderp"); assertEquals("herpderp", command);
assertEquals(argOne, "another thing"); assertEquals("another thing", argOne);
assertEquals(joinedArg, "another thing because something"); assertEquals("another thing because something", joinedArg);
} }
@Test @Test
@ -62,8 +62,8 @@ public class CommandContextTest {
assertTrue(firstCommand.hasFlag('p')); assertTrue(firstCommand.hasFlag('p'));
assertTrue(firstCommand.hasFlag('o')); assertTrue(firstCommand.hasFlag('o'));
assertTrue(firstCommand.hasFlag('w')); assertTrue(firstCommand.hasFlag('w'));
assertEquals(firstCommand.getFlag('o'), "testers"); assertEquals("testers", firstCommand.getFlag('o'));
assertEquals(firstCommand.getFlag('w'), "mani world"); assertEquals("mani world", firstCommand.getFlag('w'));
assertNull(firstCommand.getFlag('u')); assertNull(firstCommand.getFlag('u'));
} }
@ -72,8 +72,8 @@ public class CommandContextTest {
String cmd = "r \"hello goodbye have fun\""; String cmd = "r \"hello goodbye have fun\"";
String cmd2 = "r 'hellogeedby' nnnnnee"; String cmd2 = "r 'hellogeedby' nnnnnee";
try { try {
CommandContext context = new CommandContext(cmd); new CommandContext(cmd);
CommandContext context2 = new CommandContext(cmd2); new CommandContext(cmd2);
} catch (CommandException e) { } catch (CommandException e) {
e.printStackTrace(); e.printStackTrace();
fail("Error creating CommandContext"); fail("Error creating CommandContext");
@ -84,11 +84,35 @@ public class CommandContextTest {
public void testHangingQuote() { public void testHangingQuote() {
String cmd = "r \"hello goodbye have fun"; String cmd = "r \"hello goodbye have fun";
try { try {
CommandContext context = new CommandContext(cmd); new CommandContext(cmd);
} catch (CommandException e) { } catch (CommandException e) {
e.printStackTrace(); e.printStackTrace();
fail("Error creating CommandContext"); fail("Error creating CommandContext");
} }
} }
@Test
public void testMultipleSpaces() {
String cmd = "r hi self";
try {
new CommandContext(cmd);
} catch (CommandException e) {
e.printStackTrace();
fail("Error creating CommandContext");
}
}
@Test
public void testflagsAnywhere() {
try {
CommandContext context = new CommandContext("r hello -f");
assertTrue(context.hasFlag('f'));
CommandContext context2 = new CommandContext("r hello -f world");
assertTrue(context2.hasFlag('f'));
} catch (CommandException e) {
e.printStackTrace();
fail("Error creating CommandContext");
}
}
} }