How can I handle errors in picocli?

Okumo :

I try to implement my own CLI and want to use picocli for parsing my commands' arguments. That's why I don't want picocli to write in console at all. So I created class MyCommand with some option and parameters annotations. Now I want to be able to do something like this:

val myCommand = CommandLine.populateCommand(MyCommand(), args)
myCommand.execute();
val output = myCommand.getOutput();
val errors: List<String> = myCommand.getErrors();

There is no problems with the first three lines, but I am not sure how to deal with the fourth. Now populateCommand just throws all exceptions, and catching them is not an option, because thrown exception will stop my pipeline computations. Picocli documentation suggests to use parser lenient mode for exceptions to be stored in ParseResult, but it means I have to use commandLine.parseWithHandlers method that is hard to use for my needs.
Am I missing something? Maybe I sill can use populateCommand and have exception stored in some place?
Here is stacktrace for one of exceptions that populateCommand throws:

Exception in thread "main" picocli.CommandLine$MissingParameterException: Missing required parameter for option '-A' (<afterContext>)
    at picocli.CommandLine$Interpreter.assertNoMissingParameters(CommandLine.java:8059)
    at picocli.CommandLine$Interpreter.applyOption(CommandLine.java:7534)
    at picocli.CommandLine$Interpreter.processStandaloneOption(CommandLine.java:7446)
    at picocli.CommandLine$Interpreter.processArguments(CommandLine.java:7355)
    at picocli.CommandLine$Interpreter.parse(CommandLine.java:7226)
    at picocli.CommandLine$Interpreter.parse(CommandLine.java:7116)
    at picocli.CommandLine.parse(CommandLine.java:824)
    at picocli.CommandLine.populateCommand(CommandLine.java:777)
Remko Popma :

Ignoring parsing errors is unusual, but can be useful when creating your own interactive CLI console, as opposed to a single command. My answer assumes this is what you have in mind.

One idea is to use the parseArgs method instead of the populateCommand method. This method returns a ParseResult from which you can obtain the errors that picocli encountered during parsing, if you’ve configured the parser to be lenient.

For example:

val myCommand = MyCommand();
val commandLine = CommandLine(myCommand);

// tell parser to be lenient 
commandLine.getCommandSpec().parser().collectErrors(true);

// parse user input, query result for errors 
val parseResult = commandLine.parseArgs(args); 
val parseErrors: List<Exception> = parseResult.errors();

// ignoring the errors for now...
myCommand.execute();
val output = myCommand.getOutput();
val appErrors: List<String> = myCommand.getErrors();

Note that if there are any parsing errors, this means that the user specified invalid input. As a result, your command may not have been correctly initialized. The execute method needs to be extra robust to deal with partially initialized options/positional parameters.

TIP: If you are creating your own interactive CLI console (as opposed to a single command), you may be interested in JLine 2 (requires Java 5 or higher) or JLine 3 (requires Java 8 or higher). Picocli provides picocli-shell-jline2 and picocli-shell-jline3 modules that have a PicocliJLineCompleter that shows context-sensitive completion candidates for picocli commands. (The readme of each module has an example.) Applications that use picocli to define their commands no longer need to hand-code Completers for their commands and options. (An early version of this is used in the Micronaut CLI.)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=106619&siteId=1