/** * Prints a usage message to the given stream. * * @param out The output stream to write to. */ public void printUsage(OutputStream out) { Formatter formatter = new Formatter(out); Set<CommandLineOption> orderedOptions = new TreeSet<CommandLineOption>(new OptionComparator()); orderedOptions.addAll(optionsByString.values()); Map<String, String> lines = new LinkedHashMap<String, String>(); for (CommandLineOption option : orderedOptions) { Set<String> orderedOptionStrings = new TreeSet<String>(new OptionStringComparator()); orderedOptionStrings.addAll(option.getOptions()); List<String> prefixedStrings = new ArrayList<String>(); for (String optionString : orderedOptionStrings) { if (optionString.length() == 1) { prefixedStrings.add("-" + optionString); } else { prefixedStrings.add("--" + optionString); } } lines.put(GUtil.join(prefixedStrings, ", "), GUtil.elvis(option.getDescription(), "")); } int max = 0; for (String optionStr : lines.keySet()) { max = Math.max(max, optionStr.length()); } for (Map.Entry<String, String> entry : lines.entrySet()) { if (entry.getValue().length() == 0) { formatter.format("%s%n", entry.getKey()); } else { formatter.format("%-" + max + "s %s%n", entry.getKey(), entry.getValue()); } } formatter.flush(); }
@Override public ParserState onComplete() { if (getHasArgument() && values.isEmpty()) { throw new CommandLineArgumentException( String.format("No argument was provided for command-line option '%s'.", optionString)); } ParsedCommandLineOption parsedOption = commandLine.addOption(optionString.option, option); if (values.size() + parsedOption.getValues().size() > 1 && !option.getAllowsMultipleArguments()) { throw new CommandLineArgumentException( String.format( "Multiple arguments were provided for command-line option '%s'.", optionString)); } for (String value : values) { parsedOption.addArgument(value); } if (option.getDeprecationWarning() != null) { new PrintStream(CommandLineParser.this.deprecationPrinter) .println( "The " + optionString + " option is deprecated - " + option.getDeprecationWarning()); } if (option.getSubcommand() != null) { return state.onNonOption(option.getSubcommand()); } return state; }
/** * Specifies that the given set of options are mutually-exclusive. Only one of the given options * will be selected. The parser ignores all but the last of these options. */ public CommandLineParser allowOneOf(String... options) { Set<CommandLineOption> commandLineOptions = new HashSet<CommandLineOption>(); for (String option : options) { commandLineOptions.add(optionsByString.get(option)); } for (CommandLineOption commandLineOption : commandLineOptions) { commandLineOption.groupWith(commandLineOptions); } return this; }
@Override public ParserState onStartNextArg() { if (option.getAllowsArguments() && values.isEmpty()) { return new MissingOptionArgState(this); } return onComplete(); }
/** * Defines a new option. By default, the option takes no arguments and has no description. * * @param options The options values. * @return The option, which can be further configured. */ public CommandLineOption option(String... options) { for (String option : options) { if (optionsByString.containsKey(option)) { throw new IllegalArgumentException( String.format("Option '%s' is already defined.", option)); } if (option.startsWith("-")) { throw new IllegalArgumentException( String.format("Cannot add option '%s' as an option cannot start with '-'.", option)); } } CommandLineOption option = new CommandLineOption(Arrays.asList(options)); for (String optionStr : option.getOptions()) { this.optionsByString.put(optionStr, option); } return option; }
public int compare(CommandLineOption option1, CommandLineOption option2) { String min1 = Collections.min(option1.getOptions(), new OptionStringComparator()); String min2 = Collections.min(option2.getOptions(), new OptionStringComparator()); return new CaseInsensitiveStringComparator().compare(min1, min2); }
@Override public boolean getHasArgument() { return option.getAllowsArguments(); }
/** * Parse the command line, validate the arguments and make them available through the getValue() * and isExists() methods. * * @param args the command line arguments, usually from the main() method * @param caseSensitive if true then the argument names must match exactly, else a case * insensitive match is used. */ public void parse(String[] args, boolean caseSensitive) { args = concatenateDelimitedArgs(args); for (String arg : args) { String[] nameValue = arg.split("="); String name = null; String value = null; if (nameValue.length > 0) name = nameValue[0]; if (nameValue.length > 1) value = nameValue[1]; if (name != null) { CommandLineOption commandLineArg = null; if (caseSensitive) commandLineArg = commandLineDefinition.valueOf(name); else commandLineArg = commandLineDefinition.valueOfIgnoreCase(name); if (commandLineArg != null) { try { Object typedObject = createTypedObject(value, commandLineArg.getType()); nameValuePairs.put(commandLineArg, typedObject); } catch (NumberFormatException x) { parseErrorMessages.add( "Incorrect format for value of parameter '" + name + "', must be parsable to type '" + commandLineArg.getType().toString() + "'."); } } else parseErrorMessages.add("Unknown parameter '" + name + "'."); } } for (Iterator<? extends CommandLineOption> iter = commandLineDefinition.iterator(); iter.hasNext(); ) { CommandLineOption arg = iter.next(); if (arg.isRequired() && !nameValuePairs.containsKey(arg)) parseErrorMessages.add( "Required parameter '" + arg.toString() + "' is not provided on the command line, use " + arg.toString() + ((arg.getType() == null) ? "." : "=<value>.")); if (nameValuePairs.containsKey(arg) && (arg.getType() != null) && nameValuePairs.get(arg) == null) parseErrorMessages.add( "Parameter '" + arg.toString() + "' must have a value and it does not, use " + arg.toString() + "=<value>."); } if (parseErrorMessages.size() > 0) parseErrorMessages.add( "Valid parameters are: \n" + commandLineDefinition.getUselessMessage()); }