An Arguments Splitter splits structured string arrays (String[]) into different values
following a Schema. A schema is defined by a list of Options
specifying how to transform the strings into argument values.
There are two pre-defined schemas, a record based schema that uses convention oven configuration and an options based schema that offers a programmatic API.
Defining the Unix's wc as an example:
record WordCountOptions(
@Name({"-c", "--bytes"}) boolean bytes,
@Name({"-m", "--chars"}) boolean chars,
@Name({"-l", "--lines"}) boolean lines,
@Name("--files0-from") Optional<File> files0From,
@Name({"-w", "--words"}) boolean words,
/* unnamed */ File... files
) {}
var splitter = Splitter.of(MethodHandles.lookup(), WordCountOptions.class);
WordCountOptions options = splitter.split(args);
// use options instance ...Option structures are described using Java types.
- Optional flag options (
--verbose,--foo=trueorbar=false) are described bybooleanandBooleantypes - Optional single key-value options (
--input foo.txtorinput=foo.txt) are described by theOptional<String>type - Optional repeatable key-value options (
-i foo.txt -i bar.txtorinputs=foo.txt,bar.txt) are described by theList<String>type - Positional required options (
output.txt) are described by theStringtype - Variadic options (
a.txt b.txt ...) are described by theString...type
Nested option structures are single key-value option or repeatable key-value options
described by custom record types.
By convention, a _ character in record component names is mapped to - character on the command-line.
In addition to the above conventions record components can be annotated with:
@Namein order to specify names that aren't legal Java names or to bind multiple names to one record component@Helpin order to provide a help description
Mapping to non-String or boolean types is done through a converter resolver.
Defining the Unix's wc using the type-safe programmatic API:
var bytes = Option.flag("-c", "--bytes");
var lines = Option.flag("-l", "--lines");
var files0From = Option.single("--files0-from").convert(Path::of);
var words = Option.flag("-w", "--words");
var files = Options.varargs("files").convert(Path::of);
var splitter = Splitter.of(bytes, lines, files0From, words, files);
ArgumentMap argumentMap = splitter.split(args);
// use argumentMap instance ...An option is an immutable class with one or more names, a value converter, and optionally a help text and a nested schema.
How to build this project and run tests.
Setup JDK 17 or later, and on the command-line run:
# run all tests
java build/build.java
# run single test class
java build/build.java JarTests
# run one or more methods of a single test class
java build/build.java JarTests example2 example4In an IDE:
- run as java application (
mainmethod) - use name(s) of methods as arguments to limit
This project is inspired by https://github.com/forax/argvester