picocli : анализировать аргументы без шаблона

Обычно я храню все параметры командной строки в другом классе, например CliArguments. Это позволяет избежать шума в основном классе. Вот что у меня получилось с 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 не должен реализовывать Callable или Runnable. Я могу сделать MyApp Callable или Runnable. но для CommandLine new MyApp() не является командой, а new CliArguments().

Если я хочу сделать что-то вроде этого:

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

как перенести всю спецификацию @Option в другой класс, CliArguments, сохраняя при этом управление выполнением в MyApp?

Я уверен, что мне чего-то не хватает прямо вперед.


person Kap4Lin    schedule 22.05.2020    source источник


Ответы (1)


Самый простой способ добиться этого — создать CliArguments миксин в MyApp. Затем мы можем поместить бизнес-логику в MyApp и сделать ее Runnable или Callable, чтобы мы могли загрузить приложение с помощью 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, становятся частью миксина MyApp. Кроме того, любые атрибуты @Command, определенные в CliArgs, становятся частью команды MyApp.

Теперь вы можете запустить:

java MyApp -x

и это будет печатать

-x=true
-y=false

Так как миксин имеет @Command(mixinStandardHelpOptions = true), команда MyApp также имеет параметры --help и --version, которые работают так, как вы ожидаете.

person Remko Popma    schedule 22.05.2020
comment
Спасибо, @Mixin это то, чего мне не хватало. Кстати, пример github, CommandWithMixin.java отсутствует. - person Kap4Lin; 22.05.2020
comment
Спасибо за подтверждение. Чего не хватает в примере GitHub? Я вижу класс миксина CommonOption.java, или вы не это имеете в виду? - person Remko Popma; 22.05.2020
comment
Github выдавал ошибку сервера в файле CommandWithMixin.java. Я вижу это сейчас. Без вопросов. Спасибо, агиан. - person Kap4Lin; 23.05.2020