Added simple usage generation

This commit is contained in:
Nathan Adams
2014-10-09 12:15:54 +02:00
parent b3703db535
commit 91559191b6
12 changed files with 340 additions and 5 deletions
@@ -1,14 +1,31 @@
package com.mojang.brigadier;
import com.google.common.base.Predicate;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.exceptions.CommandException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode;
import com.mojang.brigadier.tree.RootCommandNode;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class CommandDispatcher<T> {
private static final Predicate<CommandNode> HAS_COMMAND = new Predicate<CommandNode>() {
@Override
public boolean apply(@Nullable CommandNode input) {
return input != null && (input.getCommand() != null || Iterables.any(input.getChildren(), HAS_COMMAND));
}
};
public static final SimpleCommandExceptionType ERROR_UNKNOWN_COMMAND = new SimpleCommandExceptionType("unknown_command", "Unknown command");
public static final String ARGUMENT_SEPARATOR = " ";
@@ -39,13 +56,57 @@ public class CommandDispatcher<T> {
}
}
if (exception != null) {
throw exception;
}
if (command.length() > 0) {
if (exception != null) {
throw exception;
}
throw ERROR_UNKNOWN_COMMAND.create();
}
return contextBuilder.build();
}
public String getUsage(String command, T source) throws CommandException {
CommandContext<T> context = parseNodes(root, command, new CommandContextBuilder<T>(source));
CommandNode base = Iterables.getLast(context.getNodes().keySet());
List<CommandNode> children = Lists.newArrayList(Iterables.filter(base.getChildren(), HAS_COMMAND));
boolean optional = base.getCommand() != null;
if (children.isEmpty()) {
return context.getInput();
}
Collections.sort(children, new Comparator<CommandNode>() {
@Override
public int compare(CommandNode o1, CommandNode o2) {
return ComparisonChain.start()
.compareTrueFirst(o1 instanceof LiteralCommandNode, o2 instanceof LiteralCommandNode)
.result();
}
});
StringBuilder result = new StringBuilder(context.getInput());
result.append(ARGUMENT_SEPARATOR);
if (optional) {
result.append("[");
} else if (children.size() > 1) {
result.append("(");
}
for (int i = 0; i < children.size(); i++) {
result.append(children.get(i).getUsageText());
if (i < children.size() - 1) {
result.append("|");
}
}
if (optional) {
result.append("]");
} else if (children.size() > 1) {
result.append(")");
}
return result.toString();
}
}
@@ -1,19 +1,27 @@
package com.mojang.brigadier.context;
import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
import com.google.common.primitives.Primitives;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.tree.CommandNode;
import java.util.Map;
public class CommandContext<T> {
private final Joiner JOINER = Joiner.on(CommandDispatcher.ARGUMENT_SEPARATOR);
private final T source;
private final Map<String, ParsedArgument<?>> arguments;
private final Command command;
private final Map<CommandNode, String> nodes;
public CommandContext(T source, Map<String, ParsedArgument<?>> arguments, Command command) {
public CommandContext(T source, Map<String, ParsedArgument<?>> arguments, Command command, Map<CommandNode, String> nodes) {
this.source = source;
this.arguments = arguments;
this.command = command;
this.nodes = nodes;
}
public Command getCommand() {
@@ -47,6 +55,7 @@ public class CommandContext<T> {
CommandContext that = (CommandContext) o;
if (!arguments.equals(that.arguments)) return false;
if (!Iterables.elementsEqual(nodes.entrySet(), that.nodes.entrySet())) return false;
if (command != null ? !command.equals(that.command) : that.command != null) return false;
if (!source.equals(that.source)) return false;
@@ -58,6 +67,15 @@ public class CommandContext<T> {
int result = source.hashCode();
result = 31 * result + arguments.hashCode();
result = 31 * result + (command != null ? command.hashCode() : 0);
result = 31 * result + nodes.hashCode();
return result;
}
public String getInput() {
return JOINER.join(nodes.values());
}
public Map<CommandNode, String> getNodes() {
return nodes;
}
}
@@ -2,11 +2,13 @@ package com.mojang.brigadier.context;
import com.google.common.collect.Maps;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.tree.CommandNode;
import java.util.Map;
public class CommandContextBuilder<T> {
private final Map<String, ParsedArgument<?>> arguments = Maps.newHashMap();
private final Map<CommandNode, String> nodes = Maps.newLinkedHashMap();
private final T source;
private Command command;
@@ -28,14 +30,20 @@ public class CommandContextBuilder<T> {
return this;
}
public CommandContextBuilder<T> withNode(CommandNode node, String raw) {
this.nodes.put(node, raw);
return this;
}
public CommandContextBuilder<T> copy() {
CommandContextBuilder<T> copy = new CommandContextBuilder<T>(source);
copy.command = this.command;
copy.arguments.putAll(this.arguments);
copy.nodes.putAll(this.nodes);
return copy;
}
public CommandContext<T> build() {
return new CommandContext<T>(source, arguments, command);
return new CommandContext<T>(source, arguments, command, nodes);
}
}
@@ -29,12 +29,18 @@ public class ArgumentCommandNode<T> extends CommandNode {
return name;
}
@Override
public String getUsageText() {
return "<" + name + ">";
}
@Override
public String parse(String command, CommandContextBuilder<?> contextBuilder) throws CommandException {
ParsedArgument<T> parsed = type.parse(command);
int start = parsed.getRaw().length();
contextBuilder.withArgument(name, parsed);
contextBuilder.withNode(this, parsed.getRaw());
if (command.length() > start) {
return command.substring(start + 1);
@@ -59,5 +59,7 @@ public abstract class CommandNode {
protected abstract Object getMergeKey();
public abstract String getUsageText();
public abstract String parse(String command, CommandContextBuilder<?> contextBuilder) throws CommandException;
}
@@ -33,6 +33,7 @@ public class LiteralCommandNode extends CommandNode {
throw ERROR_INCORRECT_LITERAL.create(literal);
}
contextBuilder.withNode(this, literal);
int start = expected.length();
return command.substring(start);
}
@@ -48,6 +49,11 @@ public class LiteralCommandNode extends CommandNode {
return super.equals(o);
}
@Override
public String getUsageText() {
return literal;
}
@Override
public int hashCode() {
int result = literal.hashCode();
@@ -13,6 +13,11 @@ public class RootCommandNode extends CommandNode {
throw new UnsupportedOperationException("Cannot add a RootCommandNode as a child to any other CommandNode");
}
@Override
public String getUsageText() {
return "";
}
@Override
public String parse(String command, CommandContextBuilder<?> contextBuilder) throws CommandException {
return command;