Вступление
 Picocli — это структура синтаксического анализа командной строки, состоящая из одного файла, которая позволяет создавать приложения командной строки практически без кода.  Аннотируйте поля в вашем приложении с помощью @Option или @Parameters , и picocli заполнит эти поля параметрами командной строки и позиционными параметрами соответственно.  Например: 
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 | @Command(name = "Greet", header = "%n@|green Hello world demo|@")classGreet implementsRunnable {  @Option(names = {"-u", "--user"}, required = true, description = "The user name.")  String userName;  publicvoidrun() {    System.out.println("Hello, "+ userName);  }  publicstaticvoidmain(String... args) {    CommandLine.run(newGreet(), System.err, args);  }} | 
  Когда мы выполняем эту программу, picocli анализирует командную строку и заполняет поле userName перед вызовом метода run : 
| 1 2 3 | $ java Greet -u picocliHello, picocli | 
Picocli создает справочные сообщения об использовании цветов и стилей Ansi . Если мы запустим вышеупомянутую программу с неверным вводом (пропуская обязательную опцию имени пользователя), picocli напечатает ошибку и сообщение помощи использования:
  Picocli может сгенерировать сценарий автозаполнения, который позволяет конечным пользователям использовать завершение командной строки <TAB> чтобы определить, какие параметры и подкоманды доступны.  Вам также может понравиться поддержка picocli для подкоманд и вложенных подкоманд до любого уровня глубины. 
Руководство пользователя подробно описывает функциональные возможности Picocli. В этой статье рассматриваются новые и заслуживающие внимания функции, представленные в выпуске picocli 2.0.
Параметры микширования с позиционными параметрами
Парсер был улучшен, и позиционные параметры теперь можно смешивать с опциями в командной строке.
Ранее позиционные параметры должны были следовать параметрам. В этом выпуске любой аргумент командной строки, который не является опцией или подкомандой, интерпретируется как позиционный параметр.
Например:
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | classMixDemo implementsRunnable {  @Option(names = "-o")  List<String> options;  @Parameters  List<String> positional;  publicvoidrun() {    System.out.println("positional: "+ positional);    System.out.println("options   : "+ options);  }  publicstaticvoidmain(String[] args) {    CommandLine.run(newMixDemo(), System.err, args);  }} | 
Запуск вышеуказанного класса со смесью опций и позиционных параметров показывает, что неопционные параметры распознаются как позиционные параметры. Например:
| 1 2 3 4 | $ java MixDemo param0 -o AAA param1 param2 -o BBB param3positional: [param0, param1, param2, param3]options   : [AAA, BBB] | 
Для поддержки параметров смешивания с позиционными параметрами, синтаксический анализатор был изменен. В Picocli 2.0 многозначные параметры (поля массива, списка и карты) больше не являются жадными по умолчанию . Примечания к выпуску 2.0 подробно описывают это изменение и другие потенциальные критические изменения .
Открытие типов коллекций
Picocli выполняет автоматическое преобразование типов аргументов командной строки в тип аннотированного поля. И именованные параметры, и позиционные параметры могут быть строго типизированы.
  До версии 2.0 Picocli требовал аннотирования полей « Collection и « Map type атрибутом type чтобы можно было выполнять преобразование типов.  Для полей других типов, например полей массива и полей с одним значением, таких как поля int или java.io.File , picocli автоматически определяет тип цели по типу поля, но для коллекций и карт требуется более подробная аннотация.  Например: 
| 1 2 3 4 5 6 7 | classBefore {    @Option(names = "-u", type = {TimeUnit.class, Long.class})    Map<TimeUnit, Long> timeout;    @Parameters(type = File.class)    List<File> files;} | 
  Начиная с версии 2.0, атрибут type больше не требуется для полей Collection и Map : picocli будет выводить тип элемента коллекции из универсального типа.  Атрибут type прежнему работает, как и раньше, в большинстве случаев он не является обязательным. 
  Пропуск атрибута type удаляет некоторое дублирование и приводит к более простому и чистому коду: 
| 1 2 3 4 5 6 7 | classCurrent {    @Option(names = "-u")    Map<TimeUnit, Long> timeout;    @Parameters    List<File> files;} | 
  В приведенном выше примере picocli 2.0 может автоматически обнаруживать, что аргументы командной строки необходимо преобразовать в File перед добавлением их в список, а для карты эти ключи необходимо преобразовать в TimeUnit а значения в Long . 
Автоматическая справка
  Picocli предоставляет ряд удобных методов, таких как run и call которые анализируют аргументы командной строки, заботятся об обработке ошибок и вызывают интерфейсный метод для выполнения приложения. 
  В этом выпуске вспомогательные методы также автоматически usageHelp об использовании и информацию о версии, когда пользователь указывает параметр, usageHelp атрибутом usageHelp или usageHelp в командной строке. 
Пример программы ниже демонстрирует автоматическую помощь:
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | @Command(version = "Help demo v1.2.3", header = "%nAutomatic Help Demo%n",         description = "Prints usage help and version help when requested.%n")classAutomaticHelpDemo implementsRunnable {    @Option(names = "--count", description = "The number of times to repeat.")    intcount;    @Option(names = {"-h", "--help"}, usageHelp = true,            description = "Print usage help and exit.")    booleanusageHelpRequested;    @Option(names = {"-V", "--version"}, versionHelp = true,            description = "Print version information and exit.")    booleanversionHelpRequested;    publicvoidrun() {        // NOTE: code like below is no longer required:        //        // if (usageHelpRequested) {        //     new CommandLine(this).usage(System.err);        // } else if (versionHelpRequested) {        //     new CommandLine(this).printVersionHelp(System.err);        // } else { ... the business logic        for(inti = 0; i < count; i++) {            System.out.println("Hello world");        }    }    publicstaticvoidmain(String... args) {        CommandLine.run(newAutomaticHelpDemo(), System.err, args);    }} | 
  При выполнении с -h или --help программа выводит справку об использовании: 
  Аналогично, при выполнении с -V или --version программа выводит информацию о версии: 
Методы, которые автоматически выводят справку:
- CommandLine :: вызов
- CommandLine :: бежать
- CommandLine :: parseWithHandler (со встроенными обработчиками Run…)
- CommandLine :: parseWithHandlers (со встроенными обработчиками Run…)
Методы, которые не выводят справку автоматически:
- CommandLine :: синтаксического
- CommandLine :: populateCommand
Лучшая поддержка подкоманд
  В этом выпуске добавлены новые CommandLine::parseWithHandler .  Эти методы предлагают ту же простоту использования, что и методы run и call , но с большей гибкостью и лучшей поддержкой вложенных подкоманд. 
Рассмотрим, что должно делать приложение с подкомандами:
- Разбор командной строки.
- Если пользовательский ввод был неверным, распечатайте сообщение об ошибке и справку по использованию для подкоманды, где анализ не удался.
- Если анализ выполнен успешно, проверьте, запрашивал ли пользователь справку об использовании или информацию о версии для команды верхнего уровня или подкоманды. Если это так, распечатайте запрошенную информацию и выйдите.
- В противном случае выполните бизнес-логику. Обычно это означает выполнение наиболее конкретной подкоманды.
Picocli предоставляет некоторые строительные блоки для достижения этой цели, но приложение должно было соединить их вместе. Эта проводка, по сути, является стандартной и очень похожа между приложениями. Например, ранее приложение с подкомандами обычно содержало такой код:
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | publicstaticvoidmain() {    // 1. parse the command line    CommandLine top = newCommandLine(newYourApp());    List<CommandLine> parsedCommands;    try{        parsedCommands = top.parse(args);    } catch(ParameterException ex) {        // 2. handle incorrect user input for one of the subcommands        System.err.println(ex.getMessage());        ex.getCommandLine().usage(System.err);        return;    }    // 3. check if the user requested help    for(CommandLine parsed : parsedCommands) {        if(parsed.isUsageHelpRequested()) {            parsed.usage(System.err);            return;        } elseif(parsed.isVersionHelpRequested()) {            parsed.printVersionHelp(System.err);            return;        }    }    // 4. execute the most specific subcommand    Object last = parsedCommands.get(parsedCommands.size() - 1).getCommand();    if(last instanceofRunnable) {        ((Runnable) last).run();    } elseif(last instanceofCallable) {        Object result = ((Callable) last).call();        // ... do something with result    } else{        thrownewExecutionException("Not a Runnable or Callable");    }} | 
Это довольно много стандартного кода. Picocli 2.0 предоставляет удобный метод, который позволяет вам свести все вышеперечисленное к одной строке кода, чтобы вы могли сосредоточиться на бизнес-логике вашего приложения:
| 1 2 3 4 5 6 7 8 | publicstaticvoidmain() {    // This handles all of the above in one line:    // 1. parse the command line    // 2. handle incorrect user input for one of the subcommands    // 3. automatically print help if requested    // 4. execute one or more subcommands    newCommandLine(newYourApp()).parseWithHandler(newRunLast(), System.err, args);} | 
  Новый удобный метод — parseWithHandler .  Вы можете создать свой собственный обработчик или использовать один из встроенных обработчиков.  Picocli предоставляет реализации обработчиков для некоторых распространенных случаев использования. 
  Встроенными обработчиками являются RunFirst , RunLast и RunAll .  Все они предоставляют автоматическую справку: если пользователь запрашивает UseHelp или VersionHelp, запрашиваемая информация печатается, и обработчик возвращается без дальнейшей обработки.  Обработчики ожидают, что все команды реализуют либо java.lang.Runnable либо java.util.concurrent.Callable . 
-   RunLastвыполняет наиболее конкретную команду или подкоманду. Например, если пользователь вызвалjava Git commit -m "commit message", picocli считаетGitкомандой верхнего уровня и передаст подкоманду. В этом примере подкомандаcommitявляется наиболее конкретной командой, поэтомуRunLastбудет выполнять только эту подкоманду. Если подкоманд нет, выполняется команда верхнего уровня.RunLastтеперь используется внутри Picocli для реализации существующихCommandLine::runиCommandLine::callудобства.
-   RunFirstвыполняет только команду первого , верхнего уровня и игнорирует подкоманды.
-   RunAllвыполняет команду верхнего уровня и все подкоманды, которые появились в командной строке.
  Существует также метод parseWithHandlers , который аналогичен, но дополнительно позволяет указать пользовательский обработчик для неправильного ввода пользователя. 
  Улучшены методы run и call 
  CommandLine::call и CommandLine::run теперь поддерживают подкоманды и будут выполнять последнюю подкоманду, указанную пользователем.  Ранее подкоманды были проигнорированы, и была выполнена только команда верхнего уровня. 
Улучшенные исключения
  Наконец, в этом выпуске все исключения picocli предоставляют метод getCommandLine который возвращает команду или подкоманду, если синтаксический анализ или выполнение не удалось.  Ранее, если пользователь предоставлял неверный ввод для приложений с подкомандами, было трудно точно определить, какая именно подкоманда не смогла проанализировать ввод. 
Вывод
Если вы уже используете Picocli, v2.0 является существенным обновлением. Если вы ранее не пользовались picocli, надеюсь, вышеизложенное заинтересовало вас попробовать.
Многие из этих улучшений возникли в результате отзывов пользователей и последующих обсуждений. Пожалуйста, не стесняйтесь задавать вопросы, запрашивать функции или давать другие отзывы о системе отслеживания проблем picocli.
Пожалуйста, пометьте проект на GitHub, если вам это нравится, и расскажите об этом друзьям!
| Смотрите оригинальную статью здесь: Picocli 2.0: больше с меньшими затратами Мнения, высказанные участниками Java Code Geeks, являются их собственными. | 






