/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.cli;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
/**
* A formatter of help messages for command line options.
*
*
* Example:
*
*
*
* Options options = new Options();
* options.addOption(OptionBuilder.withLongOpt("file").withDescription("The file to be processed").hasArg()
* .withArgName("FILE").isRequired().create('f'));
* options.addOption(
* OptionBuilder.withLongOpt("version").withDescription("Print the version of the application").create('v'));
* options.addOption(OptionBuilder.withLongOpt("help").create('h'));
*
* String header = "Do something useful with an input file\n\n";
* String footer = "\nPlease report issues at http://example.com/issues";
*
* HelpFormatter formatter = new HelpFormatter();
* formatter.printHelp("myapp", header, options, footer, true);
*
*
* This produces the following output:
*
*
* usage: myapp -f <FILE> [-h] [-v]
* Do something useful with an input file
*
* -f,--file <FILE> The file to be processed
* -h,--help
* -v,--version Print the version of the application
*
* Please report issues at http://example.com/issues
*
*
* @version $Id: HelpFormatter.java 1677407 2015-05-03 14:31:12Z britter $
*/
public class HelpFormatter {
// --------------------------------------------------------------- Constants
/** default number of characters per line */
public static final int DEFAULT_WIDTH = 74;
/** default padding to the left of each line */
public static final int DEFAULT_LEFT_PAD = 1;
/** number of space characters to be prefixed to each description line */
public static final int DEFAULT_DESC_PAD = 3;
/** the string to display at the beginning of the usage statement */
public static final String DEFAULT_SYNTAX_PREFIX = "usage: ";
/** default prefix for shortOpts */
public static final String DEFAULT_OPT_PREFIX = "-";
/** default prefix for long Option */
public static final String DEFAULT_LONG_OPT_PREFIX = "--";
/**
* default separator displayed between a long Option and its value
*
* @since 1.3
**/
public static final String DEFAULT_LONG_OPT_SEPARATOR = " ";
/** default name for an argument */
public static final String DEFAULT_ARG_NAME = "arg";
// -------------------------------------------------------------- Attributes
/**
* number of characters per line
*
* @deprecated Scope will be made private for next major version - use get/setWidth methods instead.
*/
@Deprecated
public int defaultWidth = DEFAULT_WIDTH;
/**
* amount of padding to the left of each line
*
* @deprecated Scope will be made private for next major version - use get/setLeftPadding methods instead.
*/
@Deprecated
public int defaultLeftPad = DEFAULT_LEFT_PAD;
/**
* the number of characters of padding to be prefixed to each description line
*
* @deprecated Scope will be made private for next major version - use get/setDescPadding methods instead.
*/
@Deprecated
public int defaultDescPad = DEFAULT_DESC_PAD;
/**
* the string to display at the beginning of the usage statement
*
* @deprecated Scope will be made private for next major version - use get/setSyntaxPrefix methods instead.
*/
@Deprecated
public String defaultSyntaxPrefix = DEFAULT_SYNTAX_PREFIX;
/**
* the new line string
*
* @deprecated Scope will be made private for next major version - use get/setNewLine methods instead.
*/
@Deprecated
public String defaultNewLine = System.getProperty("line.separator");
/**
* the shortOpt prefix
*
* @deprecated Scope will be made private for next major version - use get/setOptPrefix methods instead.
*/
@Deprecated
public String defaultOptPrefix = DEFAULT_OPT_PREFIX;
/**
* the long Opt prefix
*
* @deprecated Scope will be made private for next major version - use get/setLongOptPrefix methods instead.
*/
@Deprecated
public String defaultLongOptPrefix = DEFAULT_LONG_OPT_PREFIX;
/**
* the name of the argument
*
* @deprecated Scope will be made private for next major version - use get/setArgName methods instead.
*/
@Deprecated
public String defaultArgName = DEFAULT_ARG_NAME;
/**
* Comparator used to sort the options when they output in help text
*
* Defaults to case-insensitive alphabetical sorting by option key
*/
protected Comparator optionComparator = new OptionComparator();
/** The separator displayed between the long option and its value. */
private String longOptSeparator = DEFAULT_LONG_OPT_SEPARATOR;
/**
* Sets the 'width'.
*
* @param width
* the new value of 'width'
*/
public void setWidth(final int width) {
defaultWidth = width;
}
/**
* Returns the 'width'.
*
* @return the 'width'
*/
public int getWidth() {
return defaultWidth;
}
/**
* Sets the 'leftPadding'.
*
* @param padding
* the new value of 'leftPadding'
*/
public void setLeftPadding(final int padding) {
defaultLeftPad = padding;
}
/**
* Returns the 'leftPadding'.
*
* @return the 'leftPadding'
*/
public int getLeftPadding() {
return defaultLeftPad;
}
/**
* Sets the 'descPadding'.
*
* @param padding
* the new value of 'descPadding'
*/
public void setDescPadding(final int padding) {
defaultDescPad = padding;
}
/**
* Returns the 'descPadding'.
*
* @return the 'descPadding'
*/
public int getDescPadding() {
return defaultDescPad;
}
/**
* Sets the 'syntaxPrefix'.
*
* @param prefix
* the new value of 'syntaxPrefix'
*/
public void setSyntaxPrefix(final String prefix) {
defaultSyntaxPrefix = prefix;
}
/**
* Returns the 'syntaxPrefix'.
*
* @return the 'syntaxPrefix'
*/
public String getSyntaxPrefix() {
return defaultSyntaxPrefix;
}
/**
* Sets the 'newLine'.
*
* @param newline
* the new value of 'newLine'
*/
public void setNewLine(final String newline) {
defaultNewLine = newline;
}
/**
* Returns the 'newLine'.
*
* @return the 'newLine'
*/
public String getNewLine() {
return defaultNewLine;
}
/**
* Sets the 'optPrefix'.
*
* @param prefix
* the new value of 'optPrefix'
*/
public void setOptPrefix(final String prefix) {
defaultOptPrefix = prefix;
}
/**
* Returns the 'optPrefix'.
*
* @return the 'optPrefix'
*/
public String getOptPrefix() {
return defaultOptPrefix;
}
/**
* Sets the 'longOptPrefix'.
*
* @param prefix
* the new value of 'longOptPrefix'
*/
public void setLongOptPrefix(final String prefix) {
defaultLongOptPrefix = prefix;
}
/**
* Returns the 'longOptPrefix'.
*
* @return the 'longOptPrefix'
*/
public String getLongOptPrefix() {
return defaultLongOptPrefix;
}
/**
* Set the separator displayed between a long option and its value. Ensure that the separator specified is supported
* by the parser used, typically ' ' or '='.
*
* @param longOptSeparator
* the separator, typically ' ' or '='.
* @since 1.3
*/
public void setLongOptSeparator(final String longOptSeparator) {
this.longOptSeparator = longOptSeparator;
}
/**
* Returns the separator displayed between a long option and its value.
*
* @return the separator
* @since 1.3
*/
public String getLongOptSeparator() {
return longOptSeparator;
}
/**
* Sets the 'argName'.
*
* @param name
* the new value of 'argName'
*/
public void setArgName(final String name) {
defaultArgName = name;
}
/**
* Returns the 'argName'.
*
* @return the 'argName'
*/
public String getArgName() {
return defaultArgName;
}
/**
* Comparator used to sort the options when they output in help text. Defaults to case-insensitive alphabetical
* sorting by option key.
*
* @return the {@link Comparator} currently in use to sort the options
* @since 1.2
*/
public Comparator getOptionComparator() {
return optionComparator;
}
/**
* Set the comparator used to sort the options when they output in help text. Passing in a null comparator will keep
* the options in the order they were declared.
*
* @param comparator
* the {@link Comparator} to use for sorting the options
* @since 1.2
*/
public void setOptionComparator(final Comparator comparator) {
optionComparator = comparator;
}
/**
* Print the help for options
with the specified command line syntax. This method prints help
* information to System.out.
*
* @param cmdLineSyntax
* the syntax for this application
* @param options
* the Options instance
*/
public void printHelp(final String cmdLineSyntax, final Options options) {
printHelp(getWidth(), cmdLineSyntax, null, options, null, false);
}
/**
* Print the help for options
with the specified command line syntax to the specified print writer.
*
* @param pw
* the {@link PrintWriter} instance that should be used. Note that it wont be flused.
* @param cmdLineSyntax
* the syntax for this application
* @param options
* the Options instance
* @author Daniel Dietsch (dietsch@informatik.uni-freiburg.de)
*/
public void printHelp(final PrintWriter pw, final String cmdLineSyntax, final Options options) {
printHelp(pw, getWidth(), cmdLineSyntax, null, options, getLeftPadding(), getDescPadding(), null, false);
}
/**
* Print the help for options
with the specified command line syntax. This method prints help
* information to System.out.
*
* @param cmdLineSyntax
* the syntax for this application
* @param options
* the Options instance
* @param autoUsage
* whether to print an automatically generated usage statement
*/
public void printHelp(final String cmdLineSyntax, final Options options, final boolean autoUsage) {
printHelp(getWidth(), cmdLineSyntax, null, options, null, autoUsage);
}
/**
* Print the help for options
with the specified command line syntax. This method prints help
* information to System.out.
*
* @param cmdLineSyntax
* the syntax for this application
* @param header
* the banner to display at the beginning of the help
* @param options
* the Options instance
* @param footer
* the banner to display at the end of the help
*/
public void printHelp(final String cmdLineSyntax, final String header, final Options options, final String footer) {
printHelp(cmdLineSyntax, header, options, footer, false);
}
/**
* Print the help for options
with the specified command line syntax. This method prints help
* information to System.out.
*
* @param cmdLineSyntax
* the syntax for this application
* @param header
* the banner to display at the beginning of the help
* @param options
* the Options instance
* @param footer
* the banner to display at the end of the help
* @param autoUsage
* whether to print an automatically generated usage statement
*/
public void printHelp(final String cmdLineSyntax, final String header, final Options options, final String footer,
final boolean autoUsage) {
printHelp(getWidth(), cmdLineSyntax, header, options, footer, autoUsage);
}
/**
* Print the help for options
with the specified command line syntax. This method prints help
* information to System.out.
*
* @param width
* the number of characters to be displayed on each line
* @param cmdLineSyntax
* the syntax for this application
* @param header
* the banner to display at the beginning of the help
* @param options
* the Options instance
* @param footer
* the banner to display at the end of the help
*/
public void printHelp(final int width, final String cmdLineSyntax, final String header, final Options options,
final String footer) {
printHelp(width, cmdLineSyntax, header, options, footer, false);
}
/**
* Print the help for options
with the specified command line syntax. This method prints help
* information to System.out.
*
* @param width
* the number of characters to be displayed on each line
* @param cmdLineSyntax
* the syntax for this application
* @param header
* the banner to display at the beginning of the help
* @param options
* the Options instance
* @param footer
* the banner to display at the end of the help
* @param autoUsage
* whether to print an automatically generated usage statement
*/
public void printHelp(final int width, final String cmdLineSyntax, final String header, final Options options,
final String footer, final boolean autoUsage) {
final PrintWriter pw = new PrintWriter(System.out);
printHelp(pw, width, cmdLineSyntax, header, options, getLeftPadding(), getDescPadding(), footer, autoUsage);
pw.flush();
}
/**
* Print the help for options
with the specified command line syntax.
*
* @param pw
* the writer to which the help will be written
* @param width
* the number of characters to be displayed on each line
* @param cmdLineSyntax
* the syntax for this application
* @param header
* the banner to display at the beginning of the help
* @param options
* the Options instance
* @param leftPad
* the number of characters of padding to be prefixed to each line
* @param descPad
* the number of characters of padding to be prefixed to each description line
* @param footer
* the banner to display at the end of the help
*
* @throws IllegalStateException
* if there is no room to print a line
*/
public void printHelp(final PrintWriter pw, final int width, final String cmdLineSyntax, final String header,
final Options options, final int leftPad, final int descPad, final String footer) {
printHelp(pw, width, cmdLineSyntax, header, options, leftPad, descPad, footer, false);
}
/**
* Print the help for options
with the specified command line syntax.
*
* @param pw
* the writer to which the help will be written
* @param width
* the number of characters to be displayed on each line
* @param cmdLineSyntax
* the syntax for this application
* @param header
* the banner to display at the beginning of the help
* @param options
* the Options instance
* @param leftPad
* the number of characters of padding to be prefixed to each line
* @param descPad
* the number of characters of padding to be prefixed to each description line
* @param footer
* the banner to display at the end of the help
* @param autoUsage
* whether to print an automatically generated usage statement
*
* @throws IllegalStateException
* if there is no room to print a line
*/
public void printHelp(final PrintWriter pw, final int width, final String cmdLineSyntax, final String header,
final Options options, final int leftPad, final int descPad, final String footer, final boolean autoUsage) {
if (cmdLineSyntax == null || cmdLineSyntax.length() == 0) {
throw new IllegalArgumentException("cmdLineSyntax not provided");
}
if (autoUsage) {
printUsage(pw, width, cmdLineSyntax, options);
} else {
printUsage(pw, width, cmdLineSyntax);
}
if (header != null && header.trim().length() > 0) {
printWrapped(pw, width, header);
}
printOptions(pw, width, options, leftPad, descPad);
if (footer != null && footer.trim().length() > 0) {
printWrapped(pw, width, footer);
}
}
/**
* Prints the usage statement for the specified application.
*
* @param pw
* The PrintWriter to print the usage statement
* @param width
* The number of characters to display per line
* @param app
* The application name
* @param options
* The command line Options
*/
public void printUsage(final PrintWriter pw, final int width, final String app, final Options options) {
// initialise the string buffer
final StringBuffer buff = new StringBuffer(getSyntaxPrefix()).append(app).append(" ");
// create a list for processed option groups
final Collection processedGroups = new ArrayList();
final List optList = new ArrayList (options.getOptions());
if (getOptionComparator() != null) {
Collections.sort(optList, getOptionComparator());
}
// iterate over the options
for (final Iterator it = optList.iterator(); it.hasNext();) {
// get the next Option
final Option option = it.next();
// check if the option is part of an OptionGroup
final OptionGroup group = options.getOptionGroup(option);
// if the option is part of a group
if (group != null) {
// and if the group has not already been processed
if (!processedGroups.contains(group)) {
// add the group to the processed list
processedGroups.add(group);
// add the usage clause
appendOptionGroup(buff, group);
}
// otherwise the option was displayed in the group
// previously so ignore it.
}
// if the Option is not part of an OptionGroup
else {
appendOption(buff, option, option.isRequired());
}
if (it.hasNext()) {
buff.append(" ");
}
}
// call printWrapped
printWrapped(pw, width, buff.toString().indexOf(' ') + 1, buff.toString());
}
/**
* Appends the usage clause for an OptionGroup to a StringBuffer. The clause is wrapped in square brackets if the
* group is required. The display of the options is handled by appendOption
*
* @param buff
* the StringBuffer to append to
* @param group
* the group to append
* @see #appendOption(StringBuffer,Option,boolean)
*/
private void appendOptionGroup(final StringBuffer buff, final OptionGroup group) {
if (!group.isRequired()) {
buff.append("[");
}
final List optList = new ArrayList (group.getOptions());
if (getOptionComparator() != null) {
Collections.sort(optList, getOptionComparator());
}
// for each option in the OptionGroup
for (final Iterator it = optList.iterator(); it.hasNext();) {
// whether the option is required or not is handled at group level
appendOption(buff, it.next(), true);
if (it.hasNext()) {
buff.append(" | ");
}
}
if (!group.isRequired()) {
buff.append("]");
}
}
/**
* Appends the usage clause for an Option to a StringBuffer.
*
* @param buff
* the StringBuffer to append to
* @param option
* the Option to append
* @param required
* whether the Option is required or not
*/
private void appendOption(final StringBuffer buff, final Option option, final boolean required) {
if (!required) {
buff.append("[");
}
if (option.getOpt() != null) {
buff.append("-").append(option.getOpt());
} else {
buff.append("--").append(option.getLongOpt());
}
// if the Option has a value and a non blank argname
if (option.hasArg() && (option.getArgName() == null || option.getArgName().length() != 0)) {
buff.append(option.getOpt() == null ? longOptSeparator : " ");
buff.append("<").append(option.getArgName() != null ? option.getArgName() : getArgName()).append(">");
}
// if the Option is not a required option
if (!required) {
buff.append("]");
}
}
/**
* Print the cmdLineSyntax to the specified writer, using the specified width.
*
* @param pw
* The printWriter to write the help to
* @param width
* The number of characters per line for the usage statement.
* @param cmdLineSyntax
* The usage statement.
*/
public void printUsage(final PrintWriter pw, final int width, final String cmdLineSyntax) {
final int argPos = cmdLineSyntax.indexOf(' ') + 1;
printWrapped(pw, width, getSyntaxPrefix().length() + argPos, getSyntaxPrefix() + cmdLineSyntax);
}
/**
* Print the help for the specified Options to the specified writer, using the specified width, left padding and
* description padding.
*
* @param pw
* The printWriter to write the help to
* @param width
* The number of characters to display per line
* @param options
* The command line Options
* @param leftPad
* the number of characters of padding to be prefixed to each line
* @param descPad
* the number of characters of padding to be prefixed to each description line
*/
public void printOptions(final PrintWriter pw, final int width, final Options options, final int leftPad,
final int descPad) {
final StringBuffer sb = new StringBuffer();
renderOptions(sb, width, options, leftPad, descPad);
pw.println(sb.toString());
}
/**
* Print the specified text to the specified PrintWriter.
*
* @param pw
* The printWriter to write the help to
* @param width
* The number of characters to display per line
* @param text
* The text to be written to the PrintWriter
*/
public void printWrapped(final PrintWriter pw, final int width, final String text) {
printWrapped(pw, width, 0, text);
}
/**
* Print the specified text to the specified PrintWriter.
*
* @param pw
* The printWriter to write the help to
* @param width
* The number of characters to display per line
* @param nextLineTabStop
* The position on the next line for the first tab.
* @param text
* The text to be written to the PrintWriter
*/
public void printWrapped(final PrintWriter pw, final int width, final int nextLineTabStop, final String text) {
final StringBuffer sb = new StringBuffer(text.length());
renderWrappedTextBlock(sb, width, nextLineTabStop, text);
pw.println(sb.toString());
}
// --------------------------------------------------------------- Protected
/**
* Render the specified Options and return the rendered Options in a StringBuffer.
*
* @param sb
* The StringBuffer to place the rendered Options into.
* @param width
* The number of characters to display per line
* @param options
* The command line Options
* @param leftPad
* the number of characters of padding to be prefixed to each line
* @param descPad
* the number of characters of padding to be prefixed to each description line
*
* @return the StringBuffer with the rendered Options contents.
*/
protected StringBuffer renderOptions(final StringBuffer sb, final int width, final Options options,
final int leftPad, final int descPad) {
final String lpad = createPadding(leftPad);
final String dpad = createPadding(descPad);
// first create list containing only -a,--aaa where
// -a is opt and --aaa is long opt; in parallel look for
// the longest opt string this list will be then used to
// sort options ascending
int max = 0;
final List prefixList = new ArrayList();
final List optList = options.helpOptions();
if (getOptionComparator() != null) {
Collections.sort(optList, getOptionComparator());
}
for (final Option option : optList) {
final StringBuffer optBuf = new StringBuffer();
if (option.getOpt() == null) {
optBuf.append(lpad).append(getLongOptPrefix()).append(option.getLongOpt());
} else {
optBuf.append(lpad).append(getOptPrefix()).append(option.getOpt());
if (option.hasLongOpt()) {
optBuf.append(',').append(getLongOptPrefix()).append(option.getLongOpt());
}
}
if (option.hasArg()) {
final String argName = option.getArgName();
if (argName != null && argName.length() == 0) {
// if the option has a blank argname
optBuf.append(' ');
} else {
optBuf.append(option.hasLongOpt() ? longOptSeparator : " ");
optBuf.append("<").append(argName != null ? option.getArgName() : getArgName()).append(">");
}
}
prefixList.add(optBuf);
max = optBuf.length() > max ? optBuf.length() : max;
}
int x = 0;
for (final Iterator it = optList.iterator(); it.hasNext();) {
final int nextLineTabStop = max + descPad;
final Option option = it.next();
final StringBuilder optBuf = new StringBuilder(prefixList.get(x++).toString());
renderWrappedText(sb, width, nextLineTabStop, optBuf.toString());
if (option.getDescription() != null) {
sb.append(getNewLine());
renderWrappedText(sb, width, descPad, dpad + option.getDescription());
}
if (it.hasNext()) {
sb.append(getNewLine());
}
}
return sb;
}
/**
* Render the specified text and return the rendered Options in a StringBuffer.
*
* @param sb
* The StringBuffer to place the rendered text into.
* @param width
* The number of characters to display per line
* @param nextLineTabStop
* The position on the next line for the first tab.
* @param text
* The text to be rendered.
*
* @return the StringBuffer with the rendered Options contents.
*/
protected StringBuffer renderWrappedText(final StringBuffer sb, final int width, int nextLineTabStop, String text) {
int pos = findWrapPos(text, width, 0);
if (pos == -1) {
sb.append(rtrim(text));
return sb;
}
sb.append(rtrim(text.substring(0, pos))).append(getNewLine());
if (nextLineTabStop >= width) {
// stops infinite loop happening
nextLineTabStop = getDescPadding();
}
// all following lines must be padded with nextLineTabStop space characters
final String padding = createPadding(nextLineTabStop);
while (true) {
text = padding + text.substring(pos).trim();
pos = findWrapPos(text, width, 0);
if (pos == -1) {
sb.append(text);
return sb;
}
if (text.length() > width && pos == nextLineTabStop - 1) {
pos = width;
}
sb.append(rtrim(text.substring(0, pos))).append(getNewLine());
}
}
/**
* Render the specified text width a maximum width. This method differs from renderWrappedText by not removing
* leading spaces after a new line.
*
* @param sb
* The StringBuffer to place the rendered text into.
* @param width
* The number of characters to display per line
* @param nextLineTabStop
* The position on the next line for the first tab.
* @param text
* The text to be rendered.
*/
private Appendable renderWrappedTextBlock(final StringBuffer sb, final int width, final int nextLineTabStop,
final String text) {
try {
final BufferedReader in = new BufferedReader(new StringReader(text));
String line;
boolean firstLine = true;
while ((line = in.readLine()) != null) {
if (!firstLine) {
sb.append(getNewLine());
} else {
firstLine = false;
}
renderWrappedText(sb, width, nextLineTabStop, line);
}
} catch (final IOException e) // NOPMD
{
// cannot happen
}
return sb;
}
/**
* Finds the next text wrap position after startPos
for the text in text
with the column
* width width
. The wrap point is the last position before startPos+width having a whitespace character
* (space, \n, \r). If there is no whitespace character before startPos+width, it will return startPos+width.
*
* @param text
* The text being searched for the wrap position
* @param width
* width of the wrapped text
* @param startPos
* position from which to start the lookup whitespace character
* @return position on which the text must be wrapped or -1 if the wrap position is at the end of the text
*/
protected int findWrapPos(final String text, final int width, final int startPos) {
// the line ends before the max wrap pos or a new line char found
int pos = text.indexOf('\n', startPos);
if (pos != -1 && pos <= width) {
return pos + 1;
}
pos = text.indexOf('\t', startPos);
if (pos != -1 && pos <= width) {
return pos + 1;
}
if (startPos + width >= text.length()) {
return -1;
}
// look for the last whitespace character before startPos+width
for (pos = startPos + width; pos >= startPos; --pos) {
final char c = text.charAt(pos);
if (c == ' ' || c == '\n' || c == '\r') {
break;
}
}
// if we found it - just return
if (pos > startPos) {
return pos;
}
// if we didn't find one, simply chop at startPos+width
pos = startPos + width;
return pos == text.length() ? -1 : pos;
}
/**
* Return a String of padding of length len
.
*
* @param len
* The length of the String of padding to create.
*
* @return The String of padding
*/
protected String createPadding(final int len) {
final char[] padding = new char[len];
Arrays.fill(padding, ' ');
return new String(padding);
}
/**
* Remove the trailing whitespace from the specified String.
*
* @param s
* The String to remove the trailing padding from.
*
* @return The String of without the trailing padding
*/
protected String rtrim(final String s) {
if (s == null || s.length() == 0) {
return s;
}
int pos = s.length();
while (pos > 0 && Character.isWhitespace(s.charAt(pos - 1))) {
--pos;
}
return s.substring(0, pos);
}
// ------------------------------------------------------ Package protected
// ---------------------------------------------------------------- Private
// ---------------------------------------------------------- Inner classes
/**
* This class implements the Comparator
interface for comparing Options.
*/
private static class OptionComparator implements Comparator , Serializable {
/** The serial version UID. */
private static final long serialVersionUID = 5305467873966684014L;
/**
* Compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first
* argument is less than, equal to, or greater than the second.
*
* @param opt1
* The first Option to be compared.
* @param opt2
* The second Option to be compared.
* @return a negative integer, zero, or a positive integer as the first argument is less than, equal to, or
* greater than the second.
*/
@Override
public int compare(final Option opt1, final Option opt2) {
return opt1.getKey().compareToIgnoreCase(opt2.getKey());
}
}
}