Detect which flags were defined in the command line

14 views
Skip to first unread message

Andres Almiray

unread,
Jan 26, 2023, 4:24:33 PM1/26/23
to picocli
Hello everyone!

I've got the following use case:

The next major release of JReleaser will remove several flags. I'd like to give ample warning to users so that they can migrate to replacement flags. For this reason, I'm looking at a way to detect that the old/deprecated flag was actually used and suggest the new one.

For example given the following flag definition:

```
@CommandLine.Option(names = {"-d", "--distribution"},
paramLabel = "<distribution>")
String[] includedDistributions;
```

If a user sets "-d" then I'd like to print out a message stating that flag is deprecated and "--distribution" should be used instead.

Any hints will be greatly appreciated.

Cheers,
Andres

Pedro Lamarão

unread,
Jan 26, 2023, 4:26:17 PM1/26/23
to Andres Almiray, picocli
Hello!
You could put @Option(names={"--distribution"} on a setter method, and define this method as 1. warn 2. set the option.
Cheers!

--
You received this message because you are subscribed to the Google Groups "picocli" group.
To unsubscribe from this group and stop receiving emails from it, send an email to picocli+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/picocli/b3b35783-9822-4d20-b1bf-8a932cfe9156n%40googlegroups.com.


--
Pedro Lamarão
Securing Critical Systems

Antes de imprimir esta mensagem e seus anexos, certifique-se que seja realmente necessário.
Proteger o meio ambiente é nosso dever.
Before printing this e-mail or attachments, be sure it is necessary.
It is in our hands to protect the environment.

Andres Almiray

unread,
Jan 26, 2023, 4:48:56 PM1/26/23
to picocli
Thanks Pedro, an annotated method would let me hook in the validation I want to put in place. However, I still don't see how I'll be able to detect that the "-d" flag was used instead of "--distribution".

As I understand the method would have to be defined as

```
@CommandLine.Option(names = {"-d", "--distribution"},
     paramLabel = "<distribution>")
    public void setIncludedDistributions(String[] distributions) {
         // somehow find out if -d was used and print out a warning
         // ???
     this.includedDistributions = distributions;
}
```

Pedro Lamarão

unread,
Jan 26, 2023, 6:04:33 PM1/26/23
to Andres Almiray, picocli
Sorry, I got your requirement confused. If you want to deprecated  "-d", put that on the setter only, then put "--distribution" directly on the option. If the user opts for "--distribution", Picocli will assign directly on the attribute. If she opts for "-d", Picocli will call the setter method. Caveat not tested! Cheers!

Andres Almiray

unread,
Jan 26, 2023, 6:20:51 PM1/26/23
to picocli
Gotcha. Unfortunately it's not enough at least for arrays as setting the field value overrides whatever value may have been set previously by the method and viceversa.
I suppose this technique is OK for scalar values (numbers, strings, booleans, paths) but will fail for arrays and collections :'(

This is what I did, perhaps I'm missing something

```
@CommandLine.Option(names = {"--packager"},
    paramLabel = "<packager>")
String[] includedPackagers;

@CommandLine.Option(names = {"-p"},
    paramLabel = "<packager>")
public void setIncludedPackagers(String[] includedPackagers) {
    System.out.println("Use --packager instead");
    this.includedPackagers = includedPackagers;
}
```

Cheers,
Andres

picocli

unread,
Jan 26, 2023, 9:51:33 PM1/26/23
to picocli
Hi Andres,

It is possible to query the ParseResult for the list of Strings that were just parsed, via the expandedArgs and originalArgs methods.

See this example class:

Example execution:

picocli.examples.parseresult.ParseResultDemo -x 123 --y-long 456

ExpandedArgs: [-x, 123, --y-long, 456]                      
OriginalArgs: [-x, 123, --y-long, 456]                      
--x-long was specified: true                                
-x=123 (-1 means this option was not matched on command line)
--x-long=123 (arg value or default)                                                                                 
(...)

You can then see if this list contains the short name of the option.

This is not 100% watertight; it is theoretically possible that the short name of the option is in the argument list as a parameter, 
but picocli currently does not track which of the option names was actually matched on the command line,
so this is the best we can do with the current version of picocli. 

Andres Almiray

unread,
Jan 27, 2023, 9:36:07 AM1/27/23
to picocli
Thank you Remko!

The answer was staring at me the whole time -> https://picocli.info/#_was_a_value_defaulted

That section of the docs links to the full example you mentioned.
I should have looked further into the docs, I knew this was possible, somehow 😅

Cheers,
Andres
Reply all
Reply to author
Forward
0 new messages