Статьи

Picocli 2.0: отличные скрипты на стероидах

В Picocli 2.0 добавлена ​​улучшенная поддержка других языков JVM, особенно Groovy. Зачем использовать picocli, когда язык Groovy имеет встроенную поддержку CLI с классом CliBuilder ?

Вам может понравиться справка по использованию Picocli, которая по умолчанию показывает цвета и стили ANSI. Еще одна особенность, которая вам может понравиться — это автозаполнение TAB из командной строки. Наконец, есть множество мелких функций, таких как тот факт, что вашему сценарию требуется ноль строк кода синтаксического анализа командной строки, поддержка подкоманд Picocli, преобразование типов для параметров и позиционных параметров и трассировка синтаксического анализатора .

пример

Давайте посмотрим на пример. Приведенный ниже скрипт checkum.groovy принимает один или несколько параметров файла и для каждого файла выводит контрольную сумму и имя файла. Алгоритм «контрольной суммы» по умолчанию является MD5, но пользователи могут указать другой алгоритм MessageDigest. Пользователи могут запросить помощь по использованию с опцией -h или --help .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
@Grab('info.picocli:picocli:2.0.3')
@picocli.groovy.PicocliScript
import groovy.transform.Field
import java.security.MessageDigest
import static picocli.CommandLine.*
 
@Parameters(arity="1", paramLabel="FILE", description="The file(s) whose checksum to calculate.")
@Field File[] files
 
@Option(names = ["-a", "--algorithm"], description = [
        "MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512,",
        "  or any other MessageDigest algorithm."])
@Field String algorithm = "MD5"
 
@Option(names= ["-h", "--help"], usageHelp= true, description= "Show this help message and exit.")
@Field boolean helpRequested
 
files.each {
  println MessageDigest.getInstance(algorithm).digest(it.bytes).encodeHex().toString() + "\t" + it
}

При запуске в $picocli-home/examples/src/main/groovy/picocli/examples этот скрипт примера дает следующие результаты:

1
2
3
4
$ groovy checksum.groovy *.*
4995d24bbb3adf67e2120c36dd3027b7        checksum.groovy
a03c852de017f9303fcc373c7adafac6        checksum-with-banner.groovy
1ee567193bf41cc835ce76b6ca29ed30        checksum-without-base.groovy

Вызов сценария с параметром -h или --help показывает сообщение справки об использовании с цветами и стилями ANSI ниже:

Где код?

Возможно, вы заметили, что приведенный выше скрипт не содержит никакой логики для разбора аргументов командной строки или для обработки запросов на помощь по использованию.

Без аннотации @picocli.groovy.PicocliScript код сценария будет выглядеть примерно так:

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
class Checksum {
    @Parameters(arity = "1", paramLabel = "FILE", description = "...")
    File[] files
 
    @Option(names = ["-a", "--algorithm"], description = ["..."])
    String algorithm = "MD5"
 
    @Option(names = ["-h", "--help"], usageHelp = true, description = "...")
    boolean helpRequested
}
Checksum checksum = new Checksum()
CommandLine commandLine = new CommandLine(checksum)
try {
    commandLine.parse(args)
    if (commandLine.usageHelpRequested) {
        commandLine.usage(System.out)
    } else {
        checksum.files.each {
            byte[] digest = MessageDigest.getInstance(checksum.algorithm).digest(it.bytes)
            println digest.encodeHex().toString() + "\t" + it
        }
    }
} catch (ParameterException ex) {
    println ex.message
    commandLine.usage(System.out)
}

В приведенном выше примере есть явный код для разбора командной строки, обработки неправильного ввода пользователя и проверки запросов на помощь по использованию. Первая версия скрипта не имела такого стандартного кода.

Давайте посмотрим, как это работает.

BaseScript

Скрипты, аннотированные @picocli.groovy.PicocliScript , автоматически преобразуются для использования picocli.groovy.PicocliBaseScript качестве базового класса. Это превращает скрипт Groovy в приложение командной строки на основе picocli.

Когда скрипт запускается, Groovy вызывает метод run скрипта. Метод PicocliBaseScript::run заботится о разборе командной строки и PicocliBaseScript::run полей скрипта результатами. Метод run делает следующее:

  • Сначала переменные @Field аннотированные @Option или @Parameters , инициализируются из аргументов командной строки.
  • Если пользовательский ввод был неверным, печатается сообщение об ошибке, сопровождаемое сообщением помощи использования.
  • Если пользователь запросил справку по использованию или информацию о версии, она выводится на консоль и сценарий завершается.
  • В противном случае тело скрипта выполняется.

Это поведение можно настроить, см. Подробности в javadoc PicocliBaseScript .

Помимо изменения базового класса сценария, аннотация @PicocliScript также позволяет сценариям Groovy напрямую использовать аннотацию @Command без введения вспомогательного класса. Парсер picocli будет искать эту аннотацию в классе, содержащем аннотированные поля @Option и @Parameters . То же пользовательское преобразование AST, которое изменяет базовый класс сценария, также перемещает любую аннотацию @Command в сценарии в этот преобразованный класс, чтобы анализатор picocli мог его забрать.

Справка по использованию с цветами

Аннотация @Command позволяет настраивать части справочного сообщения об использовании, такие как имя команды, описание, верхние и нижние колонтитулы и т. Д.

Давайте добавим несколько наворотов в пример сценария. (Благодарим http://patorjk.com/software/taag/ за ASCII Art Generator.)

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
34
35
36
@Grab('info.picocli:picocli:2.0.3')
@Command(header = [
        $/@|bold,green    ___                            ___ _           _                  |@/$,
        $/@|bold,green   / __|_ _ ___  _____ ___  _     / __| |_  ___ __| |__ ____  _ _ __  |@/$,
        $/@|bold,green  | (_ | '_/ _ \/ _ \ V / || |   | (__| ' \/ -_) _| / /(_-< || | '  \ |@/$,
        $/@|bold,green   \___|_| \___/\___/\_/ \_, |    \___|_||_\___\__|_\_\/__/\_,_|_|_|_||@/$,
        $/@|bold,green                         |__/                                         |@/$
        ],
        description = "Print a checksum of each specified FILE.",
        version = 'checksum v1.2.3', showDefaultValues = true,
        footerHeading = "%nFor more details, see:%n",
                "ASCII Art thanks to http://patorjk.com/software/taag/"]
)
@picocli.groovy.PicocliScript
import groovy.transform.Field
import java.security.MessageDigest
import static picocli.CommandLine.*
 
@Parameters(arity="1", paramLabel="FILE", description="The file(s) whose checksum to calculate.")
@Field private File[] files
 
@Option(names = ["-a", "--algorithm"], description = [
        "MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512, or",
        "  any other MessageDigest algorithm. See [1] for more details."])
@Field private String algorithm = "MD5"
 
@Option(names= ["-h", "--help"], usageHelp=true, description="Show this help message and exit.")
@Field private boolean helpRequested
 
@Option(names= ["-V", "--version"], versionHelp=true, description="Show version info and exit.")
@Field private boolean versionInfoRequested
 
files.each {
  println MessageDigest.getInstance(algorithm).digest(it.bytes).encodeHex().toString() + "\t" + it
}

В новой версии скрипта добавлены верхний и нижний колонтитулы, а также возможность распечатывать информацию о версии. Весь текст, отображаемый в справочном сообщении об использовании и информации о версии, может содержать спецификаторы формата, такие как разделитель строк %n .

Справочное сообщение об использовании также может отображать цвета и стили ANSI. Picocli поддерживает простой синтаксис разметки, где @| начинает раздел в стиле ANSI, а |@ завершает его. Сразу после @| список цветов и стилей через запятую, например @|STYLE1[,STYLE2]…​ text|@ . См. Руководство пользователя picocli для получения подробной информации о доступных цветах и ​​стилях.

Сообщение об использовании нового скрипта выглядит следующим образом:

Аннотация @Command также имеет атрибут version = "checksum v1.2.3" . Эта строка версии печатается, когда пользователь указывает --version в командной строке, потому что мы объявили @Option с этим именем с атрибутом versionHelp = true .

1
2
$ groovy checksum-with-banner.groovy --version
checksum v1.2.3

Для получения дополнительной информации см. Раздел справки по версии руководства пользователя.

Вывод

Аннотация @PicocliScript позволяет сценариям Groovy пропускать шаблонный код и одновременно добавлять мощные общие функциональные возможности приложения командной строки. В финальной версии нашего примера сценария большая часть кода на самом деле представляет собой текст описания сообщения об использовании.

Существует много других возможностей для пикокли, попробуйте!

Пожалуйста, пометьте проект на GitHub, если вам это нравится, и расскажите об этом друзьям!

Смотреть оригинальную статью здесь: Picocli 2.0: Groovy Scripts на стероидах

Мнения, высказанные участниками Java Code Geeks, являются их собственными.