Skip to content

jbock-java/jbock

Folders and files

NameName
Last commit message
Last commit date
Dec 25, 2023
Mar 5, 2024
Mar 5, 2024
Mar 5, 2024
Mar 5, 2024
Dec 12, 2023
Sep 28, 2018
Mar 5, 2024
May 9, 2021
Dec 3, 2023
Jan 26, 2022
Jan 25, 2022

Repository files navigation

jbock-compiler jbock

jbock is a command line parser, which uses the same well-known annotation names as JCommander and picocli. It is an annotation processor so it doesn't use runtime reflection, but generates a custom parser at compile time instead.

Quick rundown

Create an abstract class, or alternatively a Java interface, and add the @Command annotation. In this so-called command class, each abstract method represents a command line option or argument. Every such method must have

  • getter signature (doesn't return void, takes no arguments) and
  • annotation (either @Option, @Parameter or @VarargsParameter).

The multiplicity of options and parameters is determined by the return type of their declaring method. The types boolean, List and Optional (including OptionalInt, yada yada) have a special meaning. See example below.

@Command
abstract class DeleteCommand {

  @Option(names = {"-v", "--verbosity"},
          description = {"A named option. The return type reflects optionality.",
                         "Could use Optional<Integer> too, but using int or Integer",
                         "would make it a 'required option'."})
  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-of-something."})
  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 Charset.forName(token); }
  }
}

The generated class is called DeleteCommandParser. It converts a string array to an instance of DeleteCommand:

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

In addition to parseOrExit, the generated parser has a basic and side-effect free parse method. This can be used to fine-tune the help and error messages for your users.

Standard types

Some types don't need a custom converter. See StandardConverters.java.

Subcommands

The @SuperCommand annotation can be used to define a git-like subcommand structure. See javadoc.

Sample projects

Alternatives