Skip to content

Commit 7aac2dd

Browse files
[CLI-332] Add optional HelpFormatter Function to document Deprecated options (#271)
* added ability to display deprecation information in help output * fixed checkstyle errors * added since annotation to new method * Fix Javadoc --------- Co-authored-by: Gary Gregory <garydgregory@users.noreply.github.com>
1 parent 2130068 commit 7aac2dd

2 files changed

Lines changed: 90 additions & 19 deletions

File tree

src/main/java/org/apache/commons/cli/HelpFormatter.java

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more
3030
import java.util.Iterator;
3131
import java.util.List;
3232
import java.util.Objects;
33+
import java.util.function.BiFunction;
3334
import java.util.function.Supplier;
3435

3536
/**
@@ -75,9 +76,14 @@ public static final class Builder implements Supplier<HelpFormatter> {
7576
// Make HelpFormatter immutable for 2.0
7677

7778
/**
78-
* Whether to show deprecated options.
79+
* A function to convert a description (not null) and a deprecated Option (not null) to help description
7980
*/
80-
private boolean showDeprecated;
81+
private static final BiFunction<String, Option, String> DEFAULT_DEPRECATED_FORMAT = (d, o) -> "[Deprecated] " + d;
82+
83+
/**
84+
* Formatter for deprecated options.
85+
*/
86+
private BiFunction<String, Option, String> deprecatedFormatFunc;
8187

8288
/**
8389
* The output PrintWriter, defaults to wrapping {@link System#out}.
@@ -86,7 +92,7 @@ public static final class Builder implements Supplier<HelpFormatter> {
8692

8793
@Override
8894
public HelpFormatter get() {
89-
return new HelpFormatter(showDeprecated, printStream);
95+
return new HelpFormatter(deprecatedFormatFunc, printStream);
9096
}
9197

9298
/**
@@ -103,14 +109,24 @@ public Builder setPrintWriter(final PrintWriter printWriter) {
103109
/**
104110
* Sets whether to show deprecated options.
105111
*
106-
* @param showDeprecated Whether to show deprecated options.
112+
* @param useDefaultFormat if {@code true} use the default format, otherwise clear the formatter.
107113
* @return this.
108114
*/
109-
public Builder setShowDeprecated(final boolean showDeprecated) {
110-
this.showDeprecated = showDeprecated;
111-
return this;
115+
public Builder setShowDeprecated(final boolean useDefaultFormat) {
116+
return setShowDeprecated(useDefaultFormat ? DEFAULT_DEPRECATED_FORMAT : null);
112117
}
113118

119+
/**
120+
* Sets whether to show deprecated options.
121+
*
122+
* @param showDeprecatedFunc Specify the format for the deprecated options.
123+
* @return this.
124+
* @since 1.8.0
125+
*/
126+
public Builder setShowDeprecated(final BiFunction<String, Option, String> showDeprecatedFunc) {
127+
this.deprecatedFormatFunc = showDeprecatedFunc;
128+
return this;
129+
}
114130
}
115131

116132
/**
@@ -250,9 +266,9 @@ private static PrintWriter createDefaultPrintWriter() {
250266
protected Comparator<Option> optionComparator = new OptionComparator();
251267

252268
/**
253-
* Whether to show deprecated options.
269+
* BiFunction to format the description for a deprecated option.
254270
*/
255-
private final boolean showDeprecated;
271+
private final BiFunction<String, Option, String> deprecatedFormatFunc;
256272

257273
/**
258274
* Where to print help.
@@ -268,17 +284,17 @@ private static PrintWriter createDefaultPrintWriter() {
268284
* Constructs a new instance.
269285
*/
270286
public HelpFormatter() {
271-
this(false, createDefaultPrintWriter());
287+
this(null, createDefaultPrintWriter());
272288
}
273289

274290
/**
275291
* Constructs a new instance.
276292
* @param printStream TODO
277293
*/
278-
private HelpFormatter(final boolean showDeprecated, final PrintWriter printStream) {
294+
private HelpFormatter(final BiFunction<String, Option, String> deprecatedFormatFunc, final PrintWriter printStream) {
279295
// TODO All other instance HelpFormatter instance variables.
280296
// Make HelpFormatter immutable for 2.0
281-
this.showDeprecated = showDeprecated;
297+
this.deprecatedFormatFunc = deprecatedFormatFunc;
282298
this.printWriter = printStream;
283299
}
284300

@@ -778,13 +794,9 @@ protected StringBuffer renderOptions(final StringBuffer sb, final int width, fin
778794
}
779795
optBuf.append(dpad);
780796
final int nextLineTabStop = max + descPad;
781-
if (showDeprecated && option.isDeprecated()) {
782-
optBuf.append("[Deprecated]");
783-
}
784-
if (option.getDescription() != null) {
785-
if (showDeprecated && option.isDeprecated()) {
786-
optBuf.append(' ');
787-
}
797+
if (deprecatedFormatFunc != null && option.isDeprecated()) {
798+
optBuf.append(deprecatedFormatFunc.apply(option.getDescription() == null ? "" : option.getDescription(), option).trim());
799+
} else if (option.getDescription() != null) {
788800
optBuf.append(option.getDescription());
789801
}
790802
renderWrappedText(sb, width, nextLineTabStop, optBuf.toString());

src/test/java/org/apache/commons/cli/HelpFormatterTest.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,15 @@ Licensed to the Apache Software Foundation (ASF) under one or more
2424
import java.io.ByteArrayOutputStream;
2525
import java.io.PrintWriter;
2626
import java.io.StringWriter;
27+
import java.util.ArrayList;
28+
import java.util.List;
29+
import java.util.stream.Stream;
2730

2831
import org.apache.commons.cli.HelpFormatter.Builder;
2932
import org.junit.jupiter.api.Test;
33+
import org.junit.jupiter.params.ParameterizedTest;
34+
import org.junit.jupiter.params.provider.Arguments;
35+
import org.junit.jupiter.params.provider.MethodSource;
3036

3137
/**
3238
* Test case for the HelpFormatter class.
@@ -484,6 +490,59 @@ public void testPrintOptions() {
484490
assertEquals(expected, sb.toString(), "multiple wrapped options");
485491
}
486492

493+
@ParameterizedTest
494+
@MethodSource("deprecatedOptionsProvider")
495+
public void testPrintDeprecatedOptions(final HelpFormatter hf, final Option option, final String expectedTxt) {
496+
final StringBuffer sb = new StringBuffer();
497+
498+
final int leftPad = 1;
499+
final int descPad = 3;
500+
final String lpad = hf.createPadding(leftPad);
501+
final String dpad = hf.createPadding(descPad);
502+
Options options;
503+
String expected = lpad + "-a,--aaa";
504+
505+
options = new Options().addOption(option);
506+
if (expectedTxt.length() > 0) {
507+
expected = expected + dpad + expectedTxt;
508+
}
509+
hf.renderOptions(sb, 160, options, leftPad, descPad);
510+
assertEquals(expected, sb.toString());
511+
}
512+
513+
static Stream<Arguments> deprecatedOptionsProvider() {
514+
List<Arguments> lst = new ArrayList<>();
515+
Option option = Option.builder("a").longOpt("aaa").desc("dddd dddd dddd")
516+
.deprecated(DeprecatedAttributes.builder().setForRemoval(true).setSince("now")
517+
.setDescription("Why why why").get())
518+
.build();
519+
520+
HelpFormatter hf = HelpFormatter.builder().setShowDeprecated(false).get();
521+
lst.add(Arguments.of(hf, option, "dddd dddd dddd"));
522+
523+
hf = HelpFormatter.builder().setShowDeprecated(true).get();
524+
lst.add(Arguments.of(hf, option, "[Deprecated] dddd dddd dddd"));
525+
526+
hf = HelpFormatter.builder().setShowDeprecated((d, o) -> String.format("%s [%s]", d, o.getDeprecated())).get();
527+
lst.add(Arguments.of(hf, option, "dddd dddd dddd [Deprecated for removal since now: Why why why]"));
528+
529+
option = Option.builder("a").longOpt("aaa")
530+
.deprecated(DeprecatedAttributes.builder().setForRemoval(true).setSince("now")
531+
.setDescription("Why why why").get())
532+
.build();
533+
534+
hf = HelpFormatter.builder().setShowDeprecated(false).get();
535+
lst.add(Arguments.of(hf, option, ""));
536+
537+
hf = HelpFormatter.builder().setShowDeprecated(true).get();
538+
lst.add(Arguments.of(hf, option, "[Deprecated]"));
539+
540+
hf = HelpFormatter.builder().setShowDeprecated((d, o) -> String.format("%s [%s]", d, o.getDeprecated())).get();
541+
lst.add(Arguments.of(hf, option, "[Deprecated for removal since now: Why why why]"));
542+
543+
return lst.stream();
544+
}
545+
487546
@Test
488547
public void testPrintOptionWithEmptyArgNameUsage() {
489548
final Option option = new Option("f", true, null);

0 commit comments

Comments
 (0)