diff --git a/src/main/java/com/sk89q/minecraft/util/commands/CommandContext.java b/src/main/java/com/sk89q/minecraft/util/commands/CommandContext.java index 0f2463652..f5e891e7a 100644 --- a/src/main/java/com/sk89q/minecraft/util/commands/CommandContext.java +++ b/src/main/java/com/sk89q/minecraft/util/commands/CommandContext.java @@ -18,12 +18,13 @@ package com.sk89q.minecraft.util.commands; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; -import static com.sk89q.util.ArrayUtil.removePortionOfArray; public class CommandContext { protected final String[] args; @@ -48,11 +49,18 @@ public class CommandContext { * @throws CommandException This is thrown if flag fails for some reason. */ public CommandContext(String[] args, Set valueFlags) throws CommandException { + if (valueFlags == null) { + valueFlags = Collections.emptySet(); + } + + final String command = args[0]; + + List argList = new ArrayList(args.length); + argList.add(command); // Go through empty args and multiword args first for (int i = 1; i < args.length; ++i) { - final String arg = args[i]; + String arg = args[i]; if (arg.isEmpty()) { - args = removePortionOfArray(args, i, i, null); continue; } @@ -61,6 +69,7 @@ public class CommandContext { case '"': final StringBuilder build = new StringBuilder(); final char quotedChar = arg.charAt(0); + int endIndex; for (endIndex = i; endIndex < args.length; ++endIndex) { final String arg2 = args[endIndex]; @@ -74,50 +83,62 @@ public class CommandContext { 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) { - valueFlags = Collections.emptySet(); - } + List argList2 = new ArrayList(argList.size()); + argList2.add(command); // Then flags - for (int i = 1; i < args.length; ++i) { - final String arg = args[i]; + int nextArg = 1; - 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; } + // Handle flag parsing terminator -- if (arg.equals("--")) { - args = removePortionOfArray(args, i, i, null); + while (nextArg < argList.size()) { + argList2.add(argList.get(nextArg++)); + } break; } - if (!arg.matches("^-[a-zA-Z]+$")) { - continue; - } - int index = i; - for (int k = 1; k < arg.length(); ++k) { - final char flagName = arg.charAt(k); + // Go through the flags + for (int i = 1; i < arg.length(); ++i) { + char flagName = arg.charAt(i); + if (valueFlags.contains(flagName)) { if (this.valueFlags.containsKey(flagName)) { 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]); - } else { + if (nextArg >= argList.size()) + 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); } } - args = removePortionOfArray(args, i, index, null); } - this.args = args; + + this.args = args = argList2.toArray(new String[argList2.size()]); } public String getCommand() { diff --git a/src/test/java/com/sk89q/minecraft/util/commands/CommandContextTest.java b/src/test/java/com/sk89q/minecraft/util/commands/CommandContextTest.java index e20e34126..057e96dff 100644 --- a/src/test/java/com/sk89q/minecraft/util/commands/CommandContextTest.java +++ b/src/test/java/com/sk89q/minecraft/util/commands/CommandContextTest.java @@ -52,9 +52,9 @@ public class CommandContextTest { String command = firstCommand.getCommand(); String argOne = firstCommand.getString(0); String joinedArg = firstCommand.getJoinedStrings(0); - assertEquals(command, "herpderp"); - assertEquals(argOne, "another thing"); - assertEquals(joinedArg, "another thing because something"); + assertEquals("herpderp", command); + assertEquals("another thing", argOne); + assertEquals("another thing because something", joinedArg); } @Test @@ -62,8 +62,8 @@ public class CommandContextTest { assertTrue(firstCommand.hasFlag('p')); assertTrue(firstCommand.hasFlag('o')); assertTrue(firstCommand.hasFlag('w')); - assertEquals(firstCommand.getFlag('o'), "testers"); - assertEquals(firstCommand.getFlag('w'), "mani world"); + assertEquals("testers", firstCommand.getFlag('o')); + assertEquals("mani world", firstCommand.getFlag('w')); assertNull(firstCommand.getFlag('u')); } @@ -72,8 +72,8 @@ public class CommandContextTest { String cmd = "r \"hello goodbye have fun\""; String cmd2 = "r 'hellogeedby' nnnnnee"; try { - CommandContext context = new CommandContext(cmd); - CommandContext context2 = new CommandContext(cmd2); + new CommandContext(cmd); + new CommandContext(cmd2); } catch (CommandException e) { e.printStackTrace(); fail("Error creating CommandContext"); @@ -84,11 +84,35 @@ public class CommandContextTest { public void testHangingQuote() { String cmd = "r \"hello goodbye have fun"; try { - CommandContext context = new CommandContext(cmd); + new CommandContext(cmd); } catch (CommandException e) { e.printStackTrace(); 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"); + } + } }