如何处理 picocli 中的错误?

How can I handle errors in picocli?

我尝试实现我自己的 CLI 并想使用 picocli 来解析我的命令的参数。这就是为什么我根本不想让 picocli 在控制台中写入。所以我用一些选项和参数注释创建了 class MyCommand。现在我希望能够做这样的事情:

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

前三行没有问题,但我不知道如何处理第四行。现在 populateCommand 只是抛出所有异常,捕获它们不是一种选择,因为抛出的异常会停止我的管道计算。 Picocli 文档建议使用解析器宽松模式将异常存储在 ParseResult 中,但这意味着我必须使用 commandLine.parseWithHandlers 方法,这很难满足我的需要。
我错过了什么吗?也许我仍然可以使用 populateCommand 并将异常存储在某个地方?
这是 populateCommand 抛出的异常之一的堆栈跟踪:

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)

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.

一个想法是使用 parseArgs 方法而不是 populateCommand 方法。此方法 returns a ParseResult 如果您已将解析器配置为宽松,您可以从中获取 picocli 在解析过程中遇到的错误。

例如:

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.

提示:如果您要创建自己的 interactive CLI 控制台(而不是单个命令),您可能会对 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.)