devonfw / ide

Tool to automate setup and update of development environment (esp. for Java projects).
Apache License 2.0
35 stars 101 forks source link

Analyze CLI and capabilities of picocli #1193

Closed hohwille closed 8 months ago

hohwille commented 1 year ago

For #1101 we have chosen picoCLI what seems a nice fit as it works fine with GraalVM and can auto-generate bash completion scripts. However, we are facing problems and limitations: Our current CLI is designed as following:

devon [core-options] [«commandlet» [commandlet-args]]

Examples for core-options are:

Various commandlets act as command-wrapper so they can take arbitrary arguments of the according tool that we do not know and do not want to hard-code.

From this we can look at two simple examples:

$ devon --version
2023.04.001

and in contrast:

$ devon mvn --version
Running: /d/projects/devonfw/software/maven/bin/mvn --version
Apache Maven 3.8.6 (84538c9988a25aec085021c365c560670ad80f63)
Maven home: D:\projects\devonfw\software\maven
Java version: 11.0.17, vendor: Eclipse Adoptium, runtime: D:\projects\devonfw\software\java
Default locale: en_US, platform encoding: UTF-8
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

As you can see, our CLI allows the option --version in different places with different meanings. Tools like PicoCLI do not expect this to happen and do not support this. POSIX standard says that options (e.g. short options like -h or long-options like --help) may occur in any place or order (except after a potential -- argument) and short options may even be combined (so -bfq is the same as -b -f -q). Therefore if we declare --version as option in PicoCLI we can not easily distinguish between the two above cases. To make it even more clear: A command-wrapper just takes any argument that is unknown to him and just delegates this to the according tool:

$ devon mvn banana -apple pie
Running: /d/projects/devonfw/software/maven/bin/mvn banana -apple pie
Unable to parse command line options: Unrecognized option: -apple

usage: mvn [options] [<goal(s)>] [<phase(s)>]

In contrast, picoCLI expects us to specify what options and arguments our CLI does offer so it can automatically do the parsing and also auto-generate the help usage. In the future at some day mvn may introduce arguments like banana -apple pie and without changing our current bash code, we can support this options. Currently, with Java and PicoCLI this is partially prevented. We should analyze what is possible with PicoCLI and how we can "redesign" our CLI to be "compatible" in order to get all working. In the worst case the result is that PicoCLI cannot be used and we have to use something else or implement our own CLI parser (with the need to also implement help output, auto-completion, etc.). If we have to go that way, this is also doable and I have already done it recently in my private time (https://github.com/m-m-m/cli), but if we can stay with picoCLI this would be awesome.

jan-vcapgemini commented 1 year ago

@tobka777 has found this, which might be helpful: https://picocli.info/apidocs/picocli/CommandLine.Parameters.html

Fields annotated with @Parameters will be initialized with positional parameters. By specifying the index() attribute you can pick the exact position or a range of positional parameters to apply. If no index is specified, the field will get all positional parameters (and so it should be an array or a collection).

In the case of command methods (annotated with @Command), method parameters may be annotated with @Parameters, but are are considered positional parameters by default, unless they are annotated with @Option.

from this source: https://www.innoq.com/en/articles/2022/01/java-cli-libraries/#picocli

hohwille commented 8 months ago

We faced several limitations and drawbacks with picocli and implemented our own CLI classes for parsing, autocompletion, etc. that works without deep reflection and is much easier for us to maintain, debug and to get the problems solved. I will close this issue.