Internal restructuring of CommandContext

- getJoinedStrings(n) will now return literally everything after the first space following the (n-1)th argument. Mixing flags in after that is undefined
- What was in args before is now a List named parsedArgs, which also no longer contains the command, which was split off into a separate field.
- get[Padded]Slice now operates on the unparsed args with flags and all, allowing whoever uses it (script commands) to obtain a more low-level input.
- Added a test for the exactness of getJoinedStrings and adjusted an existing test to the new old behaviour.
This commit is contained in:
TomyLobo 2011-09-20 02:35:15 +02:00
parent 2d86b1b40d
commit 67918f171b
2 changed files with 56 additions and 35 deletions

View File

@ -27,7 +27,10 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
public class CommandContext { public class CommandContext {
protected final String[] args; protected final String command;
protected final List<String> parsedArgs;
protected final List<Integer> originalArgIndices;
protected final String[] originalArgs;
protected final Set<Character> booleanFlags = new HashSet<Character>(); protected final Set<Character> booleanFlags = new HashSet<Character>();
protected final Map<Character, String> valueFlags = new HashMap<Character, String>(); protected final Map<Character, String> valueFlags = new HashMap<Character, String>();
@ -53,17 +56,20 @@ public class CommandContext {
valueFlags = Collections.emptySet(); valueFlags = Collections.emptySet();
} }
final String command = args[0]; originalArgs = args;
command = args[0];
// Eliminate empty args and combine multiword args first
List<Integer> argIndexList = new ArrayList<Integer>(args.length);
List<String> argList = new ArrayList<String>(args.length); List<String> argList = new ArrayList<String>(args.length);
argList.add(command);
// Go through empty args and multiword args first
for (int i = 1; i < args.length; ++i) { for (int i = 1; i < args.length; ++i) {
String arg = args[i]; String arg = args[i];
if (arg.isEmpty()) { if (arg.isEmpty()) {
continue; continue;
} }
argIndexList.add(i);
switch (arg.charAt(0)) { switch (arg.charAt(0)) {
case '\'': case '\'':
case '"': case '"':
@ -93,31 +99,32 @@ public class CommandContext {
argList.add(arg); argList.add(arg);
} }
List<String> argList2 = new ArrayList<String>(argList.size());
argList2.add(command);
// Then flags // Then flags
int nextArg = 1;
while (nextArg < argList.size()) { this.originalArgIndices = new ArrayList<Integer>(argIndexList.size());
this.parsedArgs = new ArrayList<String>(argList.size());
for (int nextArg = 0; nextArg < argList.size(); ) {
// Fetch argument // Fetch argument
String arg = argList.get(nextArg++); String arg = argList.get(nextArg++);
// No more flags? // Not a flag?
if (arg.charAt(0) != '-' || arg.length() == 1 || !arg.matches("^-[a-zA-Z]+$")) { if (arg.charAt(0) != '-' || arg.length() == 1 || !arg.matches("^-[a-zA-Z]+$")) {
argList2.add(arg); originalArgIndices.add(argIndexList.get(nextArg-1));
parsedArgs.add(arg);
continue; continue;
} }
// Handle flag parsing terminator -- // Handle flag parsing terminator --
if (arg.equals("--")) { if (arg.equals("--")) {
while (nextArg < argList.size()) { while (nextArg < argList.size()) {
argList2.add(argList.get(nextArg++)); originalArgIndices.add(argIndexList.get(nextArg));
parsedArgs.add(argList.get(nextArg++));
} }
break; break;
} }
// Go through the flags // Go through the flag characters
for (int i = 1; i < arg.length(); ++i) { for (int i = 1; i < arg.length(); ++i) {
char flagName = arg.charAt(i); char flagName = arg.charAt(i);
@ -137,60 +144,58 @@ public class CommandContext {
} }
} }
} }
this.args = args = argList2.toArray(new String[argList2.size()]);
} }
public String getCommand() { public String getCommand() {
return args[0]; return command;
} }
public boolean matches(String command) { public boolean matches(String command) {
return args[0].equalsIgnoreCase(command); return command.equalsIgnoreCase(command);
} }
public String getString(int index) { public String getString(int index) {
return args[index + 1]; return parsedArgs.get(index);
} }
public String getString(int index, String def) { public String getString(int index, String def) {
return index + 1 < args.length ? args[index + 1] : def; return index < parsedArgs.size() ? parsedArgs.get(index) : def;
} }
public String getJoinedStrings(int initialIndex) { public String getJoinedStrings(int initialIndex) {
initialIndex = initialIndex + 1; initialIndex = originalArgIndices.get(initialIndex);
StringBuilder buffer = new StringBuilder(args[initialIndex]); StringBuilder buffer = new StringBuilder(originalArgs[initialIndex]);
for (int i = initialIndex + 1; i < args.length; ++i) { for (int i = initialIndex + 1; i < originalArgs.length; ++i) {
buffer.append(" ").append(args[i]); buffer.append(" ").append(originalArgs[i]);
} }
return buffer.toString(); return buffer.toString();
} }
public int getInteger(int index) throws NumberFormatException { public int getInteger(int index) throws NumberFormatException {
return Integer.parseInt(args[index + 1]); return Integer.parseInt(parsedArgs.get(index));
} }
public int getInteger(int index, int def) throws NumberFormatException { public int getInteger(int index, int def) throws NumberFormatException {
return index + 1 < args.length ? Integer.parseInt(args[index + 1]) : def; return index < parsedArgs.size() ? Integer.parseInt(parsedArgs.get(index)) : def;
} }
public double getDouble(int index) throws NumberFormatException { public double getDouble(int index) throws NumberFormatException {
return Double.parseDouble(args[index + 1]); return Double.parseDouble(parsedArgs.get(index));
} }
public double getDouble(int index, double def) throws NumberFormatException { public double getDouble(int index, double def) throws NumberFormatException {
return index + 1 < args.length ? Double.parseDouble(args[index + 1]) : def; return index < parsedArgs.size() ? Double.parseDouble(parsedArgs.get(index)) : def;
} }
public String[] getSlice(int index) { public String[] getSlice(int index) {
String[] slice = new String[args.length - index]; String[] slice = new String[originalArgs.length - index];
System.arraycopy(args, index, slice, 0, args.length - index); System.arraycopy(originalArgs, index, slice, 0, originalArgs.length - index);
return slice; return slice;
} }
public String[] getPaddedSlice(int index, int padding) { public String[] getPaddedSlice(int index, int padding) {
String[] slice = new String[args.length - index + padding]; String[] slice = new String[originalArgs.length - index + padding];
System.arraycopy(args, index, slice, padding, args.length - index); System.arraycopy(originalArgs, index, slice, padding, originalArgs.length - index);
return slice; return slice;
} }
@ -243,6 +248,6 @@ public class CommandContext {
} }
public int argsLength() { public int argsLength() {
return args.length - 1; return parsedArgs.size();
} }
} }

View File

@ -54,7 +54,7 @@ public class CommandContextTest {
String joinedArg = firstCommand.getJoinedStrings(0); String joinedArg = firstCommand.getJoinedStrings(0);
assertEquals("herpderp", command); assertEquals("herpderp", command);
assertEquals("another thing", argOne); assertEquals("another thing", argOne);
assertEquals("another thing because something", joinedArg); assertEquals("'another thing' because something", joinedArg);
} }
@Test @Test
@ -64,7 +64,7 @@ public class CommandContextTest {
assertTrue(firstCommand.hasFlag('w')); assertTrue(firstCommand.hasFlag('w'));
assertEquals("testers", firstCommand.getFlag('o')); assertEquals("testers", firstCommand.getFlag('o'));
assertEquals("mani world", firstCommand.getFlag('w')); assertEquals("mani world", firstCommand.getFlag('w'));
assertNull(firstCommand.getFlag('u')); assertFalse(firstCommand.hasFlag('u'));
} }
@Test @Test
@ -103,7 +103,7 @@ public class CommandContextTest {
} }
@Test @Test
public void testflagsAnywhere() { public void testFlagsAnywhere() {
try { try {
CommandContext context = new CommandContext("r hello -f"); CommandContext context = new CommandContext("r hello -f");
assertTrue(context.hasFlag('f')); assertTrue(context.hasFlag('f'));
@ -115,4 +115,20 @@ public class CommandContextTest {
fail("Error creating CommandContext"); fail("Error creating CommandContext");
} }
} }
@Test
public void testExactJoinedStrings() {
try {
CommandContext context = new CommandContext("r -f \"hello world\" foo bar");
assertTrue(context.hasFlag('f'));
assertEquals("\"hello world\" foo bar", context.getJoinedStrings(0));
assertEquals("foo bar", context.getJoinedStrings(1));
CommandContext context2 = new CommandContext("pm name \"hello world\" foo bar");
assertEquals("\"hello world\" foo bar", context2.getJoinedStrings(1));
} catch (CommandException e) {
e.printStackTrace();
fail("Error creating CommandContext");
}
}
} }