Added support for suggestions tabcompletions of a command input
This commit is contained in:
@@ -2,6 +2,7 @@ package com.mojang.brigadier;
|
||||
|
||||
import com.google.common.collect.ComparisonChain;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.context.CommandContextBuilder;
|
||||
@@ -12,6 +13,7 @@ import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
import com.mojang.brigadier.tree.RootCommandNode;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -23,7 +25,7 @@ public class CommandDispatcher<T> {
|
||||
}
|
||||
};
|
||||
|
||||
public static final SimpleCommandExceptionType ERROR_UNKNOWN_COMMAND = new SimpleCommandExceptionType("unknown_command", "Unknown command");
|
||||
public static final SimpleCommandExceptionType ERROR_UNKNOWN_COMMAND = new SimpleCommandExceptionType("command.unknown", "Unknown command");
|
||||
public static final String ARGUMENT_SEPARATOR = " ";
|
||||
private static final String USAGE_OPTIONAL_OPEN = "[";
|
||||
private static final String USAGE_OPTIONAL_CLOSE = "]";
|
||||
@@ -52,7 +54,11 @@ public class CommandDispatcher<T> {
|
||||
if (child.getCommand() != null) {
|
||||
context.withCommand(child.getCommand());
|
||||
}
|
||||
return parseNodes(child, remaining, context);
|
||||
if (remaining.isEmpty()) {
|
||||
return context.build();
|
||||
} else {
|
||||
return parseNodes(child, remaining.substring(1), context);
|
||||
}
|
||||
} catch (CommandException ex) {
|
||||
exception = ex;
|
||||
}
|
||||
@@ -106,4 +112,28 @@ public class CommandDispatcher<T> {
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private Set<String> findSuggestions(CommandNode node, String command, CommandContextBuilder<T> contextBuilder, Set<String> result) {
|
||||
for (CommandNode child : node.getChildren()) {
|
||||
try {
|
||||
CommandContextBuilder<T> context = contextBuilder.copy();
|
||||
String remaining = child.parse(command, context);
|
||||
if (remaining.isEmpty()) {
|
||||
child.listSuggestions(command, result);
|
||||
} else {
|
||||
return findSuggestions(child, remaining.substring(1), context, result);
|
||||
}
|
||||
} catch (CommandException e) {
|
||||
child.listSuggestions(command, result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public String[] getCompletionSuggestions(String command, T source) {
|
||||
final Set<String> nodes = findSuggestions(root, command, new CommandContextBuilder<>(source), Sets.newLinkedHashSet());
|
||||
|
||||
return nodes.toArray(new String[nodes.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,10 @@ package com.mojang.brigadier.arguments;
|
||||
import com.mojang.brigadier.context.ParsedArgument;
|
||||
import com.mojang.brigadier.exceptions.CommandException;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface CommandArgumentType<T> {
|
||||
ParsedArgument<T> parse(String command) throws CommandException;
|
||||
|
||||
void listSuggestions(String command, Set<String> output);
|
||||
}
|
||||
|
||||
@@ -7,10 +7,12 @@ import com.mojang.brigadier.context.ParsedArgument;
|
||||
import com.mojang.brigadier.exceptions.CommandException;
|
||||
import com.mojang.brigadier.exceptions.ParameterizedCommandExceptionType;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class IntegerArgumentType implements CommandArgumentType<Integer> {
|
||||
public static final ParameterizedCommandExceptionType ERROR_NOT_A_NUMBER = new ParameterizedCommandExceptionType("argument-integer-invalid", "Expected an integer, found '${found}'", "found");
|
||||
public static final ParameterizedCommandExceptionType ERROR_TOO_SMALL = new ParameterizedCommandExceptionType("argument-integer-low", "Integer must not be less than ${minimum}, found ${found}", "found", "minimum");
|
||||
public static final ParameterizedCommandExceptionType ERROR_TOO_BIG = new ParameterizedCommandExceptionType("argument-integer-big", "Integer must not be more than ${maximum}, found ${found}", "found", "maximum");
|
||||
public static final ParameterizedCommandExceptionType ERROR_NOT_A_NUMBER = new ParameterizedCommandExceptionType("argument.integer.invalid", "Expected an integer, found '${found}'", "found");
|
||||
public static final ParameterizedCommandExceptionType ERROR_TOO_SMALL = new ParameterizedCommandExceptionType("argument.integer.low", "Integer must not be less than ${minimum}, found ${found}", "found", "minimum");
|
||||
public static final ParameterizedCommandExceptionType ERROR_TOO_BIG = new ParameterizedCommandExceptionType("argument.integer.big", "Integer must not be more than ${maximum}, found ${found}", "found", "maximum");
|
||||
|
||||
private static final Splitter SPLITTER = Splitter.on(CommandDispatcher.ARGUMENT_SEPARATOR).limit(2);
|
||||
|
||||
@@ -58,6 +60,10 @@ public class IntegerArgumentType implements CommandArgumentType<Integer> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void listSuggestions(String command, Set<String> output) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
@@ -6,6 +6,8 @@ import com.mojang.brigadier.context.CommandContextBuilder;
|
||||
import com.mojang.brigadier.context.ParsedArgument;
|
||||
import com.mojang.brigadier.exceptions.CommandException;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class ArgumentCommandNode<T> extends CommandNode {
|
||||
private static final String USAGE_ARGUMENT_OPEN = "<";
|
||||
private static final String USAGE_ARGUMENT_CLOSE = ">";
|
||||
@@ -46,12 +48,17 @@ public class ArgumentCommandNode<T> extends CommandNode {
|
||||
contextBuilder.withNode(this, parsed.getRaw());
|
||||
|
||||
if (command.length() > start) {
|
||||
return command.substring(start + 1);
|
||||
return command.substring(start);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void listSuggestions(String command, Set<String> output) {
|
||||
type.listSuggestions(command, output);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.mojang.brigadier.exceptions.CommandException;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class CommandNode {
|
||||
private final Map<Object, CommandNode> children = Maps.newLinkedHashMap();
|
||||
@@ -62,4 +63,6 @@ public abstract class CommandNode {
|
||||
public abstract String getUsageText();
|
||||
|
||||
public abstract String parse(String command, CommandContextBuilder<?> contextBuilder) throws CommandException;
|
||||
|
||||
public abstract void listSuggestions(String command, Set<String> output);
|
||||
}
|
||||
|
||||
@@ -6,8 +6,10 @@ import com.mojang.brigadier.context.CommandContextBuilder;
|
||||
import com.mojang.brigadier.exceptions.CommandException;
|
||||
import com.mojang.brigadier.exceptions.ParameterizedCommandExceptionType;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class LiteralCommandNode extends CommandNode {
|
||||
public static final ParameterizedCommandExceptionType ERROR_INCORRECT_LITERAL = new ParameterizedCommandExceptionType("incorrect_literal", "Expected literal ${expected}", "expected");
|
||||
public static final ParameterizedCommandExceptionType ERROR_INCORRECT_LITERAL = new ParameterizedCommandExceptionType("argument.literal.incorrect", "Expected literal ${expected}", "expected");
|
||||
|
||||
private final String literal;
|
||||
|
||||
@@ -34,10 +36,17 @@ public class LiteralCommandNode extends CommandNode {
|
||||
}
|
||||
|
||||
contextBuilder.withNode(this, literal);
|
||||
int start = expected.length();
|
||||
int start = literal.length();
|
||||
return command.substring(start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void listSuggestions(String command, Set<String> output) {
|
||||
if (literal.startsWith(command)) {
|
||||
output.add(literal);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.mojang.brigadier.tree;
|
||||
import com.mojang.brigadier.context.CommandContextBuilder;
|
||||
import com.mojang.brigadier.exceptions.CommandException;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class RootCommandNode extends CommandNode {
|
||||
public RootCommandNode() {
|
||||
super(null);
|
||||
@@ -23,6 +25,10 @@ public class RootCommandNode extends CommandNode {
|
||||
return command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void listSuggestions(String command, Set<String> output) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
Reference in New Issue
Block a user