Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Named Parameters and Per Parameter Tab Completion #178

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

bundabrg
Copy link

@bundabrg bundabrg commented Oct 28, 2018

Overview

Provides both Named Parameters through the @Switch annotation as well as per parameter TabCompletion

A parameter can optionally be annotated with @Switch to provide one or more names it can be referred by. It can then be used anywhere before its normal position upto and including its normal position by passing "-{switch name} {value}" in the command. It can also be used normally by position as well without the switch name.

Due to the nature of how Tab completions work, a Switch MUST use the parameter CommandCompletion annotation to provide tab completions, otherwise it will be assumed to have none in those positions. Method Level CommandCompletion annotations will be respected as well.

Both execution and tab completion use a method parseArgument to ensure both follow the same parsing rules.

Example

    @Subcommand("open|o")
    @Description("Open Menu")
    @CommandCompletion("@menulist")
    public void onOpen(
        CommandSender sender,
        String menuItem,
        @Switch("player,p") @CommandCompletion("@players") OnlinePlayer player,
        @Switch("title") @CommandCompletion("title1|title2") String title)

This will allow the following to work:

/cmd open mainmenu playername title1
/cmd open -player playername mainmenu title1
/cmd open -title title1 mainmenu playername
/cmd open -title title1 -player playername mainmenu
/cmd open mainmenu -player playername -title title1
/cmd open mainmenu playername -title title1

Whilst typing, when a '-' is detected, tab completion will show a completion list of unused switches. This will be reduced as switches are used or the parameters providing the switch are resolved by position. So in the 4th example when starting to type "-player" it will only show "-player" on the tab completion, whereas before typing "-title" it will show both options. In the 6th example when starting to type '-title' it will only show '-title' as player has already been satisfied by position.

After a switch is typed its own command completions will be provided.

Note in the example it will use the @menulist tab completion for argument menuitem, and the per parameter ones for the other parameters.

How its done

A new method to RegisterdedCommand, parseArgument, is used to take a list of arguments and return the current completion, the list of parameters (in the order detected from the arguments, so not necessarily in proper parameter order), a list of unused switches, and if the current argument is potentially a switch (allows a "-" sign to be used as an argument to a switch without it thinking its a new switch).

Both TabCompletion and Execution use this to resolve the arguments to ensure that both operate the same way.

Reason for requiring Per Parameter Tab Completion

There some challenges to a Switch with tab completion. One of the biggest ones is that an IssuerAwareContext does not have to consume any arguments (For example a Player.class will consume its argument if there is a Flag("other") provided, otherwise it does not), which also means it does not consume tab completions. This makes it impossible to know real time which tab completions to move using position only.

In order to satisfy as many of the requirements for this as possible with fewest changes, the easiest option is to require that a per-parameter tab completion is provided for a Switch.

For example:

    @Subcommand("open|o")
    @Description("Open Menu")
    @CommandCompletion("@players test1|test2")
    public void onOpen(
        CommandSender sender,
        Player player1
        @Flag("other") Player player2
        @Switch("test,t") String test)

it is impossible to know that the @players belongs to player2 and not player1 without knowing that a Player context uses a flag to change its behaviour. This means typing '-test', it is hard to know that 'test1|test2' belongs to that parameter.

The only option is if parameters were actively involved in tab completion or declared the number of arguments they consume upfront. This is not easy to satsify in a backwards compatible method.

Todo

  • Maybe a flag to force a switch to be named rather than satisfied by position (IE: @Switch("option", true)) with false by default to allow it to satsify either by position or name. I'm not too sure if this is needed or not.

  • Handle @Optional and @Default if it doesn't already work

A parameter can optionally be annoted with @switch to provide one or more names it can be referred by. It can then be used anywhere before its normal position upto and including its normal position. It can also be used normally by position as well without the switch name.

Due to the nature of how Tab completions work, a Switch MUST use the parameter CommandCompletion annotation to provide tab completions, otherwise it will assume to have none in those positions. Method Level CommandCompletion annotations will be respected as well.

Both execution and tab completion use a method parseArgument to ensure both follow the same parsing rules.
@Saturn745
Copy link

Sorry to necro post but is their any updates on this? Would be an amazing feature to have.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants