Иерархия команд Picocli в JLine

Я использую Pico CLI v4.0.0-alpha-3 и jline v3. У меня есть следующий класс (с использованием аннотаций). Когда я запускаю основной класс, я не могу запустить команду и вызвать вызываемый объект. Я могу вызвать вызываемое, если просто передам параметры.

@CommandLine.Command(name = "Test CLI",
        description = "CLI tool",
        header = "%n@|green test cli |@",
        footer = {"",
                "@|cyan Press Ctrl-D to exit the CLI.|@",
                        ""},
        version = "1.0.0",
        showDefaultValues = true,
        optionListHeading = "@|bold %nOptions|@:%n",
        subcommands = {
                Sync.class,
                Status.class
    })
public class Tester implements Callable<Integer> {

    private static final String PROMPT = "Test CLI> ";

    private LineReaderImpl lineReader;
    private PrintWriter out;


    @Option(names = {"-u", "--username"}, required = true, description = "user name")
    private String userName;

    @Option(names = {"-p", "--password"}, required = true, description = "password")
    private String password;



   final Tester tester = new Tester();
    final CommandLine cmd = prepareCommand(tester);
    final int exitCode = cmd.execute(args);

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

2 ответа

Решение

Утилиты командной строки

Я думаю, что путаница в том, как упаковываются Java-приложения. Если ваше приложение было одним исполняемым файлом, скажем myapp.exe тогда вы бы вызвали приложение из командной строки следующим образом:

myapp -u xxx

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

java -cp mylib.jar com.myorg.MyApp -u xxx

Итак, команда верхнего уровня com.myorg.MyApp сам класс, указывать не нужно myapp в качестве аргумента com.myorg.MyApp класс в командной строке.

Теперь представьте, что ваш myapp Приложение имеет подкоманду под названием sub, Опять же, если бы ваше приложение было одним исполняемым файлом, вы бы вызвали подкоманду в командной строке следующим образом:

myapp sub --subcommand-options

Как Java-класс, вы должны вызывать его, как показано ниже. Обратите внимание, что здесь вам необходимо указать имя подкоманды в качестве аргумента командной строки для com.myorg.MyApp класс:

java -cp mylib.jar com.myorg.MyApp sub --subcommand-options

Примечание: что люди часто делают, это создают сценарии запуска для Windows и Unix, которые позволяют вам выполнять ваше приложение как myapp вместо java -cp mylib.jar com.myorg.MyApp, Одна из причин, по которой люди с энтузиазмом относятся к GraalVM, заключается в том, что собственные изображения GraalVM решают эту проблему упаковки и позволяют разработчикам Java распространять свои приложения в виде одного исполняемого файла.

Основным вариантом использования Picocli является облегчение создания утилит командной строки в Java. Так что это очень легко сделать с помощью следующего кода:

package com.myorg;

@Command(name = "myapp")
public class MyApp implements Runnable {

    @Option(names = {"-u", "--username"}, description = "user name")
    private String userName;

    @Command // subcommand "sub"
    public void sub(@Option(names = "--subcommand-options") String option)  {
        System.out.printf("sub says hello %s!%n", userName);
    }

    @Override
    public void run() {
        System.out.printf("myapp says hi %s!%n", userName);
    }

    public static void main(String[] args) {
        int exitCode = new CommandLine(new MyApp()).execute(args);

    }
}

Интерактивные приложения командной строки

Когда вы создаете интерактивную оболочку CLI с помощью JLine, вам необходимо помнить, что команда верхнего уровня не указана в командной строке.

Поэтому все команды, которые вы хотите, чтобы пользователи могли вводить в оболочке, должны быть подкомандами, как вы описали в своем ответе.

Команда верхнего уровня все еще может быть полезна для оказания помощи пользователям. Одна идея состоит в том, чтобы напечатать дружеское справочное сообщение, за которым следует справка по использованию команды верхнего уровня, когда пользователь вводит недопустимую команду (или просто нажимает ввод без параметров).

Я никогда не мог использовать имя команды, когда терминал CLI был открыт. Я мог бы просто использовать параметры без имени команды.

Я закончил тем, что переместил логику в подкоманду, после чего подкоманда может быть вызвана. Однако теперь CLI отображает предложенную команду как "родительская команда + вспомогательная команда", что, как я вижу, довольно запутанно (и использование этой опции не дает желаемого результата). Я закончил тем, что удалил описание из родительской команды, чтобы позаботиться об этом.

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