Add a possibility for partial arguments parsing
highsource opened this issue · 0 comments
highsource commented
I'd like to use args4j
in XJC plugins.
They may implement a method like:
public int parseArgument( Options opt, String[] args, int i ) throws BadCommandLineException, IOException {
return 0;
}
i
is initial position the the arguments list and return value is the number of the arguments consumed.
So I basically need the something similar in the CmdLineParser
. This is how I did it at the moment:
public int parseArgument(final String[] args, final int position)
throws CmdLineException {
Validate.noNullElements(args);
currentOptionHandler = null;
CmdLineImpl cmdLine = new CmdLineImpl(args, position);
Set<OptionHandler<?>> present = new HashSet<OptionHandler<?>>();
int argIndex = position;
int consumed = 0;
while (cmdLine.hasMore()) {
String arg = cmdLine.getCurrentToken();
if (isOption(arg)) {
// '=' is for historical compatibility fallback
boolean isKeyValuePair = arg.contains(getProperties()
.getOptionValueDelimiter()) || arg.indexOf('=') != -1;
// parse this as an option.
currentOptionHandler = isKeyValuePair ? findOptionHandler(arg)
: findOptionByName(arg);
if (currentOptionHandler == null) {
return consumed;
}
// known option; skip its name
if (isKeyValuePair) {
cmdLine.splitToken();
} else {
cmdLine.proceed(1);
consumed++;
}
} else {
if (argIndex >= getArguments().size()) {
Messages msg = getArguments().size() == 0 ? Messages.NO_ARGUMENT_ALLOWED
: Messages.TOO_MANY_ARGUMENTS;
throw new CmdLineException(this, msg, arg);
}
// known argument
currentOptionHandler = getArguments().get(argIndex);
if (currentOptionHandler == null) // this is a programmer error.
// arg index should be
// continuous
throw new IllegalStateException("@Argument with index="
+ argIndex + " is undefined");
if (!currentOptionHandler.option.isMultiValued())
argIndex++;
}
int diff = currentOptionHandler.parseArguments(cmdLine);
cmdLine.proceed(diff);
consumed += diff;
present.add(currentOptionHandler);
}
// check whether a help option is set
boolean helpSet = false;
for (OptionHandler<?> handler : getOptions()) {
if (handler.option.help() && present.contains(handler)) {
helpSet = true;
}
}
if (!helpSet) {
checkRequiredOptionsAndArguments(present);
}
return consumed;
}
This is basically a copy-paste from CmdLineParser
with the main difference that if some option can't be parsed, the method returns instead of throwing the exception.
Currently I've solved it by subclassing the CmdLineParser
. I had to copy-paste a number of things as they are private/package-protected:
findOptionHandler
findOptionByName
checkRequiredOptionsAndArguments
isHandlerHasHisOptions
isHandlerAllowOtherOptions
- `CmdLineImpl - also need a new constructor to set the initial position
getOptionName
org.kohsuke.args4j.Messages
Would you consider a PR for this functionality? Should I do one?