【问题标题】:picocli example showing the usage of multiple commands显示多个命令用法的 picocli 示例
【发布时间】:2019-09-27 11:35:16
【问题描述】:

我得到了一些与 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[])

有人可以发布一个关于如何使用多个命令的示例吗?

【问题讨论】:

    标签: picocli


    【解决方案1】:

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

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

    您的命令应该实现 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);
         }
    }
    

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

    有关更完整的 Spring 示例,请参阅picocli-spring-boot-starter README。

    【讨论】:

    • 所以我可以运行:java -jar target/jsontest2-0.0.1-SNAPSHOT.jar foo - 按预期打印 hi。但是使用 parse 运行会打印:索引 0 处的不匹配参数:'parse' - 因为既不需要开始也不需要结束,我希望看到以下行:“没有指定开始日期,使用:01.01.2005”,另一个用于结束...?
    • 该示例定义了一个--startDate 和一个--endDate 选项,以及一个foo 子命令。如果您传入的参数与其中任何一个都不匹配(例如字符串 parse),那么 picocli 会认为此无效输入并显示错误消息。您可以使用 CommandLine.setUnmatchedArgumentsAllowed 方法告诉 picocli 忽略此类无效参数。见picocli.info/#_unmatched_input。或者,您可以通过在选项之外定义 positional parameters 来捕获这些参数。
    • 但是 @Command(name = "parse"...) 和 @Command(name = "foo") 定义的方式相同,只是解析得到了一些可以与之配套的参数?
    • 哦,我明白你的意思了。您在问为什么不需要在命令行上指定顶级命令的名称。这个想法是,您可以将 java -jar myjar.jar 调用包装在名为 parse 的脚本中,或者使用 GraalVM 将您的 CLI 应用程序编译为名为 parse 的本机映像。之后,用户可以使用parse foo 调用您的程序。 (而且您不想要求他们输入parse parse foo。)
    • 没错,感谢您的解释以及在 stackoverflow 上支持您自己的软件。
    猜你喜欢
    • 2019-10-24
    • 1970-01-01
    • 1970-01-01
    • 2019-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-14
    相关资源
    最近更新 更多