io.airlift.command.Parser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of airline Show documentation
Show all versions of airline Show documentation
Airline is a Java annotation-based framework for parsing Git like command line structures.
The newest version!
package io.airlift.command;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import com.google.common.collect.PeekingIterator;
import io.airlift.command.model.ArgumentsMetadata;
import io.airlift.command.model.CommandGroupMetadata;
import io.airlift.command.model.CommandMetadata;
import io.airlift.command.model.GlobalMetadata;
import io.airlift.command.model.OptionMetadata;
import java.util.List;
import java.util.regex.Pattern;
import static com.google.common.base.Predicates.compose;
import static com.google.common.base.Predicates.equalTo;
import static com.google.common.collect.Iterables.find;
public class Parser
{
private static final Pattern SHORT_OPTIONS_PATTERN = Pattern.compile("-[^-].*");
private final GlobalMetadata metadata;
public Parser(GlobalMetadata metadata)
{
this.metadata = metadata;
}
// global> (option value*)* (group (option value*)*)? (command (option value* | arg)* '--'? args*)?
public ParseState parse(String... params)
{
return parse(ImmutableList.copyOf(params));
}
public ParseState parse(Iterable params)
{
PeekingIterator tokens = Iterators.peekingIterator(params.iterator());
ParseState state = ParseState.newInstance().pushContext(Context.GLOBAL);
// parse global options
state = parseOptions(tokens, state, metadata.getOptions());
// parse group
if (tokens.hasNext()) {
CommandGroupMetadata group = find(metadata.getCommandGroups(), compose(equalTo(tokens.peek()), CommandGroupMetadata.nameGetter()), null);
if (group != null) {
tokens.next();
state = state.withGroup(group).pushContext(Context.GROUP);
state = parseOptions(tokens, state, state.getGroup().getOptions());
}
}
// parse command
List expectedCommands = metadata.getDefaultGroupCommands();
if (state.getGroup() != null) {
expectedCommands = state.getGroup().getCommands();
}
if (tokens.hasNext()) {
CommandMetadata command = find(expectedCommands, compose(equalTo(tokens.peek()), CommandMetadata.nameGetter()), null);
if (command == null) {
while (tokens.hasNext()) {
state = state.withUnparsedInput(tokens.next());
}
}
else {
tokens.next();
state = state.withCommand(command).pushContext(Context.COMMAND);
while (tokens.hasNext()) {
state = parseOptions(tokens, state, command.getCommandOptions());
state = parseArgs(state, tokens, command.getArguments());
}
}
}
return state;
}
private ParseState parseOptions(PeekingIterator tokens, ParseState state, List allowedOptions)
{
while (tokens.hasNext()) {
//
// Try to parse next option(s) using different styles. If code matches it returns
// the next parser state, otherwise it returns null.
// Parse a simple option
ParseState nextState = parseSimpleOption(tokens, state, allowedOptions);
if (nextState != null) {
state = nextState;
continue;
}
// Parse GNU getopt long-form: --option=value
nextState = parseLongGnuGetOpt(tokens, state, allowedOptions);
if (nextState != null) {
state = nextState;
continue;
}
// Handle classic getopt syntax: -abc
nextState = parseClassicGetOpt(tokens, state, allowedOptions);
if (nextState != null) {
state = nextState;
continue;
}
// did not match an option
break;
}
return state;
}
private ParseState parseSimpleOption(PeekingIterator tokens, ParseState state, List allowedOptions)
{
OptionMetadata option = findOption(allowedOptions, tokens.peek());
if (option == null) {
return null;
}
tokens.next();
state = state.pushContext(Context.OPTION).withOption(option);
Object value;
if (option.getArity() == 0) {
state = state.withOptionValue(option, Boolean.TRUE).popContext();
}
else if (option.getArity() == 1) {
if (tokens.hasNext()) {
value = TypeConverter.newInstance().convert(option.getTitle(), option.getJavaType(), tokens.next());
state = state.withOptionValue(option, value).popContext();
}
}
else {
ImmutableList.Builder