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=true
orbar=false
) are described byboolean
andBoolean
types - Optional single key-value options (
--input foo.txt
orinput=foo.txt
) are described by theOptional<String>
type - Optional repeatable key-value options (
-i foo.txt -i bar.txt
orinputs=foo.txt,bar.txt
) are described by theList<String>
type - Positional required options (
output.txt
) are described by theString
type - 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:
@Name
in order to specify names that aren't legal Java names or to bind multiple names to one record component@Help
in 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 example4
In an IDE:
- run as java application (
main
method) - use name(s) of methods as arguments to limit
This project is inspired by https://github.com/forax/argvester