Пикокли: Можно ли определить параметры с пробелом в имени? - PullRequest
1 голос
/ 14 апреля 2020

Я немного погуглил, а также искал в StackOverflow и, конечно, в документах Picocli, но не нашел решения.

Компания, в которой я работаю, использует специальный формат для параметров командной строки в пакетном режиме. программы:

-VAR ARGUMENT1=VALUE -VAR ARGUMENT2=VALUE2 -VAR BOOLEANARG=FALSE

(Не спрашивайте меня, почему этот формат используется, я уже задал вопрос и не получил правильный ответ.) Теперь я хотел использовать Picocli для анализа командной строки. Однако я не могу заставить его работать с форматом параметров, который мы используем, потому что пробел заставляет Picocli думать, что это два отдельных аргумента, и поэтому он не распознает их как те, которые я определил.

Это выиграно не работает, очевидно:

@CommandLine.Option( names = { "-VAR BOOLEANARG" } )
boolean booleanarg = true;

Вызов программы с параметром -VAR BOOLEANARG = FALSE не даст никакого эффекта.

Есть ли способ пользовательского определения этих имен специальных опций, содержащих пробелы ? Или как бы я go об этом? Мне также не разрешено сворачивать несколько аргументов в качестве параметров в один параметр -VAR.

Помощь очень ценится. Спасибо и всего наилучшего, Роза

1 Ответ

0 голосов
/ 15 апреля 2020

Решение 1: Вариант карты

Самое простое решение - сделать -VAR a Параметр карты . Это может выглядеть примерно так:

@Command(separator = " ")
class Simple implements Runnable {

    enum MyOption {ARGUMENT1, OTHERARG, BOOLEANARG}

    @Option(names = "-VAR",
            description = "Variable options. Valid keys: ${COMPLETION-CANDIDATES}.")
    Map<MyOption, String> options;

    @Override
    public void run() {
        // business logic here
    }

    public static void main(String[] args) {
        new CommandLine(new Simple()).execute(args);
    }
}

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

Usage: <main class> [-VAR <MyOption=String>]...
      -VAR <MyOption=String>
         Variable options. Valid keys: ARGUMENT1, OTHERARG, BOOLEANARG.

Обратите внимание, что в этом решении все значения будут иметь одинаковый тип (String в этом примере), и вам может потребоваться преобразовать в нужный тип (boolean, int, другие ...) в приложении.

Однако, это может быть неприемлемо, учитывая это предложение в вашем посте:

Мне также не разрешено сворачивать несколько аргументов в качестве параметров в один параметр -VAR.

Решение 2: Группы аргументов

Одной из идей альтернативы является использование групп аргументов : мы можем сделать ARGUMENT1, OTHERARG и BOOLEANARG отдельными опциями и поместить их в группу так, чтобы они должны предшествует опция -VAR.

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

Usage: group-demo [-VAR (ARGUMENT1=<arg1> | OTHERARG=<otherValue> |
                  BOOLEANARG=<bool>)]... [-hV]
      -VAR                   Option prefix. Must be followed by one of
                               ARGUMENT1, OTHERARG or BOOLEANARG
      ARGUMENT1=<arg1>       An arg. Must be preceded by -VAR.
      OTHERARG=<otherValue>  Another arg. Must be preceded by -VAR.
      BOOLEANARG=<bool>      A boolean arg. Must be preceded by -VAR.
  -h, --help                 Show this help message and exit.
  -V, --version              Print version information and exit.

И реализация может выглядеть примерно так:

@Command(name = "group-demo", mixinStandardHelpOptions = true,
        sortOptions = false)
class UsingGroups implements Runnable {

    static class MyGroup {
        @Option(names = "-VAR", required = true,
          description = "Option prefix. Must be followed by one of ARGUMENT1, OTHERARG or BOOLEANARG")
        boolean ignored;

        static class InnerGroup {
            @Option(names = "ARGUMENT1", description = "An arg. Must be preceded by -VAR.")
            String arg1;

            @Option(names = "OTHERARG", description = "Another arg. Must be preceded by -VAR.")
            String otherValue;

            @Option(names = "BOOLEANARG", arity = "1",
              description = "A boolean arg. Must be preceded by -VAR.")
            Boolean bool;
        }

        // exclusive: only one of these options can follow a -VAR option
        // multiplicity=1: InnerGroup must occur once
        @ArgGroup(multiplicity = "1", exclusive = true)
        InnerGroup inner;
    }


    // non-exclusive means co-occurring, so if -VAR is specified,
    // then it must be followed by one of the InnerGroup options
    @ArgGroup(multiplicity = "0..*", exclusive = false)
    List<MyGroup> groupOccurrences;

    @Override
    public void run() {
        // business logic here

        System.out.printf("You specified %d -VAR options.%n", groupOccurrences.size());
        for (MyGroup group : groupOccurrences) {
            System.out.printf("ARGUMENT1=%s, ARGUMENT2=%s, BOOLEANARG=%s%n",
                    group.inner.arg1, group.inner.arg2, group.inner.arg3);
        }
    }

    public static void main(String[] args) {
        new CommandLine(new UsingGroups()).execute(args);
    }
}

Затем вызов с помощью java UsingGroups -VAR ARGUMENT1=abc -VAR BOOLEANARG=true дает:

You specified 2 -VAR options.
ARGUMENT1=abc, OTHERARG=null, BOOLEANARG=null
ARGUMENT1=null, OTHERARG=null, BOOLEANARG=true

С этим ок. О, вы получите объект MyGroup каждый раз, когда конечный пользователь указывает -VAR. Этот MyGroup объект имеет InnerGroup, который имеет много полей, всех, кроме одного из которых будет null. Только поле, указанное пользователем, будет не null. В этом недостаток этого подхода: в приложении вам нужно будет проверить все поля, чтобы найти не-1053 *, указанное пользователем. Преимущество заключается в том, что при выборе правильного типа для поля, помеченного @Option, значения будут автоматически преобразованы в тип назначения.

...