jbock is a command line parser that works similar to airline and picocli. While most of these other tools scan for annotations at runtime, jbock is an annotation processor and generates Java source code at compile time instead.
Overview
A command line interface is defined by an abstract
class which has a @Command
annotation. In this class, each abstract
method corresponds either to a named option or a positional parameter.
@Command
abstract class MyCommand {
/**
* A {@code @Param} is a positional parameter.
* This particular param is in the front position,
* since there are no other params in lower positions.
*/
@Param(0)
abstract Path path();
/**
* An {@code @Option} is a named option.
*/
@Option("verbosity")
abstract OptionalInt verbosity();
}
When jbock is properly configured as an annotation processor, the presence of the @Command
annotation will trigger a round of code generation at compile time. The generated class will, in this case, be called MyCommand_Parser
. It can be used as follows:
String[] args = { "--verbosity=2", "file.txt" }; // sample psvm input
MyCommand c = new MyCommand_Parser().parseOrExit(args);
// Works as expected!
assertEquals(OptionalInt.of(2), c.verbosity());
assertEquals(Paths.get("file.txt"), c.path());
In the MyCommand example, the path
parameter is required, while the option verbosity
is optional. The property of being either optional or required is called skew. There are four different skews: required, optional, repeatable and flag. In this case, the skew is determined by the return type of the option's or parameter's abstract
method, according to the following rules.
Skew rules
These rules apply for options and params that do not define a custom mapper, as in the MyCommand
example:
Skew table A
Return type of the abstract method |
Skew |
---|---|
{boolean,Boolean} |
flag (only for @Option ) |
Optional<A> |
optional |
Optional{Int,Long,Double} |
optional |
List<A> |
repeatable |
A (exact match) |
required |
where A
must be one of the auto types, otherwise compilation will fail.
Both @Option
and @Param
have an optional attribute mappedBy
which takes a single value of type Class<?>
. Any such mapper class must implement Function<String, E>
or Supplier<Function<String, E>>
for some E
.
If a custom mapper is defined, then the skew is determined by comparing the method's return type to the type of its mapper:
Skew table B
Mapper type | Return type of the abstract method |
Skew |
---|---|---|
Function<String, M > |
Optional<M> |
optional |
Function<String, {Integer,Long,Double} > |
Optional{Int,Long,Double} |
optional |
Function<String, M > |
List<M> |
repeatable |
Function<String, M > |
M |
required |
Function<String, {Integer,Float,...} > |
{int,float,...} |
required |
When none of these rules apply, compilation will fail.
Both rule tables can be summarized in a third table:
Skew rules overview
Mapper defined? | Skew |
---|---|
No | See Skew Table A |
Yes | See Skew Table B |