remkop / picocli

Picocli is a modern framework for building powerful, user-friendly, GraalVM-enabled command line apps with ease. It supports colors, autocompletion, subcommands, and more. In 1 source file so apps can include as source & avoid adding a dependency. Written in Java, usable from Groovy, Kotlin, Scala, etc.
https://picocli.info
Apache License 2.0
4.9k stars 422 forks source link

Command completion attached to a parameter/option type converter instead of a specific parameter/option #1403

Open soccermitchy opened 3 years ago

soccermitchy commented 3 years ago

This is in the same setup I have described in #1402 (using picocli in Minecraft). I've implemented type converters for things such as player names/UUIDs --> Player, however I'd also like to implement the ability to autocomplete player names passed as parameters/options in a way that's transparent to whoever is writing the command. In other words, I don't want to require the user writing commands to have a customCompletion parameter.

Is there a way to assign a custom completion method based on type, like how I can just do this to register a type converter?

cmd.registerConverter(ProxiedPlayer.class, new BungeePlayerConverter());

I'm thinking something that'd be used like:

cmd.registerCompletion(ProxiedPlayer.class, new BungeePlayerConverter()); // assuming BungeePlayerConverter also implements Iterable<String>
remkop commented 3 years ago

@soccermitchy Apologies for my late reply; I was traveling with family.

To be honest, I am not sure that I understand what problem you are trying to solve, but I will take a stab at it. ;-)

I'd also like to implement the ability to autocomplete player names passed as parameters/options in a way that's transparent to whoever is writing the command.

When you say "writing the command", do you mean entering the command on the game command line? Or do you mean other people can extend your work to create their own custom Minecraft commands, and you want such custom commands to have some built-in facilities, like player name auto-completion?

Is there a way to assign a custom completion method based on type (...)?

One idea is to use a model transformation.

I am assuming that you are creating a framework for other people to easily create their own custom Minecraft commands. I also assume that your framework is either inheritance-based or @Mixin-based: people extend a base command or have a @Mixin-annotated field (whose class is defined in your framework) to get some nice facilities. If my assumptions are correct, then your base command or mixin could have a @Command(modelTransformer = MyTransform.class) annotation that defines some logic. This logic will be executed after the full command hierarchy is constructed, and before any command line arguments are parsed.

You could use this timing to loop over all options and positional parameters, check their type, and for certain types assign a custom completion method that is defined in your framework.

Does this answer your question?

soccermitchy commented 3 years ago

Apologies for my late reply; I was traveling with family.

No problem, I completely understand!

To be honest, I am not sure that I understand what problem you are trying to solve, but I will take a stab at it. ;-)

The problem I'm trying to solve is that, on this specific server, our staff uses commands that can sometimes have a dozen different parameters, and we currently have all of our documentation on that in various Discord messages, an internal wiki, various google docs, etc. We want to make it so you:

and picocli seemed like a good fit for all of this.

When you say "writing the command", do you mean entering the command on the game command line? Or do you mean other people can extend your work to create their own custom Minecraft commands, and you want such custom commands to have some built-in facilities, like player name auto-completion?

I'm saying people (ie. developers on this server - this code is currently part of a closed-source, private plugin but we may open-source this as a library we see interest in others using it) are able to extend my work to make their own Minecraft commands, and I wanted to allow stuff like player name auto-completion.

One idea is to use a model transformation.

Ooh, didn't see that feature before - it looks like it can do what I need! I'll take a look at this when I'm back home later, but..

I am assuming that you are creating a framework for other people to easily create their own custom Minecraft commands. I also assume that your framework is either inheritance-based or @Mixin-based: people extend a base command or have a @Mixin-annotated field (whose class is defined in your framework) to get some nice facilities.

Our framework is inheritance-based, but our base class is not a command itself, ie. commands need to specify @Command themselves. Commands inherit from either BungeeParksCommand or SpigotParksCommand, depending on what environment they are running in (ie, BungeeCord or Spigot/PaperSpigot), then both of those eventually make an instance of ParksCommandCaller which handles most shared things like actually running the command, generating autocompletions, running Minecraft permissions checks, generating error messages, etc. That said, because we don't use a mixin to do everything, and the base class is not a command, am I correct in assuming we can do something similar to:

        cmd.getCommandSpec().modelTransformer(new MyTransformer());
remkop commented 2 years ago

@soccermitchy Did you have a chance to try the model transformer and have you found a solution for your use case?