jbock:無反射的Java命令列引數解析器

banq發表於2022-03-24

jbock 是一個命令列解析器,它使用與JCommander 和picocli相同的註解名稱。但是它不使用反射。它是一個 註釋處理器 ,可在編譯時生成自定義解析器。

JCommander 是一個非常小的 Java 框架,可以輕鬆解析命令列引數。您使用選項描述註釋欄位:

import com.beust.jcommander.Parameter;

public class Args {
  @Parameter
  private List<String> parameters = new ArrayList<>();

  @Parameter(names = { "-log", "-verbose" }, description = "Level of verbosity")
  private Integer verbose = 1;

  @Parameter(names = "-groups", description = "Comma-separated list of group names to be run")
  private String groups;

  @Parameter(names = "-debug", description = "Debug mode")
  private boolean debug = false;
}

然後你只需讓 JCommander 解析:

class Main {
    @Parameter(names={"--length", "-l"})
    int length;
    @Parameter(names={"--pattern", "-p"})
    int pattern;

    public static void main(String ... argv) {
        Main main = new Main();
        JCommander.newBuilder()
            .addObject(main)
            .build()
            .parse(argv);
        main.run();
    }

    public void run() {
        System.out.printf("%d %d", length, pattern);
    }
}

$ java Main -l 512 --pattern 2
512 2

 

jbock是無反射命令列解析器:

@Command
abstract class DeleteCommand {

  @Option(names = {"-v", "--verbosity"},
          description = "A named option. The return type reflects optionality.")
  abstract OptionalInt verbosity();

  @Parameter(
          index = 0,
          description = {"A required positional parameter. Return type is non-optional.",
                         "Path is a standard type, so no custom converter is needed."})
  abstract Path path();

  @Parameter(
          index = 1,
          description = "An optional positional parameter.")
  abstract Optional<Path> anotherPath();

  @VarargsParameter(
          description = {"A varargs parameter. There can only be one of these.",
                         "The return type must be List."})
  abstract List<Path> morePaths();
  
  @Option(names = "--dry-run",
          description = "A nullary option, a.k.a. mode flag. Return type is boolean.")
  abstract boolean dryRun();
  
  @Option(names = "-h",
          description = "A repeatable option. Return type is List.")
  abstract List<String> headers(); 
  
  @Option(names = "--charset",
          description = "Named option with a custom converter",
          converter = CharsetConverter.class)
  abstract Optional<Charset> charset();
  
  // sample converter class
  static class CharsetConverter extends StringConverter<Charset> {
    @Override
    protected Charset convert(String token) { return StandardCharsets.UTF_8; }
  }
}



生成的DeleteCommandParser將一個字串陣列轉換為DeleteCommand的一個例項:

public static void main(String[] args) {
  DeleteCommand command = new DeleteCommandParser().parseOrExit(args);
  // ...
}




 

相關文章