Command Line Parser
Æsh provide a Command Line Parser API which make it very easy to parse command lines. The command line parser is independant of the Console API, but can be used with it if wanted. The API support defining the commands you want parsed both with annotations and with a builder pattern.Annotations
Probably the easiest way to define a parser is by using annotations. The annotation must be defined at class level and is called CommandDefinition. CommandDefinition is the only strong requirement, but without any Options or Arguments the command would not accept any attributes. There are four different option types:- Option is the simplest kind of Option with only one value
Example: -h foo - OptionList can contain several values. It must be defined in connection to a field that implements Collection.
Example: --foo bar1,bar2,bar3 - OptionGroup is similar to OptionList in that it store several values, but OptionGroup also store the key given. This annotation must be used in connection to a field that implements Map.
Example: -Dname1=value1 -Dname2=value2 - Arguments defines the possible arguments thats given to a command. It do not require any option key, but as OptionList it require that the field must implement Collection.
A simple first example:
@CommandDefinition(name = "example1", description = "a simple example")
public class Example1 {
@Option(name = "X", description = "enable X", hasValue = false)
private Boolean enableX;
@Option(shortName = 'e', name = "equal", description = "enable equal", required = true)
private String equal;
@Option(shortName = 'i', name = "int1")
private Integer int1;
@OptionList
public List<String> values;
public Boolean getEnableX() { return enableX; }
public String getEqual() { return equal; }
public List<String> getValues() { return values; }
}
Example1 example1 = new Example1();
//this will throw an error if the object do not use the required annotations and
//if the line contain option name/values that do not match the defined options
ParserGenerator.parseAndPopulate(example1, "example1 --X --equal blabla --values one,two,three");
assertTrue(example1.getEnableX());
assertEquals("blabla", example1.getEqual());
assertEquals("one", example1.getValues().get(0));
Option
The different Option types have some common elements like:- name
- The option name. If it's not set the field name will be used. Two dashes (--) are added to the name on the command line.
- shortName
- The short option name. If it's not set the first char of name will be used. One dash (-) is added to the short name on the command line.
- description
- A simple description of the option. This info is displayed when help info is shown.
- required
- Specify if this option is required. Defaults to false.
- defaultValue[]
- Specify the default value(s) that will be used if the option do not have any value. Defaults to empty array.
- hasValue
- Define if this option should have a value connected to it. Only possible to set this to true when the field type is Boolean/boolean. Default is true.
- converter
- Specify a custom converter for the data type of the connected field.
- completer
- Specify a custom completer
- validator
- Specify a custom validator
Converter
When using a "custom" type for a field a converter is needed to inject the correct value. To ensure this we created a simple interface that all the converter implementations need to implement:public interface CLConverter<T> {
T convert(String input);
}
import java.util.Currency;
public class CurrencyConverter implements CLConverter<Currency> {
@Override
public Currency convert(String input) {
return Currency.getInstance(input);
}
}
Completer
Note that a completer is not needed if you only want to parse a command line and just populate the values. But if you are creating your own commands and want the possibility to autocomplete the values you need a completer.
Aesh already have a built in completer for Files and Boolean/booleans, all other types require adefined completer.The Completer interface looks like:
public interface OptionCompleter {
CompleterData complete(String completeValue);
}
A FooCompleter
public class FooOptionCompleter {
@Override
public CompleterData complete(String completeValue) {
List<String> values = new ArrayList<String>();
if(completeValue == null || completeValue.length() == 0)
values.add("Foo");
else if("Foo".startsWith(completeValue))
values.add("Foo")
return new CompleterData(values);
}
}
Validator
The validator is optional and will be executed during population of the option value. The validator interface looks like:public interface OptionValidator<T> {
void validate(T value) throws OptionValidatorException;
}