Add support for compound arguments for flags
Signed-off-by: Irmo van den Berge <irmo.vandenberge@ziggo.nl>
This commit is contained in:
parent
23c0ad77f9
commit
a978adc79f
3 changed files with 343 additions and 174 deletions
|
|
@ -55,6 +55,7 @@ import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
@ -552,6 +553,11 @@ public final class CommandTree<C> {
|
||||||
final @NonNull Queue<@NonNull String> commandQueue,
|
final @NonNull Queue<@NonNull String> commandQueue,
|
||||||
final @NonNull Node<@Nullable CommandArgument<C, ?>> child
|
final @NonNull Node<@Nullable CommandArgument<C, ?>> child
|
||||||
) {
|
) {
|
||||||
|
/* If argument has no value associated, break out early */
|
||||||
|
if (child.getValue() == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
/* When we get in here, we need to treat compound arguments a little differently */
|
/* When we get in here, we need to treat compound arguments a little differently */
|
||||||
if (child.getValue() instanceof CompoundArgument) {
|
if (child.getValue() instanceof CompoundArgument) {
|
||||||
@SuppressWarnings("unchecked") final CompoundArgument<?, C, ?> compoundArgument = (CompoundArgument<?, C, ?>) child
|
@SuppressWarnings("unchecked") final CompoundArgument<?, C, ?> compoundArgument = (CompoundArgument<?, C, ?>) child
|
||||||
|
|
@ -566,18 +572,27 @@ public final class CommandTree<C> {
|
||||||
commandContext.store("__parsing_argument__", i + 2);
|
commandContext.store("__parsing_argument__", i + 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (child.getValue() instanceof FlagArgument) {
|
} else if (child.getValue().getParser() instanceof FlagArgument.FlagArgumentParser) {
|
||||||
/* Remove all but last */
|
|
||||||
while (commandQueue.size() > 1) {
|
/*
|
||||||
commandContext.store(FlagArgument.FLAG_META, commandQueue.remove());
|
* Use the flag argument parser to deduce what flag is being suggested right now
|
||||||
|
* If empty, then no flag value is being typed, and the different flag options should
|
||||||
|
* be suggested instead.
|
||||||
|
*
|
||||||
|
* Note: the method parseCurrentFlag() will remove all but the last element from
|
||||||
|
* the queue!
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
FlagArgument.FlagArgumentParser<C> parser = (FlagArgument.FlagArgumentParser<C>) child.getValue().getParser();
|
||||||
|
Optional<String> lastFlag = parser.parseCurrentFlag(commandContext, commandQueue);
|
||||||
|
if (lastFlag.isPresent()) {
|
||||||
|
commandContext.store(FlagArgument.FLAG_META, lastFlag.get());
|
||||||
}
|
}
|
||||||
} else if (child.getValue() != null
|
} else if (GenericTypeReflector.erase(child.getValue().getValueType().getType()).isArray()) {
|
||||||
&& GenericTypeReflector.erase(child.getValue().getValueType().getType()).isArray()) {
|
|
||||||
while (commandQueue.size() > 1) {
|
while (commandQueue.size() > 1) {
|
||||||
commandQueue.remove();
|
commandQueue.remove();
|
||||||
}
|
}
|
||||||
} else if (child.getValue() != null
|
} else if (commandQueue.size() <= child.getValue().getParser().getRequestedArgumentCount()) {
|
||||||
&& commandQueue.size() <= child.getValue().getParser().getRequestedArgumentCount()) {
|
|
||||||
for (int i = 0; i < child.getValue().getParser().getRequestedArgumentCount() - 1
|
for (int i = 0; i < child.getValue().getParser().getRequestedArgumentCount() - 1
|
||||||
&& commandQueue.size() > 1; i++) {
|
&& commandQueue.size() > 1; i++) {
|
||||||
commandContext.store(
|
commandContext.store(
|
||||||
|
|
@ -587,7 +602,6 @@ public final class CommandTree<C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child.getValue() != null) {
|
|
||||||
if (commandQueue.isEmpty()) {
|
if (commandQueue.isEmpty()) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
} else if (child.isLeaf() && commandQueue.size() < 2) {
|
} else if (child.isLeaf() && commandQueue.size() < 2) {
|
||||||
|
|
@ -637,9 +651,6 @@ public final class CommandTree<C> {
|
||||||
return child.getValue().getSuggestionsProvider().apply(commandContext, stringOrEmpty(commandQueue.peek()));
|
return child.getValue().getSuggestionsProvider().apply(commandContext, stringOrEmpty(commandQueue.peek()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private @NonNull String stringOrEmpty(final @Nullable String string) {
|
private @NonNull String stringOrEmpty(final @Nullable String string) {
|
||||||
if (string == null) {
|
if (string == null) {
|
||||||
return "";
|
return "";
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
@ -104,131 +105,66 @@ public final class FlagArgument<C> extends CommandArgument<C, Object> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
|
||||||
public @NonNull ArgumentParseResult<@NonNull Object> parse(
|
public @NonNull ArgumentParseResult<@NonNull Object> parse(
|
||||||
final @NonNull CommandContext<@NonNull C> commandContext,
|
final @NonNull CommandContext<@NonNull C> commandContext,
|
||||||
final @NonNull Queue<@NonNull String> inputQueue
|
final @NonNull Queue<@NonNull String> inputQueue
|
||||||
) {
|
) {
|
||||||
/*
|
final FlagParser parser = new FlagParser();
|
||||||
This argument must necessarily be the last so we can just consume all remaining input. This argument type
|
return parser.parse(commandContext, inputQueue);
|
||||||
is similar to a greedy string in that sense. But, we need to keep all flag logic contained to the parser
|
}
|
||||||
*/
|
|
||||||
final Set<CommandFlag<?>> parsedFlags = new HashSet<>();
|
|
||||||
CommandFlag<?> currentFlag = null;
|
|
||||||
|
|
||||||
for (final @NonNull String string : inputQueue) {
|
/**
|
||||||
if (string.startsWith("-") && currentFlag == null) {
|
* Parse command input to figure out what flag is currently being
|
||||||
if (string.startsWith("--")) {
|
* typed at the end of the input queue. If no flag value is being
|
||||||
final String flagName = string.substring(2);
|
* inputed, returns {@link Optional#empty()}.<br>
|
||||||
for (final CommandFlag<?> flag : this.flags) {
|
* <br>
|
||||||
if (flagName.equalsIgnoreCase(flag.getName())) {
|
* Will consume all but the last element from the input queue.
|
||||||
currentFlag = flag;
|
*
|
||||||
break;
|
* @param commandContext Command context
|
||||||
|
* @param inputQueue The input queue of arguments
|
||||||
|
* @return current flag being typed, or <i>empty()</i> if none is
|
||||||
|
*/
|
||||||
|
public @NonNull Optional<String> parseCurrentFlag(
|
||||||
|
final @NonNull CommandContext<@NonNull C> commandContext,
|
||||||
|
final @NonNull Queue<@NonNull String> inputQueue
|
||||||
|
) {
|
||||||
|
/* If empty, nothing to do */
|
||||||
|
if (inputQueue.isEmpty()) {
|
||||||
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Before parsing, retrieve the last known input of the queue */
|
||||||
|
String lastInputValue = "";
|
||||||
|
for (String input : inputQueue) {
|
||||||
|
lastInputValue = input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse, but ignore the result of parsing */
|
||||||
|
final FlagParser parser = new FlagParser();
|
||||||
|
parser.parse(commandContext, inputQueue);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove all but the last element from the command input queue
|
||||||
|
* If the parser parsed the entire queue, restore the last typed
|
||||||
|
* input obtained earlier.
|
||||||
|
*/
|
||||||
|
if (inputQueue.isEmpty()) {
|
||||||
|
inputQueue.add(lastInputValue);
|
||||||
} else {
|
} else {
|
||||||
final String flagName = string.substring(1);
|
while (inputQueue.size() > 1) {
|
||||||
if (flagName.length() > 1) {
|
inputQueue.remove();
|
||||||
boolean oneAdded = false;
|
|
||||||
/* This is a multi-alias flag, find all flags that apply */
|
|
||||||
for (final CommandFlag<?> flag : this.flags) {
|
|
||||||
if (flag.getCommandArgument() != null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (final String alias : flag.getAliases()) {
|
|
||||||
if (flagName.toLowerCase(Locale.ENGLISH).contains(alias.toLowerCase(Locale.ENGLISH))) {
|
|
||||||
if (parsedFlags.contains(flag)) {
|
|
||||||
return ArgumentParseResult.failure(new FlagParseException(
|
|
||||||
string,
|
|
||||||
FailureReason.DUPLICATE_FLAG,
|
|
||||||
commandContext
|
|
||||||
));
|
|
||||||
}
|
|
||||||
parsedFlags.add(flag);
|
|
||||||
commandContext.flags().addPresenceFlag(flag);
|
|
||||||
oneAdded = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
/* We need to parse at least one flag */
|
/*
|
||||||
if (!oneAdded) {
|
* Map to name of the flag.
|
||||||
return ArgumentParseResult.failure(new FlagParseException(
|
*
|
||||||
string,
|
* Note: legacy API made it that FLAG_META stores not the flag name,
|
||||||
FailureReason.NO_FLAG_STARTED,
|
* but the - or -- prefixed name or alias of the flag(s) instead.
|
||||||
commandContext
|
* This can be removed in the future.
|
||||||
));
|
*/
|
||||||
}
|
//return parser.currentFlagBeingParsed.map(CommandFlag::getName);
|
||||||
continue;
|
return parser.currentFlagNameBeingParsed;
|
||||||
} else {
|
|
||||||
for (final CommandFlag<?> flag : this.flags) {
|
|
||||||
for (final String alias : flag.getAliases()) {
|
|
||||||
if (alias.equalsIgnoreCase(flagName)) {
|
|
||||||
currentFlag = flag;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (currentFlag == null) {
|
|
||||||
return ArgumentParseResult.failure(new FlagParseException(
|
|
||||||
string,
|
|
||||||
FailureReason.UNKNOWN_FLAG,
|
|
||||||
commandContext
|
|
||||||
));
|
|
||||||
} else if (parsedFlags.contains(currentFlag)) {
|
|
||||||
return ArgumentParseResult.failure(new FlagParseException(
|
|
||||||
string,
|
|
||||||
FailureReason.DUPLICATE_FLAG,
|
|
||||||
commandContext
|
|
||||||
));
|
|
||||||
}
|
|
||||||
parsedFlags.add(currentFlag);
|
|
||||||
if (currentFlag.getCommandArgument() == null) {
|
|
||||||
/* It's a presence flag */
|
|
||||||
commandContext.flags().addPresenceFlag(currentFlag);
|
|
||||||
/* We don't want to parse a value for this flag */
|
|
||||||
currentFlag = null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (currentFlag == null) {
|
|
||||||
return ArgumentParseResult.failure(new FlagParseException(
|
|
||||||
string,
|
|
||||||
FailureReason.NO_FLAG_STARTED,
|
|
||||||
commandContext
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
final ArgumentParseResult<?> result =
|
|
||||||
((CommandArgument) currentFlag.getCommandArgument())
|
|
||||||
.getParser()
|
|
||||||
.parse(
|
|
||||||
commandContext,
|
|
||||||
new LinkedList<>(Collections.singletonList(string))
|
|
||||||
);
|
|
||||||
if (result.getFailure().isPresent()) {
|
|
||||||
return ArgumentParseResult.failure(result.getFailure().get());
|
|
||||||
} else if (result.getParsedValue().isPresent()) {
|
|
||||||
final CommandFlag erasedFlag = currentFlag;
|
|
||||||
final Object value = result.getParsedValue().get();
|
|
||||||
commandContext.flags().addValueFlag(erasedFlag, value);
|
|
||||||
currentFlag = null;
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException("Neither result or value were present. Panicking.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (currentFlag != null) {
|
|
||||||
return ArgumentParseResult.failure(new FlagParseException(
|
|
||||||
currentFlag.getName(),
|
|
||||||
FailureReason.MISSING_ARGUMENT,
|
|
||||||
commandContext
|
|
||||||
));
|
|
||||||
}
|
|
||||||
/* We've consumed everything */
|
|
||||||
inputQueue.clear();
|
|
||||||
return ArgumentParseResult.success(FLAG_PARSE_RESULT_OBJECT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -342,6 +278,166 @@ public final class FlagArgument<C> extends CommandArgument<C, Object> {
|
||||||
return suggestions(commandContext, input);
|
return suggestions(commandContext, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to parse the command input queue into flags
|
||||||
|
* and flag values. On failure the intermediate results
|
||||||
|
* can be obtained, which are used for providing suggestions.
|
||||||
|
*/
|
||||||
|
private class FlagParser {
|
||||||
|
/** The current flag whose value is being parsed */
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private Optional<CommandFlag<?>> currentFlagBeingParsed = Optional.empty();
|
||||||
|
/**
|
||||||
|
* The name of the current flag being parsed, can be obsoleted in the future.
|
||||||
|
* This name includes the - or -- prefix.
|
||||||
|
*/
|
||||||
|
private Optional<String> currentFlagNameBeingParsed = Optional.empty();
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
|
public @NonNull ArgumentParseResult<@NonNull Object> parse(
|
||||||
|
final @NonNull CommandContext<@NonNull C> commandContext,
|
||||||
|
final @NonNull Queue<@NonNull String> inputQueue
|
||||||
|
) {
|
||||||
|
/*
|
||||||
|
This argument must necessarily be the last so we can just consume all remaining input. This argument type
|
||||||
|
is similar to a greedy string in that sense. But, we need to keep all flag logic contained to the parser
|
||||||
|
*/
|
||||||
|
final Set<CommandFlag<?>> parsedFlags = new HashSet<>();
|
||||||
|
CommandFlag<?> currentFlag = null;
|
||||||
|
String currentFlagName = null;
|
||||||
|
|
||||||
|
String string;
|
||||||
|
while ((string = inputQueue.peek()) != null) {
|
||||||
|
/* No longer typing the value of the current flag */
|
||||||
|
this.currentFlagBeingParsed = Optional.empty();
|
||||||
|
this.currentFlagNameBeingParsed = Optional.empty();
|
||||||
|
|
||||||
|
/* Parse next flag name to set */
|
||||||
|
if (string.startsWith("-") && currentFlag == null) {
|
||||||
|
/* Remove flag argument from input queue */
|
||||||
|
inputQueue.poll();
|
||||||
|
|
||||||
|
if (string.startsWith("--")) {
|
||||||
|
final String flagName = string.substring(2);
|
||||||
|
for (final CommandFlag<?> flag : FlagArgumentParser.this.flags) {
|
||||||
|
if (flagName.equalsIgnoreCase(flag.getName())) {
|
||||||
|
currentFlag = flag;
|
||||||
|
currentFlagName = string;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final String flagName = string.substring(1);
|
||||||
|
if (flagName.length() > 1) {
|
||||||
|
boolean oneAdded = false;
|
||||||
|
/* This is a multi-alias flag, find all flags that apply */
|
||||||
|
for (final CommandFlag<?> flag : FlagArgumentParser.this.flags) {
|
||||||
|
if (flag.getCommandArgument() != null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (final String alias : flag.getAliases()) {
|
||||||
|
if (flagName.toLowerCase(Locale.ENGLISH).contains(alias.toLowerCase(Locale.ENGLISH))) {
|
||||||
|
if (parsedFlags.contains(flag)) {
|
||||||
|
return ArgumentParseResult.failure(new FlagParseException(
|
||||||
|
string,
|
||||||
|
FailureReason.DUPLICATE_FLAG,
|
||||||
|
commandContext
|
||||||
|
));
|
||||||
|
}
|
||||||
|
parsedFlags.add(flag);
|
||||||
|
commandContext.flags().addPresenceFlag(flag);
|
||||||
|
oneAdded = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* We need to parse at least one flag */
|
||||||
|
if (!oneAdded) {
|
||||||
|
return ArgumentParseResult.failure(new FlagParseException(
|
||||||
|
string,
|
||||||
|
FailureReason.NO_FLAG_STARTED,
|
||||||
|
commandContext
|
||||||
|
));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
for (final CommandFlag<?> flag : FlagArgumentParser.this.flags) {
|
||||||
|
for (final String alias : flag.getAliases()) {
|
||||||
|
if (alias.equalsIgnoreCase(flagName)) {
|
||||||
|
currentFlag = flag;
|
||||||
|
currentFlagName = string;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentFlag == null) {
|
||||||
|
return ArgumentParseResult.failure(new FlagParseException(
|
||||||
|
string,
|
||||||
|
FailureReason.UNKNOWN_FLAG,
|
||||||
|
commandContext
|
||||||
|
));
|
||||||
|
} else if (parsedFlags.contains(currentFlag)) {
|
||||||
|
return ArgumentParseResult.failure(new FlagParseException(
|
||||||
|
string,
|
||||||
|
FailureReason.DUPLICATE_FLAG,
|
||||||
|
commandContext
|
||||||
|
));
|
||||||
|
}
|
||||||
|
parsedFlags.add(currentFlag);
|
||||||
|
if (currentFlag.getCommandArgument() == null) {
|
||||||
|
/* It's a presence flag */
|
||||||
|
commandContext.flags().addPresenceFlag(currentFlag);
|
||||||
|
/* We don't want to parse a value for this flag */
|
||||||
|
currentFlag = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (currentFlag == null) {
|
||||||
|
return ArgumentParseResult.failure(new FlagParseException(
|
||||||
|
string,
|
||||||
|
FailureReason.NO_FLAG_STARTED,
|
||||||
|
commandContext
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
/* Mark this flag as the one currently being typed */
|
||||||
|
this.currentFlagBeingParsed = Optional.of(currentFlag);
|
||||||
|
this.currentFlagNameBeingParsed = Optional.of(currentFlagName);
|
||||||
|
|
||||||
|
final ArgumentParseResult<?> result =
|
||||||
|
((CommandArgument) currentFlag.getCommandArgument())
|
||||||
|
.getParser()
|
||||||
|
.parse(
|
||||||
|
commandContext,
|
||||||
|
inputQueue
|
||||||
|
);
|
||||||
|
if (result.getFailure().isPresent()) {
|
||||||
|
return ArgumentParseResult.failure(result.getFailure().get());
|
||||||
|
} else if (result.getParsedValue().isPresent()) {
|
||||||
|
final CommandFlag erasedFlag = currentFlag;
|
||||||
|
final Object value = result.getParsedValue().get();
|
||||||
|
commandContext.flags().addValueFlag(erasedFlag, value);
|
||||||
|
currentFlag = null;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Neither result or value were present. Panicking.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Queue ran out while a flag argument needs to be parsed still */
|
||||||
|
if (currentFlag != null) {
|
||||||
|
return ArgumentParseResult.failure(new FlagParseException(
|
||||||
|
currentFlag.getName(),
|
||||||
|
FailureReason.MISSING_ARGUMENT,
|
||||||
|
commandContext
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We've consumed everything */
|
||||||
|
return ArgumentParseResult.success(FLAG_PARSE_RESULT_OBJECT);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,14 @@
|
||||||
//
|
//
|
||||||
package cloud.commandframework;
|
package cloud.commandframework;
|
||||||
|
|
||||||
|
import cloud.commandframework.arguments.compound.ArgumentTriplet;
|
||||||
import cloud.commandframework.arguments.standard.BooleanArgument;
|
import cloud.commandframework.arguments.standard.BooleanArgument;
|
||||||
import cloud.commandframework.arguments.standard.EnumArgument;
|
import cloud.commandframework.arguments.standard.EnumArgument;
|
||||||
import cloud.commandframework.arguments.standard.IntegerArgument;
|
import cloud.commandframework.arguments.standard.IntegerArgument;
|
||||||
import cloud.commandframework.arguments.standard.StringArgument;
|
import cloud.commandframework.arguments.standard.StringArgument;
|
||||||
import cloud.commandframework.types.tuples.Pair;
|
import cloud.commandframework.types.tuples.Pair;
|
||||||
|
import cloud.commandframework.types.tuples.Triplet;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
@ -87,6 +90,16 @@ public class CommandSuggestionsTest {
|
||||||
.flag(manager.flagBuilder("third").withAliases("t"))
|
.flag(manager.flagBuilder("third").withAliases("t"))
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
|
manager.command(manager.commandBuilder("flags3")
|
||||||
|
.flag(manager.flagBuilder("compound")
|
||||||
|
.withArgument(ArgumentTriplet.of(manager, "triplet",
|
||||||
|
Triplet.of("x", "y", "z"),
|
||||||
|
Triplet.of(int.class, int.class, int.class))
|
||||||
|
.simple()))
|
||||||
|
.flag(manager.flagBuilder("presence").withAliases("p"))
|
||||||
|
.flag(manager.flagBuilder("single")
|
||||||
|
.withArgument(IntegerArgument.of("value"))));
|
||||||
|
|
||||||
manager.command(manager.commandBuilder("numbers").argument(IntegerArgument.of("num")));
|
manager.command(manager.commandBuilder("numbers").argument(IntegerArgument.of("num")));
|
||||||
manager.command(manager.commandBuilder("numberswithfollowingargument").argument(IntegerArgument.of("num"))
|
manager.command(manager.commandBuilder("numberswithfollowingargument").argument(IntegerArgument.of("num"))
|
||||||
.argument(BooleanArgument.of("another_argument")));
|
.argument(BooleanArgument.of("another_argument")));
|
||||||
|
|
@ -211,6 +224,55 @@ public class CommandSuggestionsTest {
|
||||||
final String input6 = "flags2 -f -s";
|
final String input6 = "flags2 -f -s";
|
||||||
final List<String> suggestions6 = manager.suggest(new TestCommandSender(), input6);
|
final List<String> suggestions6 = manager.suggest(new TestCommandSender(), input6);
|
||||||
Assertions.assertEquals(Arrays.asList("-st", "-s"), suggestions6);
|
Assertions.assertEquals(Arrays.asList("-st", "-s"), suggestions6);
|
||||||
|
|
||||||
|
/* When an incorrect flag is specified, should resolve to listing flags */
|
||||||
|
final String input7 = "flags2 --invalid ";
|
||||||
|
final List<String> suggestions7 = manager.suggest(new TestCommandSender(), input7);
|
||||||
|
Assertions.assertEquals(Arrays.asList("--first", "--second", "--third", "-f", "-s", "-t"), suggestions7);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCompoundFlags() {
|
||||||
|
final String input = "flags3 ";
|
||||||
|
final List<String> suggestions = manager.suggest(new TestCommandSender(), input);
|
||||||
|
Assertions.assertEquals(Arrays.asList("--compound", "--presence", "--single", "-p"), suggestions);
|
||||||
|
|
||||||
|
final String input2 = "flags3 --c";
|
||||||
|
final List<String> suggestions2 = manager.suggest(new TestCommandSender(), input2);
|
||||||
|
Assertions.assertEquals(Arrays.asList("--compound"), suggestions2);
|
||||||
|
|
||||||
|
final String input3 = "flags3 --compound ";
|
||||||
|
final List<String> suggestions3 = manager.suggest(new TestCommandSender(), input3);
|
||||||
|
Assertions.assertEquals(Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9"), suggestions3);
|
||||||
|
|
||||||
|
final String input4 = "flags3 --compound 1";
|
||||||
|
final List<String> suggestions4 = manager.suggest(new TestCommandSender(), input4);
|
||||||
|
Assertions.assertEquals(Arrays.asList("1", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19"), suggestions4);
|
||||||
|
|
||||||
|
final String input5 = "flags3 --compound 22 ";
|
||||||
|
final List<String> suggestions5 = manager.suggest(new TestCommandSender(), input5);
|
||||||
|
Assertions.assertEquals(Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9"), suggestions5);
|
||||||
|
|
||||||
|
final String input6 = "flags3 --compound 22 1";
|
||||||
|
final List<String> suggestions6 = manager.suggest(new TestCommandSender(), input6);
|
||||||
|
Assertions.assertEquals(Arrays.asList("1", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19"), suggestions6);
|
||||||
|
|
||||||
|
/* We've typed compound already, so that flag should be omitted from the suggestions */
|
||||||
|
final String input7 = "flags3 --compound 22 33 44 ";
|
||||||
|
final List<String> suggestions7 = manager.suggest(new TestCommandSender(), input7);
|
||||||
|
Assertions.assertEquals(Arrays.asList("--presence", "--single", "-p"), suggestions7);
|
||||||
|
|
||||||
|
final String input8 = "flags3 --compound 22 33 44 --pres";
|
||||||
|
final List<String> suggestions8 = manager.suggest(new TestCommandSender(), input8);
|
||||||
|
Assertions.assertEquals(Arrays.asList("--presence"), suggestions8);
|
||||||
|
|
||||||
|
final String input9 = "flags3 --compound 22 33 44 --presence ";
|
||||||
|
final List<String> suggestions9 = manager.suggest(new TestCommandSender(), input9);
|
||||||
|
Assertions.assertEquals(Arrays.asList("--single"), suggestions9);
|
||||||
|
|
||||||
|
final String input10 = "flags3 --compound 22 33 44 --single ";
|
||||||
|
final List<String> suggestions10 = manager.suggest(new TestCommandSender(), input10);
|
||||||
|
Assertions.assertEquals(Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9"), suggestions10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue