jbock is a command line parser, which uses well-known annotation names similar to JCommander and picocli. It is an annotation processor which does not use runtime reflection, but generates a custom parser at compile time instead.
Choose any name for the java interface which will describe your command line API.
Add the @Command anntation to your command interface, to make the annotation processor aware of it.
Let's call a non-default interface method an abstract method.
Each abstract method in your command interface represents a command line option or argument.
It must have "getter signature": return something other that void, and have an empty parameter list.
It must also be annotated with either
@Option, @Parameter or @VarargsParameter (with one exception, see below).
The return types boolean, List<?> and Optional<?> (including OptionalInt and such) have special semantics.
They are used to declare flags, repeable and optional options and parameters, respectively.
Tip
If a method annotated with @VarargsParameter exists, it must return a list.
There cannot be more than one such method.
Any unannotated, list-returning abstract method is also used as a catch-all for extra positional parameters.
In other words, the @VarargsParameter annotation can be omitted.
Here's an example:
@Command
interface DeleteCommand {
@Option(names = {"-v", "--verbosity"},
description = {"The return type for this option is \"optionalish\".",
"Using int or Integer instead would make it a required option."})
OptionalInt verbosity();
@Parameter(
index = 0,
description = {"A required positional parameter.",
"Path is a \"known type\",",
"so the parser knows how to create a Path from a string."})
Path path();
@Parameter(
index = 1,
description = {"The return type for this positional parameter is \"optionalish\",",
"which makes this an optional positional parameter"})
Optional<Path> anotherPath();
@VarargsParameter(
description = {"The varargs parameter. There can be at most one of these.",
"It is a catch-all for additional positional parameters.",
"Must return List<Something>.",
"Note: For an actual rm-style interface, it might make more sense",
"to have only the VarargsParameter, and no other Parameters."})
List<Path> morePaths();
@Option(names = "--dry-run",
description = {"The return type for this option is boolean,",
"which makes it a mode flag."})
boolean dryRun();
@Option(names = "-h",
description = "This returns List<Something>, so it's a \"repeatable option\".")
List<String> headers();
@Option(names = "--charset",
description = {"Charset is not a \"known type\",",
"but we can use a default method to convert. See below."})
Optional<String> charsetString();
// A default method can be used to convert from string.
default Charset charset() {
return Charset.forName(charsetString());
}
}The generated class is called DeleteCommandParser. We can use it in our main method:
public static void main(String[] args) {
DeleteCommand command = DeleteCommandParser.parseOrExit(args);
// alternatively:
// Either<ParsingFailed, DeleteCommand> either = DeleteCommandParser.parse(List.of(args));
// more cool stuff...
}Some types are converted automatically. See StandardConverters.java.
The @SuperCommand annotation can be used to define a git-like subcommand structure. See javadoc.