Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions src/main/java/org/apache/commons/cli/HelpFormatter.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

/**
Expand Down Expand Up @@ -78,12 +78,12 @@ public static final class Builder implements Supplier<HelpFormatter> {
/**
* A function to convert a description (not null) and a deprecated Option (not null) to help description
*/
private static final BiFunction<String, Option, String> DEFAULT_DEPRECATED_FORMAT = (d, o) -> "[Deprecated] " + d;
private static final Function<Option, String> DEFAULT_DEPRECATED_FORMAT = o -> "[Deprecated] " + getDescription(o);

/**
* Formatter for deprecated options.
*/
private BiFunction<String, Option, String> deprecatedFormatFunc = DEFAULT_DEPRECATED_FORMAT;
private Function<Option, String> deprecatedFormatFunc = DEFAULT_DEPRECATED_FORMAT;

/**
* The output PrintWriter, defaults to wrapping {@link System#out}.
Expand Down Expand Up @@ -113,7 +113,7 @@ public Builder setPrintWriter(final PrintWriter printWriter) {
* @return this.
* @since 1.8.0
*/
public Builder setShowDeprecated(final BiFunction<String, Option, String> showDeprecatedFunc) {
public Builder setShowDeprecated(final Function<Option, String> showDeprecatedFunc) {
this.deprecatedFormatFunc = showDeprecatedFunc;
return this;
}
Expand All @@ -129,6 +129,16 @@ public Builder setShowDeprecated(final boolean useDefaultFormat) {
}
}

/**
* Gets the option description or an empty string if the description is {@code null}.
* @param option The option to get the description from.
* @return the option description or an empty string if the description is {@code null}.
* @since 1.8.0
*/

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • New public and protected elements need Javadoc since tags.
  • In Javadoc, a foo getter methods "Gets foo..." (I've tried to be consistent with this in Commons.)

public static String getDescription(final Option option) {
String desc = option.getDescription();
return desc == null ? "" : desc;
}
/**
* This class implements the {@code Comparator} interface for comparing Options.
*/
Expand Down Expand Up @@ -266,9 +276,9 @@ private static PrintWriter createDefaultPrintWriter() {
protected Comparator<Option> optionComparator = new OptionComparator();

/**
* BiFunction to format the description for a deprecated option.
* Function to format the description for a deprecated option.
*/
private final BiFunction<String, Option, String> deprecatedFormatFunc;
private final Function<Option, String> deprecatedFormatFunc;
Comment thread
garydgregory marked this conversation as resolved.

/**
* Where to print help.
Expand All @@ -291,7 +301,7 @@ public HelpFormatter() {
* Constructs a new instance.
* @param printStream TODO
*/
private HelpFormatter(final BiFunction<String, Option, String> deprecatedFormatFunc, final PrintWriter printStream) {
private HelpFormatter(final Function<Option, String> deprecatedFormatFunc, final PrintWriter printStream) {
// TODO All other instance HelpFormatter instance variables.
// Make HelpFormatter immutable for 2.0
this.deprecatedFormatFunc = deprecatedFormatFunc;
Expand Down Expand Up @@ -795,7 +805,7 @@ protected StringBuffer renderOptions(final StringBuffer sb, final int width, fin
optBuf.append(dpad);
final int nextLineTabStop = max + descPad;
if (deprecatedFormatFunc != null && option.isDeprecated()) {
optBuf.append(deprecatedFormatFunc.apply(option.getDescription() == null ? "" : option.getDescription(), option).trim());
optBuf.append(deprecatedFormatFunc.apply(option).trim());
} else if (option.getDescription() != null) {
optBuf.append(option.getDescription());
}
Expand Down
232 changes: 113 additions & 119 deletions src/site/xdoc/usage.xml
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ try {
}
catch (ParseException exp) {
System.out.println("Unexpected exception:" + exp.getMessage());
}</source>
} </source>
</section>
<section name="Converting (Parsing) Option Values">
<p>
Expand All @@ -392,31 +392,30 @@ catch (ParseException exp) {
that the "count" option should return an Integer the following code could be used:
</p>
<source>
public static void main(String[] args) {
Option count = Option.builder("count")
.hasArg()
.desc("the number of things")
.type(Integer.class)
.build();
Options options = new Options().addOption(count);
// create the parser
CommandLineParser parser = new DefaultParser();
try {
// parse the command line arguments
CommandLine line = parser.parse(options, args);
}
catch (ParseException exp) {
// oops, something went wrong
System.err.println("Parsing failed. Reason: " + exp.getMessage());
}

try {
Integer value = line.getParsedOptionValue(count);
System.out.format("The value is %s\m", value );
} catch (ParseException e) {
e.printStackTrace();
}
}</source>
public static void main(String[] args) {
Option count = Option.builder("count")
.hasArg()
.desc("the number of things")
.type(Integer.class)
.build();
Options options = new Options().addOption(count);
// create the parser
CommandLineParser parser = new DefaultParser();
try {
// parse the command line arguments
CommandLine line = parser.parse(options, args);
} catch (ParseException exp) {
// oops, something went wrong
System.err.println("Parsing failed. Reason: " + exp.getMessage());
}

try {
Integer value = line.getParsedOptionValue(count);
System.out.format("The value is %s%n", value );
} catch (ParseException e) {
e.printStackTrace();
}
} </source>
<p>
The value types natively supported by commons-cli are:
<ul>
Expand Down Expand Up @@ -446,12 +445,11 @@ catch (ParseException exp) {
Conversions can be specified without using the <code>TypeHandler</code> class by specifying the converter
directly during the option build. For example:
<source>
Option fooOpt = Option.builder("foo")
.hasArg()
.desc("the foo arg")
.converter((s) -> new Foo(s))
.build();
</source>
Option fooOpt = Option.builder("foo")
.hasArg()
.desc("the foo arg")
.converter(Foo::new)
.build();</source>
The above will create an option that passes the string value to the Foo constructor when <code>commandLine.getParsedOptionValue(fooOpt)</code> is called.
</p>
<p>
Expand All @@ -466,145 +464,141 @@ catch (ParseException exp) {
<code>deprecated</code> method.

Usage of the deprecated option is announced when the presence of the option is checked
or the value of the option is retrieved. By default the announcement printed to Standard out.
or the value of the option is retrieved. By default, the announcement printed to Standard out.

The HelpFormatter output will be default show the description prefixed by "[Deprecated]"
The HelpFormatter output will by default show the description prefixed by "[Deprecated]"
</p>
<p>
The examples below will implement <code>doSomething</code> in the following code block.
<source>
public static void main(String[] args) {
Option n = Option.builder("n")
.deprecated(DeprecatedAttributes.builder()
.setDescription("Use '-count' instead")
.setForRemoval(true)
.setSince("now").get())
.hasArg()
.desc("the number of things")
.type(Integer.class)
.build();
Option count = Option.builder("count")
.hasArg()
.desc("the number of things")
.type(Integer.class)
.build();
Options options = new Options().addOption(n).addOption(count);
public static void main(String[] args) {
Option n = Option.builder("n")
.deprecated(DeprecatedAttributes.builder()
.setDescription("Use '-count' instead")
.setForRemoval(true)
.setSince("now").get())
.hasArg()
.desc("the number of things")
.type(Integer.class)
.build();
Option count = Option.builder("count")
.hasArg()
.desc("the number of things")
.type(Integer.class)
Comment thread
garydgregory marked this conversation as resolved.
.build();
Options options = new Options().addOption(n).addOption(count);

doSomething(options);
}
</source>
doSomething(options);
} </source>
</p>

<subsection name="Changing Usage Announcement">
<p>
The usage announcement may be changed by providing a <code>Consumer&gt;Option&lt;></code> to the
<code>CommandLine.Builder.deprecatedHandler</code> method.
The usage announcement may be changed by providing a <code>Consumer&lt;Option></code> to the
<code>CommandLine.Builder.deprecatedHandler</code> method. This is commonly used to log usage
of deprecated options rather than printing them on the standard output.
</p>
<p>
for example if <code>doSomething</code> is implemented as:
</p>
<sorce>
void doSomething(Options options) {
CommandLineParser parser = new DefaultParser();
CommandLine line;
try {
// parse the command line arguments
line = parser.parse(options, new String[] {"-n", "5"});
System.out.println( "n="+line.getParsedOptionValue("n"));
} catch (ParseException exp) {
// oops, something went wrong
System.err.println("Parsing failed. Reason: " + exp.getMessage());
}
}
</sorce>
<source>
void doSomething(Options options) {
CommandLineParser parser = new DefaultParser();
CommandLine line;
try {
// parse the command line arguments
line = parser.parse(options, new String[] {"-n", "5"});
System.out.println("n=" + line.getParsedOptionValue("n"));
} catch (ParseException exp) {
// oops, something went wrong
System.err.println("Parsing failed. Reason: " + exp.getMessage());
}
} </source>
<p>
The output of the run would be.
</p>

<source>
Option 'n': Deprecated for removal since now: Use '-count' instead
n=5
</source>
Option 'n': Deprecated for removal since now: Use '-count' instead
n=5 </source>

<p>
for example if <code>doSomething</code> is implemented as:
</p>

<source>
void doSomething(Options options) {
Consumer&gt;Option&lt; deprecatedUsageAnnouncement = o -> {
final StringBuilder buf = new StringBuilder()
.append("'")
.append(o.getOpt())
.append("'");
if (o.getLongOpt() != null) {
buf.append("'").append(o.getLongOpt()).append("'");
}
System.err.printf("ERROR: Option %s: %s%n", buf, o.getDeprecated());
};
DefaultParser parser = DefaultParser.builder().setDeprecatedHandler(deprecatedUsageAnnouncement).build();
CommandLine line;
try {
// parse the command line arguments
line = parser.parse(options, new String[] {"-n", "5"});
System.out.println( "n="+line.getParsedOptionValue("n"));
} catch (ParseException exp) {
// oops, something went wrong
System.err.println("Parsing failed. Reason: " + exp.getMessage());
}
}
</source>
void doSomething(Options options) {
Consumer&lt;Option> deprecatedUsageAnnouncement = o -> {
final StringBuilder buf = new StringBuilder()
.append("'")
.append(o.getOpt())
.append("'");
if (o.getLongOpt() != null) {
buf.append("'").append(o.getLongOpt()).append("'");
}
System.err.printf("ERROR: Option %s: %s%n", buf, o.getDeprecated());
};
DefaultParser parser = DefaultParser.builder().setDeprecatedHandler(deprecatedUsageAnnouncement).build();
CommandLine line;
try {
// parse the command line arguments
line = parser.parse(options, new String[] {"-n", "5"});
System.out.println("n=" + line.getParsedOptionValue("n"));
} catch (ParseException exp) {
// oops, something went wrong
System.err.println("Parsing failed. Reason: " + exp.getMessage());
}
} </source>
<p>
The output of the run would be.
</p>
<source>
ERROR: Option 'n': Deprecated for removal since now: Use '-count' instead
n=5
</source>
ERROR: Option 'n': Deprecated for removal since now: Use '-count' instead
n=5 </source>
<p>
However, the first line would be printed on system err instead of system out.
</p>

</subsection>
<subsection name="Changing help format">
<p>By default the help formater prints "[Deprecated]" in front of the description for the option. This can
be changed to display any values desired.
</p>
<p>
If <code>doSomething</code> is implemented as:
<source>
void doSomething(Options options) {
HelpFormatter formatter = HelpFormatter.builder().get();
formatter.printHelp("Command line syntax:", options);
}
</source>
void doSomething(Options options) {
HelpFormatter formatter = HelpFormatter.builder().get();
formatter.printHelp("Command line syntax:", options);
} </source>
To output is
<source>
usage: Command line syntax:
-count &lt;arg> the number of things
-n &lt;arg> [Deprecated] the number of things
</source>
usage: Command line syntax:
-count &lt;arg> the number of things
-n &lt;arg> [Deprecated] the number of things</source>
</p>
<p>
The display of deprecated options may be changed through the use of the
<code>HelpFormatter.Builder.setShowDeprecated()</code> method.
<ul>
<li>Calling <code>HelpFormatter.Builder.setShowDeprecated(false)</code> will disable the "[Deprecated]" tag.</li>
<li>Calling <code>HelpFormatter.Builder.setShowDeprecated</code> with a <code>BiFunction&lt;String, Option, String></code>
<li>Calling <code>HelpFormatter.Builder.setShowDeprecated</code> with a <code>Function&lt;Option, String></code>
will use the output of the function as the description for the option.</li>
</ul>
As an example of the second case above, changing the implementation of <code>doSomething</code> to
<source>
void doSomething(Options options) {
BiFunction&lt;String, Option, String> disp = (desc, option) -> String.format( "%s. %s", desc, option.getDeprecated().toString());
HelpFormatter formatter = HelpFormatter.builder().setShowDeprecated(disp).get();
formatter.printHelp("Command line syntax:", options);
}
</source>
void doSomething(Options options) {
Function&lt;Option, String> disp = option -> String.format("%s. %s", HelpFormatter.getDescription(option),
option.getDeprecated().toString());
HelpFormatter formatter = HelpFormatter.builder().setShowDeprecated(disp).get();
formatter.printHelp("Command line syntax:", options);
} </source>
changes the output to
<source>
usage: Command line syntax:
-count &lt;arg> the number of things
-n &lt;arg> the number of things. Deprecated for removal since now:
Use '-count' instead
</source>
usage: Command line syntax:
-count &lt;arg> the number of things
-n &lt;arg> the number of things. Deprecated for removal since now:
Use '-count' instead</source>
</p>
</subsection>
</section>
Expand Down
Loading