2011-01-29 10:05:22 +00:00
|
|
|
// $Id$
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2011-02-18 06:53:44 +00:00
|
|
|
package com.sk89q.minecraft.util.commands;
|
2011-01-29 10:05:22 +00:00
|
|
|
|
2011-09-19 21:01:57 +00:00
|
|
|
import java.util.ArrayList;
|
2011-09-14 16:36:10 +00:00
|
|
|
import java.util.Collections;
|
2011-08-26 15:28:37 +00:00
|
|
|
import java.util.HashMap;
|
2011-01-29 19:36:28 +00:00
|
|
|
import java.util.HashSet;
|
2011-09-19 21:01:57 +00:00
|
|
|
import java.util.List;
|
2011-08-26 15:28:37 +00:00
|
|
|
import java.util.Map;
|
2011-01-29 19:36:28 +00:00
|
|
|
import java.util.Set;
|
|
|
|
|
2011-01-29 10:05:22 +00:00
|
|
|
public class CommandContext {
|
2011-09-20 00:35:15 +00:00
|
|
|
protected final String command;
|
|
|
|
protected final List<String> parsedArgs;
|
|
|
|
protected final List<Integer> originalArgIndices;
|
|
|
|
protected final String[] originalArgs;
|
2011-08-26 15:28:37 +00:00
|
|
|
protected final Set<Character> booleanFlags = new HashSet<Character>();
|
|
|
|
protected final Map<Character, String> valueFlags = new HashMap<Character, String>();
|
|
|
|
|
2011-09-14 05:41:19 +00:00
|
|
|
public CommandContext(String args) throws CommandException {
|
|
|
|
this(args.split(" "), null);
|
2011-01-29 10:05:22 +00:00
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
|
2011-09-14 05:41:19 +00:00
|
|
|
public CommandContext(String[] args) throws CommandException {
|
|
|
|
this(args, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
public CommandContext(String args, Set<Character> valueFlags) throws CommandException {
|
|
|
|
this(args.split(" "), valueFlags);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2011-09-14 16:36:10 +00:00
|
|
|
* @param args An array with arguments. Empty strings outside quotes will be removed.
|
2011-09-14 05:41:19 +00:00
|
|
|
* @param valueFlags A set containing all value flags. Pass null to disable value flag parsing.
|
2011-09-14 16:36:10 +00:00
|
|
|
* @throws CommandException This is thrown if flag fails for some reason.
|
2011-09-14 05:41:19 +00:00
|
|
|
*/
|
|
|
|
public CommandContext(String[] args, Set<Character> valueFlags) throws CommandException {
|
2011-09-19 21:01:57 +00:00
|
|
|
if (valueFlags == null) {
|
|
|
|
valueFlags = Collections.emptySet();
|
|
|
|
}
|
|
|
|
|
2011-09-20 00:35:15 +00:00
|
|
|
originalArgs = args;
|
|
|
|
command = args[0];
|
2011-09-19 21:01:57 +00:00
|
|
|
|
2011-09-20 00:35:15 +00:00
|
|
|
// Eliminate empty args and combine multiword args first
|
|
|
|
List<Integer> argIndexList = new ArrayList<Integer>(args.length);
|
2011-09-19 21:01:57 +00:00
|
|
|
List<String> argList = new ArrayList<String>(args.length);
|
2011-09-14 16:36:10 +00:00
|
|
|
for (int i = 1; i < args.length; ++i) {
|
2011-09-19 21:01:57 +00:00
|
|
|
String arg = args[i];
|
2011-12-25 06:04:37 +00:00
|
|
|
if (arg.length() == 0) {
|
2011-09-14 16:36:10 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-09-20 00:35:15 +00:00
|
|
|
argIndexList.add(i);
|
|
|
|
|
2011-09-14 16:36:10 +00:00
|
|
|
switch (arg.charAt(0)) {
|
|
|
|
case '\'':
|
|
|
|
case '"':
|
|
|
|
final StringBuilder build = new StringBuilder();
|
|
|
|
final char quotedChar = arg.charAt(0);
|
2011-09-19 21:01:57 +00:00
|
|
|
|
2011-09-14 16:36:10 +00:00
|
|
|
int endIndex;
|
|
|
|
for (endIndex = i; endIndex < args.length; ++endIndex) {
|
|
|
|
final String arg2 = args[endIndex];
|
|
|
|
if (arg2.charAt(arg2.length() - 1) == quotedChar) {
|
|
|
|
if (endIndex != i) build.append(' ');
|
|
|
|
build.append(arg2.substring(endIndex == i ? 1 : 0, arg2.length() - 1));
|
2011-08-28 19:59:26 +00:00
|
|
|
break;
|
|
|
|
} else if (endIndex == i) {
|
2011-09-14 16:36:10 +00:00
|
|
|
build.append(arg2.substring(1));
|
2011-08-28 19:59:26 +00:00
|
|
|
} else {
|
2011-09-14 16:36:10 +00:00
|
|
|
build.append(' ').append(arg2);
|
2011-08-28 19:59:26 +00:00
|
|
|
}
|
|
|
|
}
|
2011-09-19 21:01:57 +00:00
|
|
|
|
|
|
|
if (endIndex < args.length) {
|
|
|
|
arg = build.toString();
|
|
|
|
i = endIndex;
|
|
|
|
}
|
2011-12-25 06:04:37 +00:00
|
|
|
|
|
|
|
// In case there is an empty quoted string
|
|
|
|
if (arg.length() == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
2011-09-19 21:01:57 +00:00
|
|
|
// else raise exception about hanging quotes?
|
2011-09-14 05:41:19 +00:00
|
|
|
}
|
2011-09-19 21:01:57 +00:00
|
|
|
argList.add(arg);
|
2011-09-14 05:41:19 +00:00
|
|
|
}
|
2011-09-14 16:36:10 +00:00
|
|
|
|
2011-09-14 05:41:19 +00:00
|
|
|
// Then flags
|
2011-09-19 21:01:57 +00:00
|
|
|
|
2011-09-20 00:35:15 +00:00
|
|
|
this.originalArgIndices = new ArrayList<Integer>(argIndexList.size());
|
|
|
|
this.parsedArgs = new ArrayList<String>(argList.size());
|
|
|
|
|
|
|
|
for (int nextArg = 0; nextArg < argList.size(); ) {
|
2011-09-19 21:01:57 +00:00
|
|
|
// Fetch argument
|
|
|
|
String arg = argList.get(nextArg++);
|
2011-09-15 00:58:22 +00:00
|
|
|
|
2011-09-20 00:35:15 +00:00
|
|
|
// Not a flag?
|
2011-09-19 21:01:57 +00:00
|
|
|
if (arg.charAt(0) != '-' || arg.length() == 1 || !arg.matches("^-[a-zA-Z]+$")) {
|
2011-11-23 01:29:48 +00:00
|
|
|
originalArgIndices.add(argIndexList.get(nextArg - 1));
|
2011-09-20 00:35:15 +00:00
|
|
|
parsedArgs.add(arg);
|
2011-09-16 00:16:11 +00:00
|
|
|
continue;
|
|
|
|
}
|
2011-09-14 16:36:10 +00:00
|
|
|
|
2011-09-19 21:01:57 +00:00
|
|
|
// Handle flag parsing terminator --
|
2011-09-14 16:36:10 +00:00
|
|
|
if (arg.equals("--")) {
|
2011-09-19 21:01:57 +00:00
|
|
|
while (nextArg < argList.size()) {
|
2011-09-20 00:35:15 +00:00
|
|
|
originalArgIndices.add(argIndexList.get(nextArg));
|
|
|
|
parsedArgs.add(argList.get(nextArg++));
|
2011-09-19 21:01:57 +00:00
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-09-14 16:36:10 +00:00
|
|
|
|
2011-09-20 00:35:15 +00:00
|
|
|
// Go through the flag characters
|
2011-09-19 21:01:57 +00:00
|
|
|
for (int i = 1; i < arg.length(); ++i) {
|
|
|
|
char flagName = arg.charAt(i);
|
|
|
|
|
2011-09-14 16:36:10 +00:00
|
|
|
if (valueFlags.contains(flagName)) {
|
|
|
|
if (this.valueFlags.containsKey(flagName)) {
|
|
|
|
throw new CommandException("Value flag '" + flagName + "' already given");
|
|
|
|
}
|
|
|
|
|
2011-09-24 19:24:10 +00:00
|
|
|
if (nextArg >= argList.size()) {
|
2011-11-23 01:29:48 +00:00
|
|
|
throw new CommandException("No value specified for the '-" + flagName + "' flag.");
|
2011-09-24 19:24:10 +00:00
|
|
|
}
|
2011-09-19 21:01:57 +00:00
|
|
|
|
|
|
|
// If it is a value flag, read another argument and add it
|
|
|
|
this.valueFlags.put(flagName, argList.get(nextArg++));
|
2011-10-26 20:50:46 +00:00
|
|
|
} else {
|
2011-09-14 16:36:10 +00:00
|
|
|
booleanFlags.add(flagName);
|
|
|
|
}
|
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-29 10:05:22 +00:00
|
|
|
public String getCommand() {
|
2011-09-20 00:35:15 +00:00
|
|
|
return command;
|
2011-01-29 10:05:22 +00:00
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
|
2011-01-29 10:05:22 +00:00
|
|
|
public boolean matches(String command) {
|
2011-10-09 17:31:15 +00:00
|
|
|
return this.command.equalsIgnoreCase(command);
|
2011-01-29 10:05:22 +00:00
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
|
2011-01-29 10:05:22 +00:00
|
|
|
public String getString(int index) {
|
2011-09-20 00:35:15 +00:00
|
|
|
return parsedArgs.get(index);
|
2011-01-29 10:05:22 +00:00
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
|
2011-01-31 06:14:36 +00:00
|
|
|
public String getString(int index, String def) {
|
2011-09-20 00:35:15 +00:00
|
|
|
return index < parsedArgs.size() ? parsedArgs.get(index) : def;
|
2011-01-31 06:14:36 +00:00
|
|
|
}
|
2011-01-29 10:05:22 +00:00
|
|
|
|
|
|
|
public String getJoinedStrings(int initialIndex) {
|
2011-09-20 00:35:15 +00:00
|
|
|
initialIndex = originalArgIndices.get(initialIndex);
|
|
|
|
StringBuilder buffer = new StringBuilder(originalArgs[initialIndex]);
|
|
|
|
for (int i = initialIndex + 1; i < originalArgs.length; ++i) {
|
|
|
|
buffer.append(" ").append(originalArgs[i]);
|
2011-01-29 10:05:22 +00:00
|
|
|
}
|
|
|
|
return buffer.toString();
|
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
|
2011-01-29 10:05:22 +00:00
|
|
|
public int getInteger(int index) throws NumberFormatException {
|
2011-09-20 00:35:15 +00:00
|
|
|
return Integer.parseInt(parsedArgs.get(index));
|
2011-01-29 10:05:22 +00:00
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
|
2011-01-31 06:14:36 +00:00
|
|
|
public int getInteger(int index, int def) throws NumberFormatException {
|
2011-09-20 00:35:15 +00:00
|
|
|
return index < parsedArgs.size() ? Integer.parseInt(parsedArgs.get(index)) : def;
|
2011-01-31 06:14:36 +00:00
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
|
2011-01-29 10:05:22 +00:00
|
|
|
public double getDouble(int index) throws NumberFormatException {
|
2011-09-20 00:35:15 +00:00
|
|
|
return Double.parseDouble(parsedArgs.get(index));
|
2011-01-29 10:05:22 +00:00
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
|
2011-01-31 06:14:36 +00:00
|
|
|
public double getDouble(int index, double def) throws NumberFormatException {
|
2011-09-20 00:35:15 +00:00
|
|
|
return index < parsedArgs.size() ? Double.parseDouble(parsedArgs.get(index)) : def;
|
2011-01-31 06:14:36 +00:00
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
|
2011-01-29 10:05:22 +00:00
|
|
|
public String[] getSlice(int index) {
|
2011-09-20 00:35:15 +00:00
|
|
|
String[] slice = new String[originalArgs.length - index];
|
|
|
|
System.arraycopy(originalArgs, index, slice, 0, originalArgs.length - index);
|
2011-01-29 10:05:22 +00:00
|
|
|
return slice;
|
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
|
2011-01-29 10:05:22 +00:00
|
|
|
public String[] getPaddedSlice(int index, int padding) {
|
2011-09-20 00:35:15 +00:00
|
|
|
String[] slice = new String[originalArgs.length - index + padding];
|
|
|
|
System.arraycopy(originalArgs, index, slice, padding, originalArgs.length - index);
|
2011-01-29 10:05:22 +00:00
|
|
|
return slice;
|
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
|
2011-01-29 19:36:28 +00:00
|
|
|
public boolean hasFlag(char ch) {
|
2011-08-26 15:28:37 +00:00
|
|
|
return booleanFlags.contains(ch) || valueFlags.containsKey(ch);
|
2011-01-29 19:36:28 +00:00
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
|
2011-01-29 19:36:28 +00:00
|
|
|
public Set<Character> getFlags() {
|
2011-08-26 15:28:37 +00:00
|
|
|
return booleanFlags;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Map<Character, String> getValueFlags() {
|
|
|
|
return valueFlags;
|
2011-01-29 19:36:28 +00:00
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
|
|
|
|
public String getFlag(char ch) {
|
|
|
|
return valueFlags.get(ch);
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getFlag(char ch, String def) {
|
|
|
|
final String value = valueFlags.get(ch);
|
2011-09-24 19:24:10 +00:00
|
|
|
if (value == null) {
|
2011-08-26 15:28:37 +00:00
|
|
|
return def;
|
2011-09-24 19:24:10 +00:00
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getFlagInteger(char ch) throws NumberFormatException {
|
|
|
|
return Integer.parseInt(valueFlags.get(ch));
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getFlagInteger(char ch, int def) throws NumberFormatException {
|
|
|
|
final String value = valueFlags.get(ch);
|
2011-09-24 19:24:10 +00:00
|
|
|
if (value == null) {
|
2011-08-26 15:28:37 +00:00
|
|
|
return def;
|
2011-09-24 19:24:10 +00:00
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
|
|
|
|
return Integer.parseInt(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
public double getFlagDouble(char ch) throws NumberFormatException {
|
|
|
|
return Double.parseDouble(valueFlags.get(ch));
|
|
|
|
}
|
|
|
|
|
|
|
|
public double getFlagDouble(char ch, double def) throws NumberFormatException {
|
|
|
|
final String value = valueFlags.get(ch);
|
2011-09-24 19:24:10 +00:00
|
|
|
if (value == null) {
|
2011-08-26 15:28:37 +00:00
|
|
|
return def;
|
2011-09-24 19:24:10 +00:00
|
|
|
}
|
2011-08-26 15:28:37 +00:00
|
|
|
|
|
|
|
return Double.parseDouble(value);
|
|
|
|
}
|
|
|
|
|
2011-01-29 10:05:22 +00:00
|
|
|
public int argsLength() {
|
2011-09-20 00:35:15 +00:00
|
|
|
return parsedArgs.size();
|
2011-01-29 10:05:22 +00:00
|
|
|
}
|
|
|
|
}
|