-
Notifications
You must be signed in to change notification settings - Fork 418
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
Script auto-completion only ever completes options and never default bash completions #461
Comments
What you’re saying makes sense. |
I think this will do it, but I couldn't find where it actually tests for this issue (although it did not break any existing tests). |
PS. If you have ideas for more or better tests, they’ll be very welcome! |
It would require having bash on the testing machine and being able to interact with it to verify the completion, but I am not sure how feasible that is. |
It is also be possible to complete positional parameters in the same way that options are being completed now in I haven't looked into this yet, so I am not sure how hard it will be to implement, but I may at least file another issue. For now, the default completion should complete files/directories for all non-options, which is at least an improvement. |
I think that I also need to test this with a command that uses |
The case where no options are given will have to be fixed. This small fix was apparently too good to be true. If |
Currently, #462 is repeating the bug that both options and commands are given as a possible completion at the same time. And because it is checking for We want to split options and subcommands into separate cases, with something like the following, except that this allows the subcommand to appear multiple times
|
Maybe we should clarify first what exactly the expected behaviour is. Example program: @Command(name = "better", subcommands = { Sub.class, Sub2.class, Sub3.class } )
class Main {
@Option(names = { "-h", "--help"}) boolean help;
@Option(names = { "-V", "--version"}) boolean version;
@Option(names = { "-n", "--number"}) int number;
@Parameters File[] files; // we want file completions
}
@Command(name = "sub")
class Sub {
@Option(names = { "-h", "--help"}) boolean help;
@Option(names = { "-d", "--dir"}) File dir;
@Parameters InetAddress[] hosts; // we want host completions
}
@Command(name = "sub2")
class Sub2 {
@Option(names = { "-n", "--num"}) int[] numbers;
@Parameters(index = "0") InetAddress host; // we want host completions
@Parameters(index = "1") File file; // and we want file completions
}
@Command(name = "sub3")
class Sub3 {
@Parameters int[] moreNumbers; // we want default completions
}
Thoughts? |
Here are my responses:
|
Another issue with the existing code is that it has an outer and inner loop. I don't even think that this is accomplishing anything. Am I wrong? Could we not replace
with
|
Comments for case 1 or the general case and what I believe is the first issue that ought to be fixed: Assume first that The easy case: if the subcommand is required, then propose only subcommands. The ambigous case: I would say that it should propose both subcommands and file completions, since either is allowed here, proposing the subcommands first for clarity. Also, you have not mentioned this, but I believe that the command may only occur as the first word, Anything after the first word is considered a parameter. One problem with the existing picocli code and the naive fix is that it does not take position into account and so it is proposing the commands multiple times/in any position. |
Another issue with the existing code is that it does not handle option-parameter separators ( |
If you use bash-completion, you can do something like:
since |
external dependencyI am reluctant to depend on bash-completion. Maybe one idea is to let application authors decide whether they want to generate a completion script that works reasonably well and does not require any dependencies, OR whether they want to generate a more powerful completion script that requires their end users to install bash-completion. inner loopThis is to handle completion on option arguments. ${PREV_WORD} is the option, ${CURR_WORD} is potentially the option argument. option-parameter separatorYou are correct, this is currently not handled well. position-specific completion(Like in the subcommandsPicocli does not have the concept of required subcommands. Is it possible to combine a built-in (file completion) with a predefined list of candidates (subcommand names)? If that is possible, I like the idea of showing subcommands first, but I believe bash always sorts the completion candidates alphabetically. If we cannot combine a built-in with a pre-defined list I think we should just show subcommands.
I thought the current completion script correctly shows subcommands of the preceding command. For example, if global optionsPicocli does not have the concept of global options. Options following a subcommand need to be defined in that subcommand. |
The bash-completion software itself is under GPLv2+ (as opposed to ASL 2.0 for picocli). I just don't want to be in the situation such that for every new feature we want to add, we are just re-implementing what is already in bash-completion. I still wasn't sure if #461 (comment) was the correct fix. I will have to test it again. I thought that it was proposing
It does not appear to be needed. You can remove the outer loop and not lose functionality. It seems to want to handle the case where you have an empty (
Yes, let's push this to a separate issue. This ticket should just be to handle existing features correctly and not to add new features.
Yes, you can combine them, but you are correct in that it will always sort them. When I said to propose them "first", it apparently doesn't matter if you propose them as |
Question about that last point, is it possible to combine a built-in completion (suggest all files in the current directory) with candidates from our script ( |
You just add both files and commands to the For example:
The default replies will not be triggered if |
Ok, please let me know how your testing works out. |
Sorry for the repeated force push commands. Is there a command in the picocli distribution itself that can be used to test the completion for subcommands? In any case, my own tests seem to work as expected if you want to verify now. Do you want a separate pull request for removing the inner loop? |
If you have an option that should require an argument, it will propose the subcommand unless it has some explicit types (such as an |
I merged the PR. Thanks very much! (I will add an entry to RELEASE-NOTES.md soon) This discussion also revealed other points where the completion can be further improved:
Correct me if I'm wrong or missed something. |
I think that there should also be an issue about fixing the main For #468, having a mixture isn't so bad because each subcommand is processed separately and the index should be local to each subcommand. Then, we need to offset the main index by one based on whether we have a command or a parameter for the first argument. However, in #461 (comment), I believe that you mentioned a case where the first parameter can be either parameter or a subcommand, so this part may be tricky. I am actually unsure how picocli resolves this case. For example, it currently allows a command of the form |
There is ambiguity, and it’s resolved by matching subcommands first, then options (and parameters) and finally (if it couldn’t be matched to any of these), it must be a positional parameter. |
By the way, |
Nice find! |
I have generated the bash completion script for my command. I have a command that looks like:
command [OPTIONS] FILE...
If I type
$ command <TAB>
I get$ command -
and then hitting TAB twice to get$ command -<TAB><TAB>
lists all of the short and long options. The proposed completions for the command options themselves look correct.However, the completion only ever tries to complete the command options (as they begin with a
-
), and therefore, it never does not get a match and thus never falls back to the default completions.It should be listing the default case which is files/directories and not supply a
-
. It should only try to complete the command options after I manually type a-
(or--
) on the command line. This is how (all) other command completions in bash seem to work.Also, it would be nice to have
--<SPACE>
force it stop completing command options and fall back to the default competitions as this matches the behavior of the actual command.The text was updated successfully, but these errors were encountered: