Как я могу обработать ошибки в picocli?

Я пытаюсь реализовать свой собственный CLI и хочу использовать picocli для анализа аргументов моих команд. Вот почему я не хочу, чтобы Picocli писал в консоли вообще. Итак, я создал класс 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)

1 ответ

Решение

Игнорирование ошибок синтаксического анализа является необычным, но может быть полезно при создании вашей собственной интерактивной консоли CLI, в отличие от одной команды. Мой ответ предполагает, что это то, что вы имеете в виду.

Одна идея состоит в том, чтобы использовать parseArgs метод вместо populateCommand метод. Этот метод возвращает 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();

Обратите внимание, что если есть какие- либо ошибки синтаксического анализа, это означает, что пользователь указал неверный ввод. В результате ваша команда может быть неправильно инициализирована. execute Метод должен быть очень устойчивым, чтобы иметь дело с частично инициализированными опциями / позиционными параметрами.

СОВЕТ: Если вы создаете свою собственную интерактивную консоль CLI (в отличие от одной команды), вас может заинтересовать JLine 2 (требуется Java 5 или выше) или JLine 3 (требуется Java 8 или выше). Picocli предоставляет модули picocli-shell-jline2 и picocli-shell-jline3, которые имеют PicocliJLineCompleter который показывает контекстно-зависимые кандидаты на завершение для команд picocli. (В файле readme каждого модуля есть пример.) Приложения, использующие picocli для определения своих команд, больше не нуждаются в ручном кодировании Completers для своих команд и опций. (Ранняя версия этого используется в CLI Micronaut.)

Другие вопросы по тегам