diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index 946f9c793..c271f2ceb 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -1,5 +1,16 @@
# picocli Release Notes
+# Picocli 3.0.0-alpha-2 (UNRELEASED)
+## Fixed issues
+
+- [#307] Enhancement: Provide CommandLine.usage(PrintWriter) method for testing and to facilitate migration from commons-cli to picocli.
+
+## Deprecations
+See [3.0.0-alpha-1]()#3.0.0-alpha-1-deprecated)
+
+## Potential breaking changes
+See [3.0.0-alpha-1]()#3.0.0-alpha-1-breaking-changes)
+
# Picocli 3.0.0-alpha-1
The picocli community is pleased to announce picocli 3.0.0-alpha-1.
diff --git a/src/main/java/picocli/CommandLine.java b/src/main/java/picocli/CommandLine.java
index 5ab901bb5..3764a1adf 100644
--- a/src/main/java/picocli/CommandLine.java
+++ b/src/main/java/picocli/CommandLine.java
@@ -15,11 +15,7 @@
*/
package picocli;
-import java.io.File;
-import java.io.FileReader;
-import java.io.LineNumberReader;
-import java.io.PrintStream;
-import java.io.StreamTokenizer;
+import java.io.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -1261,9 +1257,13 @@ public static void usage(Object command, PrintStream out, Help.ColorScheme color
* @param out the printStream to print to
* @see #usage(PrintStream, Help.ColorScheme)
*/
- public void usage(PrintStream out) {
- usage(out, Help.Ansi.AUTO);
- }
+ public void usage(PrintStream out) { usage(out, Help.Ansi.AUTO); }
+ /**
+ * Delegates to {@link #usage(PrintWriter, Help.Ansi)} with the {@linkplain Help.Ansi#AUTO platform default}.
+ * @param writer the PrintWriter to print to
+ * @see #usage(PrintWriter, Help.ColorScheme)
+ * @since 3.0 */
+ public void usage(PrintWriter writer) { usage(writer, Help.Ansi.AUTO); }
/**
* Delegates to {@link #usage(PrintStream, Help.ColorScheme)} with the {@linkplain Help#defaultColorScheme(CommandLine.Help.Ansi) default color scheme}.
@@ -1271,9 +1271,11 @@ public void usage(PrintStream out) {
* @param ansi whether the usage message should include ANSI escape codes or not
* @see #usage(PrintStream, Help.ColorScheme)
*/
- public void usage(PrintStream out, Help.Ansi ansi) {
- usage(out, Help.defaultColorScheme(ansi));
- }
+ public void usage(PrintStream out, Help.Ansi ansi) { usage(out, Help.defaultColorScheme(ansi)); }
+ /** Similar to {@link #usage(PrintStream, Help.Ansi)} but with the specified {@code PrintWriter} instead of a {@code PrintStream}.
+ * @since 3.0 */
+ public void usage(PrintWriter writer, Help.Ansi ansi) { usage(writer, Help.defaultColorScheme(ansi)); }
+
/**
* Prints a usage help message for the annotated command class to the specified {@code PrintStream}.
* Delegates construction of the usage help message to the {@link Help} inner class and is equivalent to:
@@ -1307,9 +1309,15 @@ public void usage(PrintStream out, Help.Ansi ansi) {
* @param colorScheme the {@code ColorScheme} defining the styles for options, parameters and commands when ANSI is enabled
*/
public void usage(PrintStream out, Help.ColorScheme colorScheme) {
- Help help = new Help(getCommandSpec(), colorScheme);
- StringBuilder sb = new StringBuilder()
- .append(help.headerHeading())
+ out.print(usage(new StringBuilder(), new Help(getCommandSpec(), colorScheme)));
+ }
+ /** Similar to {@link #usage(PrintStream, Help.ColorScheme)}, but with the specified {@code PrintWriter} instead of a {@code PrintStream}.
+ * @since 3.0 */
+ public void usage(PrintWriter writer, Help.ColorScheme colorScheme) {
+ writer.print(usage(new StringBuilder(), new Help(getCommandSpec(), colorScheme)));
+ }
+ private static StringBuilder usage(StringBuilder sb, Help help) {
+ return sb.append(help.headerHeading())
.append(help.header())
.append(help.synopsisHeading()) //e.g. Usage:
.append(help.synopsis(help.synopsisHeadingLength())) //e.g. <main class> [OPTIONS] <command> [COMMAND-OPTIONS] [ARGUMENTS]
@@ -1323,7 +1331,6 @@ public void usage(PrintStream out, Help.ColorScheme colorScheme) {
.append(help.commandList()) //e.g. add adds the frup to the frooble
.append(help.footerHeading())
.append(help.footer());
- out.print(sb);
}
/**
diff --git a/src/test/java/picocli/CommandLineHelpTest.java b/src/test/java/picocli/CommandLineHelpTest.java
index 5f7390995..a43cd204d 100644
--- a/src/test/java/picocli/CommandLineHelpTest.java
+++ b/src/test/java/picocli/CommandLineHelpTest.java
@@ -2788,7 +2788,7 @@ class App {
String expected = String.format("" +
"Usage: [-h]%n" +
" -h%n");
- assertEquals(expected, new String(baos.toByteArray(), "UTF-8"));
+ assertEquals(expected, baos.toString());
}
@Test
@@ -2802,7 +2802,7 @@ class App {
assertTrue(CommandLine.printHelpIfRequested(list, new PrintStream(baos), Help.Ansi.OFF));
String expected = String.format("abc 1.2.3 myversion%n");
- assertEquals(expected, new String(baos.toByteArray(), "UTF-8"));
+ assertEquals(expected, baos.toString());
}
@Test
@@ -2815,7 +2815,7 @@ class App {
assertFalse(CommandLine.printHelpIfRequested(list, new PrintStream(baos), Help.Ansi.OFF));
String expected = "";
- assertEquals(expected, new String(baos.toByteArray(), "UTF-8"));
+ assertEquals(expected, baos.toString());
}
@Command(name = "top", subcommands = {Sub.class})
@@ -2903,7 +2903,7 @@ public void testAutoHelpMixinUsageHelpOption() throws Exception {
"Usage: [-hV]%n" +
" -h, --help Show this help message and exit.%n" +
" -V, --version Print version information and exit.%n");
- assertEquals(expected, new String(baos.toByteArray(), "UTF-8"));
+ assertEquals(expected, baos.toString());
}
}
@@ -2920,7 +2920,7 @@ public void testAutoHelpMixinVersionHelpOption() throws Exception {
assertTrue(CommandLine.printHelpIfRequested(list, new PrintStream(baos), Help.Ansi.OFF));
String expected = String.format("1.2.3%n");
- assertEquals(expected, new String(baos.toByteArray(), "UTF-8"));
+ assertEquals(expected, baos.toString());
}
}
@@ -2939,7 +2939,7 @@ public void testAutoHelpMixinUsageHelpSubcommandOnAppWithoutSubcommands() throws
" -V, --version Print version information and exit.%n" +
"Commands:%n" +
" help Displays help information about the specified command%n");
- assertEquals(expected, new String(baos.toByteArray(), "UTF-8"));
+ assertEquals(expected, baos.toString());
}
@Test
@@ -2956,7 +2956,7 @@ class App implements Runnable{ public void run(){}}
" -V, --version Print version information and exit.%n" +
"Commands:%n" +
" help Displays help information about the specified command%n");
- assertEquals(expected, new String(baos.toByteArray(), "UTF-8"));
+ assertEquals(expected, baos.toString());
}
@Test
public void testHelpSubcommandWithValidCommand() throws Exception {
@@ -2968,7 +2968,7 @@ public void testHelpSubcommandWithValidCommand() throws Exception {
String expected = String.format("" +
"Usage: sub%n" +
"This is a subcommand%n");
- assertEquals(expected, new String(baos.toByteArray(), "UTF-8"));
+ assertEquals(expected, baos.toString());
}
@Test
@@ -2987,7 +2987,7 @@ class App implements Runnable{ public void run(){}}
"Commands:%n" +
" sub This is a subcommand%n" +
" help Displays help information about the specified command%n");
- assertEquals(expected, new String(baos.toByteArray(), "UTF-8"));
+ assertEquals(expected, baos.toString());
}
@Test
@@ -3008,7 +3008,11 @@ class App implements Runnable{ public void run(){}}
"%n" +
" [COMMAND]... The COMMAND to display the usage help message for.%n" +
" -h, --help Show usage help for the help command and exit.%n");
- assertEquals(expected, new String(baos.toByteArray(), "UTF-8"));
+ assertEquals(expected, baos.toString());
+
+ StringWriter sw = new StringWriter();
+ new CommandLine(new App()).getSubcommands().get("help").usage(new PrintWriter(sw));
+ assertEquals(expected, sw.toString());
}
@Test
@@ -3026,7 +3030,11 @@ class App implements Runnable{ public void run(){}}
"Commands:%n" +
" sub This is a subcommand%n" +
" help Displays help information about the specified command%n");
- assertEquals(expected, new String(baos.toByteArray(), "UTF-8"));
+ assertEquals(expected, baos.toString());
+
+ StringWriter sw = new StringWriter();
+ new CommandLine(new App()).usage(new PrintWriter(sw));
+ assertEquals(expected, sw.toString());
}
@Test
@@ -3043,7 +3051,7 @@ public void testUsageTextWithHiddenSubcommand() throws Exception {
"Usage: app%n" +
"Commands:%n" +
" foo This is a visible subcommand%n");
- assertEquals(expected, new String(baos.toByteArray(), "UTF-8"));
+ assertEquals(expected, baos.toString());
}
@Test
@@ -3061,7 +3069,7 @@ public void testUsage_NoHeaderIfAllSubcommandHidden() throws Exception {
String expected = format("" +
"Usage: app%n");
- assertEquals(expected, new String(baos.toByteArray(), "UTF-8"));
+ assertEquals(expected, baos.toString());
}
@Test
@@ -3080,7 +3088,7 @@ public void run() { }
"Missing required parameters at positions 0..*: FILES%n" +
"Usage: FILES...%n" +
" FILES... List of files%n");
- assertEquals(expected, new String(baos.toByteArray(), "UTF-8"));
+ assertEquals(expected, baos.toString());
}
@Test
@@ -3103,7 +3111,7 @@ public void run() { }
"Usage: [-v] FILES...%n" +
" FILES... List of files%n" +
" -v Print output%n");
- assertEquals(expected, new String(baos.toByteArray(), "UTF-8"));
+ assertEquals(expected, baos.toString());
}
@Test