Hello, I would like to implement tab completion in my plugins; however, I can not figure out how to do it. I create my commands by implementing the CommandExecutor
. Could someone point me in the right direction on how I can achieve this?
A CommandCallable
handles execution, permissions and autocomplete of a command. By contrast, CommandExecutor
only does command execution. This is because the rest is handled by the CommandSpec
object that you build.
So if you want to autocomplete using a CommandSpec
you specify arguments of that children - the spec will not only generate all of the autocomplete values but also the help text. This is all so you can access those arguments later using the CommandContext
object.
This is all explained in depth in the command docs: https://docs.spongepowered.org/master/en/plugin/commands/index.html
Tab completion is handled by default, because of how you specify your arguments in your CommandSpec. The best solution to making your own tab-completion is by making your own CommandElement that you would use in your CommandSpec.
So if I want to create a custom autocomplete by implementing the CommandCallable
, which method would I override?
That would be getSuggestions(CommandSource source, String arguments)
But I’d highly recommend using the CommandSpec
object with custom arguments - it’s a much cleaner system and has things like auto generated command usage and child commands.
How do I register custom arguments?
Make a class that extends CommandElement. These are what you use as arguments in your CommandSpec builder, and chiefly found as return values for GenericArguments’s methods. Javadocs and example
Thank you! I’ll take a look at that!
Can I use add a custom usage message using a CommandSpec
? It doesn’t quite get the ‘not enough arguments’ message correct.
If there is not a simple way, I will just make all arguments optional and send my usage message if they are not present.
Ofc you can. Look at the javadocs definition. All you have to do is override the method public Text getUsage(CommandSource)
. Additionally, if you throw an ArgumentParseException from parseValue() by using CommandArgs#createError(Text), the Text object will be shown to the player in red. So, for example, in the Vector2i definition, it gets the next two arguments, and parses them into ints. If parsing fails (i.e. NumberFormatException), it throws an ArgumentParseException generated by CommandArgs#createError(Text.of("<argument> is not a valid number!")).
Thanks for explaining that, but unfortunately that is not quite what I meant. I meant when implementing the CommandExecutor
class is there any easy way to have a custom usage message?
No, but why would you need one? Usage is handled properly by the CommandElements and the CommandSpec.
The arguments for the command do not display at all in the usage message.
Example:
I have a main command /main
, with a subcommand, /main set
. The subcommand takes two string arguments, called arg1
and arg2
. Running /main set
without any arguments should send a message displaying what arguments to input, but all it sends is a message that says Not enough arguments!
. When I run the command /main set
without arguments, I want it to send a message similar to Usage: /main set <arg1> <arg2>
.
Can I see your command initialization code?
It is way to completed and split into multiple classes and files, but here is the argument registration:
CommandSpec.builder()
.arguments(GenericArguments.user(Text.of("player")), GenericArguments.doubleNum(Text.of("balance")))
.executor(this);
You are correct, and that is most likely a bug of some sort.
You could always submit a pull request, with a better error outputter.
Actually, looks like the proper usage statement isn’t shown in /help either. This is probably in need of fixing.
The issue is now on GitHub if anyone has been following this thread.