picocli
picocli copied to clipboard
access unmatched options as map
maybe this is already possible but I didn't see it, I'd like to be able to access all options passed, or maybe just the ones not configured with picocli. I'm developing a scaffolding system inspired by hygen. hygen allows you to define variables on the command line, it automatically generates?/parses those command line parameters and stuffs them into a javascript object. What I'd like is to be able to do is something like this on my picocli class. I can probably do this with a programatic spec, however, I'm still not certain if I can combine the 2 styles, and if I need to do this with programmatic I would prefer to combine the styles.
@Options( unrecognizedOnly = true )
Map<String, String> options = new HashMap<>();
There is a list-like facility for unmatched parameters: see Unmatched Input.
The easiest way to use this is with the @Unmatched
annotation:
class MyApp {
@Unmatched
List<String> unmatched;
}
hmm.... but what would this produce in the array?
--foo bar --baz=fun
I suspect (but haven't tried, sorry)
["--foo", "bar", "--baz=fun"]
which means I'd have to go about parsing this array myself. What I'd like is
{
"foo": "bar",
"baz": "fun"
}
this way I could do
@Unmatched( options = true, stripDashes=true )
Map<String, String> options;
Map<String, Object> context = new HashMap<>();
context.putAll( Map.of( "args", args, "name", name ) ); // comes from parameters
context.putAll( e.getValue().getContext() ); // comes from a config file
context.putAll( options ); // allow overriding anything
the context which is then passed to a template parser
I also wonder given the documentation... since I already have positional parameters, and one is a ..*
all parameters, how this would impact that, especially if you put the option after the parameters.
Yes, if you have a positional parameter list or array defined that captures all indices, then the @Unmatched
list will only contain "unknown options": args that "resemble" options but are not defined as picocli @Option
options.
The exact behaviour can be controlled with parser configuration like setStopAtUnmatched, setUnmatchedArgumentsAllowed , and setUnmatchedOptionsArePositionalParams.
I suspect that in the example you provided, the @Unmatched
list would end up containing ["--foo", "--baz=fun"]
, while "bar"
would be added to the positional parameters list.
So, overall, picocli currently does not provide the facility to parse the unmatched arguments. Note that it is not trivial to impose structure on this list; for example, some apps would want bar
to be interpreted as a parameter for --foo
, while others may want --foo
to have zero parameters and treat bar
as a standalone (positional) parameter. Yet other apps may want to treat --foo
as an option with 2 parameters, the first one being bar
, and the second param being --baz=fun
. All these are valid interpretations, depending on the app.
Things get even trickier if the end user specifies "unmatched" arguments intermingled with "defined" options and their parameters.
Are you interested in providing a pull request for this?
maybe, we'll see, this particular feature isn't urgent for me, it's another nice to have, eventually that may change as I don't really have a great workaround for this feature that's not basically equivalent to implementing it. I can definitely see what you're saying about the trickiness though.
ugh, I actually may need this in order for my stuff to actually work right :/ so you may get your wish :/