picocli :在没有样板的情况下解析参数

picocli : parse arguments without boiler plate

我通常将所有命令行选项存储到不同的 class,例如 CliArguments。这避免了主要 class 中的噪音。这就是我对 picocli:

的看法
public final class MyApp {

    private static final CliArguments cliArgs = new CliArguments();

    private MyApp() {}

    public static void main (String[] args) {
      if (parseArgs (args)) {
         new MyApp().execute();
      }
    }

    /* want to avoid this boiler plate */
    private static boolean parseArgs(String[] args) {
      CommandLine cmd = new CommandLine ( cliArgs );
      try {
        cmd.parseArgs( args );
        if (cmd.isUsageHelpRequested()) {
          cmd.usage( cmd.getOut() );
          return false;
        }
        else if ( cmd.isVersionHelpRequested() ) {
          cmd.printVersionHelp (cmd.getOut());
          return false;
        }
        logger.info("{}", cliArgs);
        return true;
     }
     catch ( ParameterException ex ) {
       logger.error ("Failure to parse : {}", ex);
       return false;
     }
   }

   private void execute() {
     // execution logic
   }
}

如何避免样板方法,pargeArgs(String[])?从技术上讲,CliArguments class 不应实现 CallableRunnable。我可以使 MyApp 成为 CallableRunnable。但是对于 CommandLinenew MyApp() 不是命令,new CliArguments() 是。

如果我想做这样的事情:

   final int exitCode = new CommandLine(new MyApp()).execute(args);
   if (0 != exitCode) {
     logger.error("Failed to parse");
     System.exit(exitCode);
   }

如何将所有 @Option 规范推到不同的 class、CliArguments,同时仍然在 中拥有执行控制权我的应用?

我确定我错过了一些直截了当的东西。

实现此目的的最简单方法是将 CliArguments 设为 MyApp 中的 mixin。然后我们可以将业务逻辑放在 MyApp 中,并使其成为 RunnableCallable 这样我们就可以 bootstrap 具有 new CommandLine(new MyApp()).execute(args) 的应用程序。

例如:

@Command(mixinStandardHelpOptions = true, version = "1.0.0")
public class CliArgs {
    @Option(names = "-x") boolean x;
    @Option(names = "-y") boolean y;
}

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

    // options defined in the mixin are added to this command
    // also, @Command attributes from the mixin are applied to this command
    @Mixin
    CliArgs cliArgs;

    public void run() {
        System.out.printf("-x=%s%n", cliArgs.x);
        System.out.printf("-y=%s%n", cliArgs.y);
    }

    public void main(String... args) {
        System.exit(new CommandLine(new MyApp()).execute(args));
    }
}

CliArgs mixin 中定义的选项成为 MyApp mixee 的一部分。 此外,在 CliArgs 中定义的任何 @Command 属性都会成为 MyApp 命令的一部分。

您现在可以 运行:

java MyApp -x

这将打印

-x=true
-y=false

因为 mixin 有 @Command(mixinStandardHelpOptions = true)MyApp 命令也有 --help--version 选项,可以如你所愿。