mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-07-01 02:46:41 +00:00
Added a new command dispatcher that injects different parameters dynamically.
This reduces the boilerplate code needed to parse arguments in each command, and reduces the need to maintain command documentation with @Command. Example: @Command(aliases = "/set", desc = "Set all the blocks inside the selection to a block") @CommandPermissions("worldedit.region.set") @Logging(REGION) void setBlocks(LocalPlayer player, EditSession editSession, @Selection Region region, Pattern replaceWith) { // Perform command }
This commit is contained in:
@ -27,15 +27,22 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class CommandContext {
|
||||
|
||||
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 Map<Character, String> valueFlags = new HashMap<Character, String>();
|
||||
protected final SuggestionContext suggestionContext;
|
||||
protected final CommandLocals locals;
|
||||
|
||||
public static String[] split(String args) {
|
||||
return args.split(" ", -1);
|
||||
}
|
||||
|
||||
public CommandContext(String args) throws CommandException {
|
||||
this(args.split(" "), null);
|
||||
this(args.split(" ", -1), null);
|
||||
}
|
||||
|
||||
public CommandContext(String[] args) throws CommandException {
|
||||
@ -43,28 +50,50 @@ public class CommandContext {
|
||||
}
|
||||
|
||||
public CommandContext(String args, Set<Character> valueFlags) throws CommandException {
|
||||
this(args.split(" "), valueFlags);
|
||||
this(args.split(" ", -1), valueFlags);
|
||||
}
|
||||
|
||||
public CommandContext(String args, Set<Character> valueFlags, boolean allowHangingFlag)
|
||||
throws CommandException {
|
||||
this(args.split(" ", -1), valueFlags, allowHangingFlag, new CommandLocals());
|
||||
}
|
||||
|
||||
public CommandContext(String[] args, Set<Character> valueFlags) throws CommandException {
|
||||
this(args, valueFlags, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param args An array with arguments. Empty strings outside quotes will be removed.
|
||||
* @param valueFlags A set containing all value flags. Pass null to disable value flag parsing.
|
||||
* @throws CommandException This is thrown if flag fails for some reason.
|
||||
* Parse the given array of arguments.
|
||||
*
|
||||
* <p>Empty arguments are removed from the list of arguments.</p>
|
||||
*
|
||||
* @param args an array with arguments
|
||||
* @param valueFlags a set containing all value flags (pass null to disable value flag parsing)
|
||||
* @param allowHangingFlag true if hanging flags are allowed
|
||||
* @param locals the locals, null to create empty one
|
||||
* @throws CommandException thrown on a parsing error
|
||||
*/
|
||||
public CommandContext(String[] args, Set<Character> valueFlags) throws CommandException {
|
||||
public CommandContext(String[] args, Set<Character> valueFlags,
|
||||
boolean allowHangingFlag, CommandLocals locals) throws CommandException {
|
||||
if (valueFlags == null) {
|
||||
valueFlags = Collections.emptySet();
|
||||
}
|
||||
|
||||
originalArgs = args;
|
||||
command = args[0];
|
||||
this.locals = locals != null ? locals : new CommandLocals();
|
||||
boolean isHanging = false;
|
||||
SuggestionContext suggestionContext = SuggestionContext.hangingValue();
|
||||
|
||||
// Eliminate empty args and combine multiword args first
|
||||
List<Integer> argIndexList = new ArrayList<Integer>(args.length);
|
||||
List<String> argList = new ArrayList<String>(args.length);
|
||||
for (int i = 1; i < args.length; ++i) {
|
||||
isHanging = false;
|
||||
|
||||
String arg = args[i];
|
||||
if (arg.length() == 0) {
|
||||
isHanging = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -112,9 +141,14 @@ public class CommandContext {
|
||||
for (int nextArg = 0; nextArg < argList.size(); ) {
|
||||
// Fetch argument
|
||||
String arg = argList.get(nextArg++);
|
||||
suggestionContext = SuggestionContext.hangingValue();
|
||||
|
||||
// Not a flag?
|
||||
if (arg.charAt(0) != '-' || arg.length() == 1 || !arg.matches("^-[a-zA-Z]+$")) {
|
||||
if (!isHanging) {
|
||||
suggestionContext = SuggestionContext.lastValue();
|
||||
}
|
||||
|
||||
originalArgIndices.add(argIndexList.get(nextArg - 1));
|
||||
parsedArgs.add(arg);
|
||||
continue;
|
||||
@ -139,16 +173,30 @@ public class CommandContext {
|
||||
}
|
||||
|
||||
if (nextArg >= argList.size()) {
|
||||
throw new CommandException("No value specified for the '-" + flagName + "' flag.");
|
||||
if (allowHangingFlag) {
|
||||
suggestionContext = SuggestionContext.flag(flagName);
|
||||
break;
|
||||
} 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++));
|
||||
if (!isHanging) {
|
||||
suggestionContext = SuggestionContext.flag(flagName);
|
||||
}
|
||||
} else {
|
||||
booleanFlags.add(flagName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.suggestionContext = suggestionContext;
|
||||
}
|
||||
|
||||
public SuggestionContext getSuggestionContext() {
|
||||
return suggestionContext;
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
@ -175,6 +223,18 @@ public class CommandContext {
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public String getRemainingString(int start) {
|
||||
return getString(start, parsedArgs.size() - 1);
|
||||
}
|
||||
|
||||
public String getString(int start, int end) {
|
||||
StringBuilder buffer = new StringBuilder(parsedArgs.get(start));
|
||||
for (int i = start + 1; i < end + 1; ++i) {
|
||||
buffer.append(" ").append(parsedArgs.get(i));
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public int getInteger(int index) throws NumberFormatException {
|
||||
return Integer.parseInt(parsedArgs.get(index));
|
||||
@ -258,4 +318,8 @@ public class CommandContext {
|
||||
public int argsLength() {
|
||||
return parsedArgs.size();
|
||||
}
|
||||
|
||||
public CommandLocals getLocals() {
|
||||
return locals;
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,14 @@
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
public class CommandException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 870638193072101739L;
|
||||
private List<String> commandStack = new ArrayList<String>();
|
||||
|
||||
public CommandException() {
|
||||
super();
|
||||
@ -30,8 +36,37 @@ public class CommandException extends Exception {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CommandException(String message, Throwable t) {
|
||||
super(message, t);
|
||||
}
|
||||
|
||||
public CommandException(Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
public void prependStack(String name) {
|
||||
commandStack.add(name);
|
||||
}
|
||||
|
||||
public String toStackString(String prefix, String spacedSuffix) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (prefix != null) {
|
||||
builder.append(prefix);
|
||||
}
|
||||
ListIterator<String> li = commandStack.listIterator(commandStack.size());
|
||||
while (li.hasPrevious()) {
|
||||
if (li.previousIndex() != commandStack.size() - 1) {
|
||||
builder.append(" ");
|
||||
}
|
||||
builder.append(li.previous());
|
||||
}
|
||||
if (spacedSuffix != null) {
|
||||
if (builder.length() > 0) {
|
||||
builder.append(" ");
|
||||
}
|
||||
builder.append(spacedSuffix);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
// $Id$
|
||||
/*
|
||||
* This file is a part of WorldEdit.
|
||||
* Copyright (c) sk89q <http://www.sk89q.com>
|
||||
* Copyright (c) the WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* (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
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class CommandLocals {
|
||||
|
||||
private final Map<Object, Object> locals = new HashMap<Object, Object>();
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
return locals.containsKey(key);
|
||||
}
|
||||
|
||||
public boolean containsValue(Object value) {
|
||||
return locals.containsValue(value);
|
||||
}
|
||||
|
||||
public Object get(Object key) {
|
||||
return locals.get(key);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T get(Class<T> key) {
|
||||
return (T) locals.get(key);
|
||||
}
|
||||
|
||||
public Object put(Object key, Object value) {
|
||||
return locals.put(key, value);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
|
||||
public class SuggestionContext {
|
||||
|
||||
private static final SuggestionContext FOR_LAST = new SuggestionContext(null, true);
|
||||
private static final SuggestionContext FOR_HANGING = new SuggestionContext(null, false);
|
||||
|
||||
private final Character flag;
|
||||
private final boolean forLast;
|
||||
|
||||
private SuggestionContext(Character flag, boolean forLast) {
|
||||
this.flag = flag;
|
||||
this.forLast = forLast;
|
||||
}
|
||||
|
||||
public boolean forHangingValue() {
|
||||
return flag == null && !forLast;
|
||||
}
|
||||
|
||||
public boolean forLastValue() {
|
||||
return flag == null && forLast;
|
||||
}
|
||||
|
||||
public boolean forFlag() {
|
||||
return flag != null;
|
||||
}
|
||||
|
||||
public Character getFlag() {
|
||||
return flag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return forFlag() ? ("-" + getFlag()) : (forHangingValue() ? "hanging" : "last");
|
||||
}
|
||||
|
||||
public static SuggestionContext flag(Character flag) {
|
||||
return new SuggestionContext(flag, false);
|
||||
}
|
||||
|
||||
public static SuggestionContext lastValue() {
|
||||
return FOR_LAST;
|
||||
}
|
||||
|
||||
public static SuggestionContext hangingValue() {
|
||||
return FOR_HANGING;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user