Suggestions
Suggestions
Suggestions are a powerful feature in Imperat that allow you to provide helpful hints to users as they type commands.
Using Suggestions
Imperat does not control how suggestions are displayed to the user, as this is determined by the platform's implementation of the Source interface.
However, Imperat provides a way for you to define and provide suggestions for command arguments, which can enhance the user experience by offering real-time feedback and guidance on what inputs are expected.
Moreover, Imperat integrates with the platform's suggestion system to provide dynamic suggestions based on the context of the command and the input provided by the user. This allows you to create a more interactive and user-friendly command system, where users can easily discover available options and understand the expected input format for each argument.
Suggestions are classified into static and dynamic suggestions, based on how they are retrieved/generated.
- Static Suggestions: These are predefined suggestions that are always the same regardless of the context or user input. They are often used for arguments that have a fixed set of valid values, such as a list of available ranks or game modes.
- Dynamic Suggestions: These are suggestions that are generated based on the current context, such as the user's input or other factors.
Dynamic suggestions can be particularly useful for arguments that require more complex input or have a large number of valid values, as they can provide real-time feedback and guidance to users as they type.
What is SuggestionProvider?
A SuggestionProvider is a functional interface that defines a method for providing suggestions based on the current input and context of a command execution.
It's the core component responsible for generating suggestions for command arguments, allowing you to create dynamic and context-aware suggestions.
It can also be used to create static suggestions by returning a fixed CACHED list of suggestions regardless of the input or context.
Setting Suggestions for Arguments
It differs based on the type of suggestions you want to provide, whether they are static or dynamic.
Static Suggestions
To set static suggestions for particular arguments in your pathway, annotate the parameter with @Suggest, as follows:
public class ExampleCommand {
@RootCommand("example")
public void example(PLATFORMSOURCE source, @Suggest("option1", "option2", "option3") String option) {
// Command logic here
}
}
Dynamic Suggestions
To set dynamic suggestions for particular arguments in your pathway, you should use @SuggestionProvider annotation on the parameter representing the argument,
and provide the class of the SuggestionProvider implementation that will generate the suggestions, this involves two main steps:
- Create a class that implements the
SuggestionProviderinterface and implement theprovidemethod to generate suggestions based on the context and input. - Annotate the parameter in your command with
@SuggestionProviderand specify the class of yourSuggestionProviderimplementation.
First, let's create a SuggestionProvider implementation that generates dynamic suggestions based on a registry of ranks:
public class OptionsSuggestionProvider implements SuggestionProvider<PLATFORMSOURCE> {
@Override
public List<String> provide(SuggestionContext<PLATFORMSOURCE> context, Argument<PLATFORMSOURCE> parameter) {
// Example logic to generate suggestions based on input
return Arrays.asList("option1", "option2", "option3");
}
}
Then, you can use this SuggestionProvider in your command to provide dynamic suggestions for the option argument:
@RootCommand("example")
public class ExampleCommand {
@Execute
public void example(PLATFORMSOURCE source, @SuggestionProvider(OptionsSuggestionProvider.class) String option) { //[!code focus]
// Command logic here
}
}
If your implementation(of SuggestionProvider)'s constructor requires parameters/dependencies, you MUST provide a way for imperat to instantiate it.
Please refer to the InstanceFactory section for more details on how to achieve this.
Suggestions for custom types
When creating custom argument types, you can also provide suggestions for them by overriding the getSuggestionProvider method in your custom argument type implementation.
This allows you to provide context-aware suggestions for your custom types.
Here's an example for providing suggestions of available ranks for a custom Rank type:
public class RankArgumentType extends ArgumentType<PLATFORMSOURCE, Rank> {
@Override
public @Nullable Rank parse(
@NotNull CommandContext<PLATFORMSOURCE> context,
@NotNull Argument<PLATFORMSOURCE> argument,
@NotNull String input
) throws CommandException {
Rank rank = yourRankRegistry.getRank(input);
if (rank == null) {
throw new UnknownRankException(input);
}
// for testing purposes, we will just return a new Rank with the name equal to the input
return rank;
}
@Override //assuming #getAllRanks returns a `List<Rank>`
public SuggestionProvider<PLATFORMSOURCE> getSuggestionProvider() {
return (ctx, arg)-> {
return yourRankRegistry.getAllRanks().stream()
.map(Rank::getName)
.toList();
};
}
}
and then use this custom argument type in your command:
@RootCommand("setrank")
public class RankCommand {
@Execute
public void exec(PLATFORMSOURCE source, String user, Rank rank) {
// syntax: /setrank <user> <rank>
}
}
Thus, when the user starts typing the rank argument or presses TAB for suggestions, they will receive real-time suggestions of valid ranks based on the available ranks in the registry.
Setting argument-specific suggestions using the @SuggestionProvider annotation takes precedence over the suggestions provided by the argument type's getSuggestionProvider method.
This means that if you annotate a parameter with @SuggestionProvider, the suggestions generated by that provider will be used
instead of the suggestions provided by the argument type, allowing you to customize suggestions on a per-argument basis when needed.