显示多个命令用法的 picocli 示例

picocli example showing the usage of multiple commands

我得到了一些与 picocli 配合得很好的代码:

 @Command(name = "parse", sortOptions = false, description = "parse input files and write to database")
class CommandLineArgumentParser {


@Option(names = { "-h", "--help" }, usageHelp = true, description = "display this message")
private boolean helpRequested = false;


@Option(names = { "-s", "--startDate"}, description = "First day at which to parse data",
        converter = GermanDateConverter.class, paramLabel = "dd.MM.yyyy")
public LocalDate start;

@Option(names = { "-e", "--endDate"}, description = "Last day (inclusive) at which to stop parsing",
        converter = GermanDateConverter.class, paramLabel = "dd.MM.yyyy")
public LocalDate end;


private static class GermanDateConverter implements ITypeConverter<LocalDate> {
    @Override
    public LocalDate convert(String value) throws Exception {
        LocalDate result = null;

            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
            result = LocalDate.parse(value, formatter);
            if (result.getYear() < 1900) {
                throw new IllegalArgumentException("year should be after 1900");
            }
        return result;
    }
}


@SpringBootApplication
public class Application implements CommandLineRunner {

public void run(String... args) throws Exception {
    CommandLineArgumentParser commandlineparser = new CommandLineArgumentParser();

    CommandLine commandLine = new CommandLine(commandlineparser);
    try {
        commandLine.parseArgs(args);

    } catch (MissingParameterException e) {
        System.out.println(e);
        System.out.println();
        CommandLine.usage(CommandLineArgumentParser.class, System.out);
        System.exit(1);
    } catch (ParameterException e) {
        System.out.println(e);
        System.out.println();
        CommandLine.usage(CommandLineArgumentParser.class, System.out);
        System.exit(1);
    }

    if (commandLine.isUsageHelpRequested()) {
        commandLine.usage(System.out);
        return;
    } else if (commandLine.isVersionHelpRequested()) {
        commandLine.printVersionHelp(System.out);
        return;
    }

    if (commandlineparser.start == null) {
        log.warn("no start date specified, using: 01.01.2005");
        commandlineparser.start = LocalDate.of(2005, 01, 01);
    }

    if (commandlineparser.end == null) {
        LocalDate timePoint = LocalDate.now();
        log.warn("no end date specified, using today: " + timePoint.toString());
        commandlineparser.end = timePoint;
    }
}

但我没有找到一个简单的示例来显示使用的多个命令,例如这个:
https://github.com/remkop/picocli/blob/master/src/test/java/picocli/Demo.java

不编译:

int exitCode = new CommandLine(new Demo()).execute(args);

The method execute(CommandLine, List<Object>) in the type CommandLine is not applicable for the    arguments (String[])

有人可以 post 一个关于如何使用多个命令的例子吗?

我怀疑您使用的是旧版本的库。 execute(String []) : int 方法是在 picocli 4.0 中引入的。

升级并使用 execute 方法而不是 parseArgs 方法将允许您从应用程序中删除大量样板代码:处理对 usage/version 帮助的请求和处理使用 execute 方法自动完成无效输入。

您的命令应该实现 Runnable 或 Callable,这是每个命令的业务逻辑所在。

修改你的例子并给它一个 subcommand:

@Command(name = "parse", sortOptions = false,
        mixinStandardHelpOptions = true, version = “1.0”,
        description = "parse input files and write to database",
        subcommands = MySubcommand.class)
class CommandLineArgumentParser implements Callable<Integer> {

    @Option(names = { "-s", "--startDate"}, description = "First day at which to parse data",
            converter = GermanDateConverter.class, paramLabel = "dd.MM.yyyy")
    public LocalDate start;

    @Option(names = { "-e", "--endDate"}, description = "Last day (inclusive) at which to stop parsing",
            converter = GermanDateConverter.class, paramLabel = "dd.MM.yyyy")
    public LocalDate end;


    private static class GermanDateConverter implements ITypeConverter<LocalDate> {
        @Override
        public LocalDate convert(String value) throws Exception {
            LocalDate result = null;

                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
                result = LocalDate.parse(value, formatter);
                if (result.getYear() < 1900) {
                    throw new IllegalArgumentException("year should be after 1900");
                }
            return result;
        }
    }

    @Override
    public Integer call() {
        if (start == null) {
            log.warn("no start date specified, using: 01.01.2005");
            start = LocalDate.of(2005, 01, 01);
        }

        if (end == null) {
            LocalDate timePoint = LocalDate.now();
            log.warn("no end date specified, using today: " + timePoint.toString());
            end = timePoint;
        }

        // more business logic here ...

        // add finally return an exit code 
        int exitCode = ok ? 0 : 1;
        return exitCode;
    }
}

@Command(name = "foo")
class MySubcommand implements Callable<Integer> {
    @Override
    public Integer call() {
        System.out.println("hi");
        return 0;
    }
}


@SpringBootApplication
public class Application implements CommandLineRunner {

    public void run(String... args) throws Exception {
        int exitCode = new CommandLine(
                CommandLineArgumentParser.class,
                new picocli.spring.PicocliSpringFactory())
                .execute(args);
        System.exit(exitCode);
     }
}

请注意,当Spring与picocli子命令结合使用时,您需要使用picocli.spring.PicocliSpringFactory调用CommandLine构造函数。

有关更完整的 Spring 示例,请参阅 picocli-spring-boot-starter 自述文件。