Add predicate command filter option to the cloud help system
Signed-off-by: Irmo van den Berge <irmo.vandenberge@ziggo.nl>
This commit is contained in:
parent
4556f12b6d
commit
cabb7f426c
4 changed files with 168 additions and 5 deletions
|
|
@ -38,13 +38,19 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public final class CommandHelpHandler<C> {
|
||||
|
||||
private final CommandManager<C> commandManager;
|
||||
private final Predicate<Command<C>> commandPredicate;
|
||||
|
||||
CommandHelpHandler(final @NonNull CommandManager<C> commandManager) {
|
||||
CommandHelpHandler(
|
||||
final @NonNull CommandManager<C> commandManager,
|
||||
final @NonNull Predicate<Command<C>> commandPredicate
|
||||
) {
|
||||
this.commandManager = commandManager;
|
||||
this.commandPredicate = commandPredicate;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -55,6 +61,11 @@ public final class CommandHelpHandler<C> {
|
|||
public @NonNull List<@NonNull VerboseHelpEntry<C>> getAllCommands() {
|
||||
final List<VerboseHelpEntry<C>> syntaxHints = new ArrayList<>();
|
||||
for (final Command<C> command : this.commandManager.getCommands()) {
|
||||
/* Check command is not filtered */
|
||||
if (!this.commandPredicate.test(command)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final List<CommandArgument<C, ?>> arguments = command.getArguments();
|
||||
final String description = command.getCommandMeta().getOrDefault(CommandMeta.DESCRIPTION, "");
|
||||
syntaxHints.add(new VerboseHelpEntry<>(
|
||||
|
|
@ -188,7 +199,7 @@ public final class CommandHelpHandler<C> {
|
|||
int index = 0;
|
||||
|
||||
outer:
|
||||
while (head != null) {
|
||||
while (head != null && this.isNodeVisible(head)) {
|
||||
++index;
|
||||
traversedNodes.add(head.getValue());
|
||||
|
||||
|
|
@ -233,6 +244,11 @@ public final class CommandHelpHandler<C> {
|
|||
/* Attempt to parse the longest possible description for the children */
|
||||
final List<String> childSuggestions = new LinkedList<>();
|
||||
for (final CommandTree.Node<CommandArgument<C, ?>> child : head.getChildren()) {
|
||||
/* Check filtered by predicate */
|
||||
if (!this.isNodeVisible(child)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final List<CommandArgument<C, ?>> traversedNodesSub = new LinkedList<>(traversedNodes);
|
||||
if (recipient == null
|
||||
|| child.getValue() == null
|
||||
|
|
@ -252,6 +268,29 @@ public final class CommandHelpHandler<C> {
|
|||
return new IndexHelpTopic<>(Collections.emptyList());
|
||||
}
|
||||
|
||||
/* Checks using the predicate whether a command node or one of its children is visible */
|
||||
private boolean isNodeVisible(
|
||||
final CommandTree.@NonNull Node<CommandArgument<C, ?>> node
|
||||
) {
|
||||
/* Check node is itself a command that is visible */
|
||||
final CommandArgument<C, ?> argument = node.getValue();
|
||||
if (argument != null) {
|
||||
final Command<C> owningCommand = argument.getOwningCommand();
|
||||
if (owningCommand != null && this.commandPredicate.test(owningCommand)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Query the children recursively */
|
||||
for (CommandTree.Node<CommandArgument<C, ?>> childNode : node.getChildren()) {
|
||||
if (this.isNodeVisible(childNode)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Something that can be returned as the result of a help query
|
||||
* <p>
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ import java.util.concurrent.CompletableFuture;
|
|||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* The manager is responsible for command registration, parsing delegation, etc.
|
||||
|
|
@ -753,13 +754,30 @@ public abstract class CommandManager<C> {
|
|||
|
||||
/**
|
||||
* Get a command help handler instance. This can be used to assist in the production
|
||||
* of command help menus, etc.
|
||||
* of command help menus, etc. This command help handler instance will display
|
||||
* all commands registered in this command manager.
|
||||
*
|
||||
* @return Command help handler. A new instance will be created
|
||||
* each time this method is called.
|
||||
*/
|
||||
public final @NonNull CommandHelpHandler<C> getCommandHelpHandler() {
|
||||
return new CommandHelpHandler<>(this);
|
||||
return new CommandHelpHandler<>(this, cmd -> true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a command help handler instance. This can be used to assist in the production
|
||||
* of command help menus, etc. A predicate can be specified to filter what commands
|
||||
* registered in this command manager are visible in the help menu.
|
||||
*
|
||||
* @param commandPredicate Predicate that filters what commands are displayed in
|
||||
* the help menu.
|
||||
* @return Command help handler. A new instance will be created
|
||||
* each time this method is called.
|
||||
*/
|
||||
public final @NonNull CommandHelpHandler<C> getCommandHelpHandler(
|
||||
final @NonNull Predicate<Command<C>> commandPredicate
|
||||
) {
|
||||
return new CommandHelpHandler<>(this, commandPredicate);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
//
|
||||
package cloud.commandframework;
|
||||
|
||||
import cloud.commandframework.arguments.CommandArgument;
|
||||
import cloud.commandframework.arguments.StaticArgument;
|
||||
import cloud.commandframework.arguments.standard.IntegerArgument;
|
||||
import cloud.commandframework.arguments.standard.StringArgument;
|
||||
import cloud.commandframework.meta.CommandMeta;
|
||||
|
|
@ -36,6 +38,8 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class CommandHelpHandlerTest {
|
||||
|
||||
|
|
@ -93,6 +97,94 @@ class CommandHelpHandlerTest {
|
|||
this.printTopic("vec", query4);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPredicateFilter() {
|
||||
/*
|
||||
* This predicate only displays the commands starting with /test
|
||||
* The one command ending in 'thing' is excluded as well, for complexity
|
||||
*/
|
||||
final Predicate<Command<TestCommandSender>> predicate = (command) -> {
|
||||
return command.toString().startsWith("test ")
|
||||
&& !command.toString().endsWith(" thing");
|
||||
};
|
||||
|
||||
/*
|
||||
* List all commands from root, which should show only:
|
||||
* - /test <potato>
|
||||
* - /test int <int>
|
||||
*/
|
||||
final CommandHelpHandler.HelpTopic<TestCommandSender> query1 = manager.getCommandHelpHandler(predicate).queryHelp("");
|
||||
Assertions.assertTrue(query1 instanceof CommandHelpHandler.IndexHelpTopic);
|
||||
Assertions.assertEquals(Arrays.asList("test <potato>", "test int <int>"), getSortedSyntaxStrings(query1));
|
||||
|
||||
/*
|
||||
* List all commands from /test, which should show only:
|
||||
* - /test <potato>
|
||||
* - /test int <int>
|
||||
*/
|
||||
final CommandHelpHandler.HelpTopic<TestCommandSender> query2 = manager.getCommandHelpHandler(predicate).queryHelp("test");
|
||||
Assertions.assertTrue(query2 instanceof CommandHelpHandler.MultiHelpTopic);
|
||||
Assertions.assertEquals(Arrays.asList("test <potato>", "test int <int>"), getSortedSyntaxStrings(query2));
|
||||
|
||||
/*
|
||||
* List all commands from /test int, which should show only:
|
||||
* - /test int <int>
|
||||
*/
|
||||
final CommandHelpHandler.HelpTopic<TestCommandSender> query3 = manager.getCommandHelpHandler(predicate).queryHelp("test int");
|
||||
Assertions.assertTrue(query3 instanceof CommandHelpHandler.VerboseHelpTopic);
|
||||
Assertions.assertEquals(Arrays.asList("test int <int>"), getSortedSyntaxStrings(query3));
|
||||
|
||||
/*
|
||||
* List all commands from /vec, which should show none
|
||||
*/
|
||||
final CommandHelpHandler.HelpTopic<TestCommandSender> query4 = manager.getCommandHelpHandler(predicate).queryHelp("vec");
|
||||
Assertions.assertTrue(query4 instanceof CommandHelpHandler.IndexHelpTopic);
|
||||
Assertions.assertEquals(Collections.emptyList(), getSortedSyntaxStrings(query4));
|
||||
}
|
||||
|
||||
/* Lists all the syntax strings of the commands displayed in a help topic */
|
||||
private List<String> getSortedSyntaxStrings(
|
||||
final CommandHelpHandler.HelpTopic<TestCommandSender> helpTopic
|
||||
) {
|
||||
if (helpTopic instanceof CommandHelpHandler.IndexHelpTopic) {
|
||||
CommandHelpHandler.IndexHelpTopic<TestCommandSender> index =
|
||||
(CommandHelpHandler.IndexHelpTopic<TestCommandSender>) helpTopic;
|
||||
|
||||
return index.getEntries().stream()
|
||||
.map(CommandHelpHandler.VerboseHelpEntry::getSyntaxString)
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
} else if (helpTopic instanceof CommandHelpHandler.MultiHelpTopic) {
|
||||
CommandHelpHandler.MultiHelpTopic<TestCommandSender> multi =
|
||||
(CommandHelpHandler.MultiHelpTopic<TestCommandSender>) helpTopic;
|
||||
|
||||
return multi.getChildSuggestions().stream()
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
} else if (helpTopic instanceof CommandHelpHandler.VerboseHelpTopic) {
|
||||
CommandHelpHandler.VerboseHelpTopic<TestCommandSender> verbose =
|
||||
(CommandHelpHandler.VerboseHelpTopic<TestCommandSender>) helpTopic;
|
||||
|
||||
//TODO: Use CommandManager syntax for this
|
||||
StringBuilder syntax = new StringBuilder();
|
||||
for (CommandArgument<TestCommandSender, ?> argument : verbose.getCommand().getArguments()) {
|
||||
if (argument instanceof StaticArgument) {
|
||||
syntax.append(argument.getName());
|
||||
} else if (argument.isRequired()) {
|
||||
syntax.append('<').append(argument.getName()).append('>');
|
||||
} else {
|
||||
syntax.append('[').append(argument.getName()).append(']');
|
||||
}
|
||||
syntax.append(' ');
|
||||
}
|
||||
syntax.setLength(syntax.length() - 1);
|
||||
return Collections.singletonList(syntax.toString());
|
||||
}
|
||||
|
||||
/* Dunno */
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private void printTopic(
|
||||
final String query,
|
||||
final CommandHelpHandler.HelpTopic<TestCommandSender> helpTopic
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
//
|
||||
package cloud.commandframework.minecraft.extras;
|
||||
|
||||
import cloud.commandframework.Command;
|
||||
import cloud.commandframework.CommandComponent;
|
||||
import cloud.commandframework.CommandHelpHandler;
|
||||
import cloud.commandframework.CommandManager;
|
||||
|
|
@ -44,6 +45,7 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Opinionated extension of {@link CommandHelpHandler} for Minecraft
|
||||
|
|
@ -86,6 +88,7 @@ public final class MinecraftHelp<C> {
|
|||
private final String commandPrefix;
|
||||
private final Map<String, String> messageMap = new HashMap<>();
|
||||
|
||||
private Predicate<Command<C>> commandFilter = c -> true;
|
||||
private BiFunction<C, String, String> messageProvider = (sender, key) -> this.messageMap.get(key);
|
||||
private HelpColors colors = DEFAULT_HELP_COLORS;
|
||||
private int headerFooterLength = DEFAULT_HEADER_FOOTER_LENGTH;
|
||||
|
|
@ -151,6 +154,17 @@ public final class MinecraftHelp<C> {
|
|||
return this.audienceProvider.apply(sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a filter for what commands are visible inside the help menu.
|
||||
* When the {@link Predicate} tests <i>true</i>, then the command
|
||||
* is included in the listings.
|
||||
*
|
||||
* @param commandPredicate Predicate to filter commands by
|
||||
*/
|
||||
public void setCommandFilter(final @NonNull Predicate<Command<C>> commandPredicate) {
|
||||
this.commandFilter = commandPredicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a message
|
||||
*
|
||||
|
|
@ -241,7 +255,7 @@ public final class MinecraftHelp<C> {
|
|||
recipient,
|
||||
query,
|
||||
page,
|
||||
this.commandManager.getCommandHelpHandler().queryHelp(recipient, query)
|
||||
this.commandManager.getCommandHelpHandler(this.commandFilter).queryHelp(recipient, query)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue