private void printUsageMessage(UsageMessageSpec usageMessage, PrintWriter pw, String indent) { pw.printf("%sUsageMessageSpec:%n", indent); indent += " "; pw.printf("%swidth: %s%n", indent, usageMessage.width()); pw.printf("%sabbreviateSynopsis: %s%n", indent, usageMessage.abbreviateSynopsis()); pw.printf("%shidden: %s%n", indent, usageMessage.hidden()); pw.printf("%sshowDefaultValues: %s%n", indent, usageMessage.showDefaultValues()); pw.printf("%ssortOptions: %s%n", indent, usageMessage.sortOptions()); pw.printf("%srequiredOptionMarker: '%s'%n", indent, usageMessage.requiredOptionMarker()); pw.printf("%sheaderHeading: '%s'%n", indent, usageMessage.headerHeading()); pw.printf("%sheader: %s%n", indent, Arrays.toString(usageMessage.header())); pw.printf("%ssynopsisHeading: '%s'%n", indent, usageMessage.synopsisHeading()); pw.printf("%scustomSynopsis: %s%n", indent, Arrays.toString(usageMessage.customSynopsis())); pw.printf("%sdescriptionHeading: '%s'%n", indent, usageMessage.descriptionHeading()); pw.printf("%sdescription: %s%n", indent, Arrays.toString(usageMessage.description())); pw.printf("%sparameterListHeading: '%s'%n", indent, usageMessage.parameterListHeading()); pw.printf("%soptionListHeading: '%s'%n", indent, usageMessage.optionListHeading()); pw.printf("%scommandListHeading: '%s'%n", indent, usageMessage.commandListHeading()); pw.printf("%sfooterHeading: '%s'%n", indent, usageMessage.footerHeading()); pw.printf("%sfooter: %s%n", indent, Arrays.toString(usageMessage.footer())); }
@Test public void testDefaultOptionRenderer_rendersSpacePrefixByDefaultForRequiredOptionsWithDefaultValue() { //@Command(showDefaultValues = true) // set programmatically class Example { @Option(names = {"-b", "-a", "--alpha"}, required = true, description = "other") String otherField; } Help help = new Help(new Example()); help.commandSpec().usageMessage().showDefaultValues(true); Help.IOptionRenderer renderer = help.createDefaultOptionRenderer(); Help.IParamLabelRenderer parameterRenderer = help.createDefaultParamLabelRenderer(); OptionSpec option = help.options().get(0); Text[][] row = renderer.render(option, parameterRenderer, help.colorScheme()); assertEquals(1, row.length); assertArrayEquals(Arrays.toString(row[0]), textArray(help, " ", "-b", ",", "-a, --alpha=<otherField>", "other"), row[0]); // assertArrayEquals(Arrays.toString(row[1]), textArray(help, "", "", "", "", " Default: null"), row[1]); // #201 don't show null defaults }
@Test public void testPositionalParamSpec_defaultValue_overwritesInitialValue() { @Command(showDefaultValues = true) class Params { @Parameters(paramLabel = "INT", description = "the array") int[] value = {1, 5, 11, 23}; } CommandLine cmd = new CommandLine(new Params()); PositionalParamSpec x = cmd.getCommandSpec().positionalParameters().get(0).toBuilder().defaultValue("5,4,3,2,1").splitRegex(",").build(); cmd = new CommandLine(CommandSpec.create().add(x)); cmd.getCommandSpec().usageMessage().showDefaultValues(true); String result = usageString(cmd, Help.Ansi.OFF); assertEquals(format("" + "Usage: <main class> [INT[,INT...]...]%n" + " [INT[,INT...]...] the array%n" + " Default: 5,4,3,2,1%n"), result); }
@Test public void testDefaultOptionRenderer_rendersCommaOnlyIfBothShortAndLongOptionNamesExist() { class Example { @Option(names = {"-v"}, description = "shortBool") boolean shortBoolean; @Option(names = {"--verbose"}, description = "longBool") boolean longBoolean; @Option(names = {"-x", "--xeno"}, description = "combiBool") boolean combiBoolean; @Option(names = {"-s"}, description = "shortOnly") String shortOnlyField; @Option(names = {"--long"}, description = "longOnly") String longOnlyField; @Option(names = {"-b", "--beta"}, description = "combi") String combiField; } Help help = new Help(new Example()); help.commandSpec().usageMessage().showDefaultValues(false); // omit default values from description column Help.IOptionRenderer renderer = help.createDefaultOptionRenderer(); Help.IParamLabelRenderer parameterRenderer = help.createDefaultParamLabelRenderer(); String[][] expected = new String[][] { {"", "-v", "", "", "shortBool"}, {"", "", "", "--verbose", "longBool"}, {"", "-x", ",", "--xeno", "combiBool"}, {"", "-s", "=", "<shortOnlyField>", "shortOnly"}, {"", "", "", "--long=<longOnlyField>", "longOnly"}, {"", "-b", ",", "--beta=<combiField>", "combi"}, }; int i = -1; for (OptionSpec option : help.options()) { Text[][] row = renderer.render(option, parameterRenderer, help.colorScheme()); assertEquals(1, row.length); assertArrayEquals(Arrays.toString(row[0]), textArray(help, expected[++i]), row[0]); } }
void initFromMixin(UsageMessageSpec mixin, CommandSpec commandSpec) { if (initializable(synopsisHeading, mixin.synopsisHeading(), DEFAULT_SYNOPSIS_HEADING)) {synopsisHeading = mixin.synopsisHeading();} if (initializable(commandListHeading, mixin.commandListHeading(), DEFAULT_COMMAND_LIST_HEADING)) {commandListHeading = mixin.commandListHeading();} if (initializable(requiredOptionMarker, mixin.requiredOptionMarker(), DEFAULT_REQUIRED_OPTION_MARKER)) {requiredOptionMarker = mixin.requiredOptionMarker();} if (initializable(abbreviateSynopsis, mixin.abbreviateSynopsis(), DEFAULT_ABBREVIATE_SYNOPSIS)) {abbreviateSynopsis = mixin.abbreviateSynopsis();} if (initializable(sortOptions, mixin.sortOptions(), DEFAULT_SORT_OPTIONS)) {sortOptions = mixin.sortOptions();} if (initializable(showDefaultValues, mixin.showDefaultValues(), DEFAULT_SHOW_DEFAULT_VALUES)) {showDefaultValues = mixin.showDefaultValues();} if (initializable(hidden, mixin.hidden(), DEFAULT_HIDDEN)) {hidden = mixin.hidden();} if (initializable(customSynopsis, mixin.customSynopsis(), DEFAULT_MULTI_LINE)) {customSynopsis = mixin.customSynopsis().clone();} if (initializable(description, mixin.description(), DEFAULT_MULTI_LINE)) {description = mixin.description().clone();} if (initializable(descriptionHeading, mixin.descriptionHeading(), DEFAULT_SINGLE_VALUE)) {descriptionHeading = mixin.descriptionHeading();} if (initializable(header, mixin.header(), DEFAULT_MULTI_LINE)) {header = mixin.header().clone();} if (initializable(headerHeading, mixin.headerHeading(), DEFAULT_SINGLE_VALUE)) {headerHeading = mixin.headerHeading();} if (initializable(footer, mixin.footer(), DEFAULT_MULTI_LINE)) {footer = mixin.footer().clone();} if (initializable(footerHeading, mixin.footerHeading(), DEFAULT_SINGLE_VALUE)) {footerHeading = mixin.footerHeading();} if (initializable(parameterListHeading, mixin.parameterListHeading(), DEFAULT_SINGLE_VALUE)) {parameterListHeading = mixin.parameterListHeading();} if (initializable(optionListHeading, mixin.optionListHeading(), DEFAULT_SINGLE_VALUE)) {optionListHeading = mixin.optionListHeading();} if (Messages.empty(messages)) { messages(Messages.copy(commandSpec, mixin.messages())); } } void initFrom(UsageMessageSpec settings, CommandSpec commandSpec) {
/** Returns a new default OptionRenderer which converts {@link OptionSpec Options} to five columns of text to match * the default {@linkplain TextTable TextTable} column layout. The first row of values looks like this: * <ol> * <li>the required option marker</li> * <li>2-character short option name (or empty string if no short option exists)</li> * <li>comma separator (only if both short option and long option exist, empty string otherwise)</li> * <li>comma-separated string with long option name(s)</li> * <li>first element of the {@link OptionSpec#description()} array</li> * </ol> * <p>Following this, there will be one row for each of the remaining elements of the {@link * OptionSpec#description()} array, and these rows look like {@code {"", "", "", "", option.description()[i]}}.</p> * <p>If configured, this option renderer adds an additional row to display the default field value.</p> * @return a new default OptionRenderer */ public IOptionRenderer createDefaultOptionRenderer() { return new DefaultOptionRenderer(commandSpec.usageMessage.showDefaultValues(), "" +commandSpec.usageMessage().requiredOptionMarker()); } /** Returns a new minimal OptionRenderer which converts {@link OptionSpec Options} to a single row with two columns
@Test public void testPositionalParamSpec_defaultValue_overwritesInitialValue() { @Command(showDefaultValues = true) class Params { @Parameters(paramLabel = "INT", description = "the array") int[] value = {1, 5, 11, 23}; } CommandLine cmd = new CommandLine(new Params()); PositionalParamSpec x = cmd.getCommandSpec().positionalParameters().get(0).toBuilder().defaultValue("5,4,3,2,1").splitRegex(",").build(); cmd = new CommandLine(CommandSpec.create().add(x)); cmd.getCommandSpec().usageMessage().showDefaultValues(true); String result = usageString(cmd, Help.Ansi.OFF); assertEquals(format("" + "Usage: <main class> [INT[,INT...]...]%n" + " [INT[,INT...]...] the array%n" + " Default: 5,4,3,2,1%n"), result); }
@Test public void testOptionSpec_defaultValue_overwritesInitialValue() { @Command(showDefaultValues = true) class Params { @Option(names = {"-x", "--array"}, required = true, paramLabel = "INT", description = "the array") int[] array = {1, 5, 11, 23}; } CommandLine cmd = new CommandLine(new Params()); OptionSpec x = cmd.getCommandSpec().posixOptionsMap().get('x').toBuilder().defaultValue("5,4,3,2,1").splitRegex(",").build(); cmd = new CommandLine(CommandSpec.create().addOption(x)); cmd.getCommandSpec().usageMessage().showDefaultValues(true); String result = usageString(cmd, Help.Ansi.OFF); assertEquals(format("" + "Usage: <main class> [-x=INT[,INT...]]...%n" + " -x, --array=INT[,INT...] the array%n" + " Default: 5,4,3,2,1%n"), result); }
/** Returns a new default ParameterRenderer which converts {@linkplain PositionalParamSpec positional parameters} to four columns of * text to match the default {@linkplain TextTable TextTable} column layout. The first row of values looks like this: * <ol> * <li>empty string </li> * <li>empty string </li> * <li>parameter(s) label as rendered by the {@link IParamLabelRenderer}</li> * <li>first element of the {@link PositionalParamSpec#description()} array</li> * </ol> * <p>Following this, there will be one row for each of the remaining elements of the {@link * PositionalParamSpec#description()} array, and these rows look like {@code {"", "", "", param.description()[i]}}.</p> * <p>If configured, this parameter renderer adds an additional row to display the default field value.</p> * @return a new default ParameterRenderer */ public IParameterRenderer createDefaultParameterRenderer() { return new DefaultParameterRenderer(commandSpec.usageMessage.showDefaultValues(), "" + commandSpec.usageMessage().requiredOptionMarker()); } /** Returns a new minimal ParameterRenderer which converts {@linkplain PositionalParamSpec positional parameters}
@Test public void testDefaultOptionRenderer_rendersSpacePrefixByDefaultForRequiredOptionsWithDefaultValue() { //@Command(showDefaultValues = true) // set programmatically class Example { @Option(names = {"-b", "-a", "--alpha"}, required = true, description = "other") String otherField; } Help help = new Help(new Example()); help.commandSpec().usageMessage().showDefaultValues(true); Help.IOptionRenderer renderer = help.createDefaultOptionRenderer(); Help.IParamLabelRenderer parameterRenderer = help.createDefaultParamLabelRenderer(); OptionSpec option = help.options().get(0); Text[][] row = renderer.render(option, parameterRenderer, help.colorScheme()); assertEquals(1, row.length); assertArrayEquals(Arrays.toString(row[0]), textArray(help, " ", "-b", ",", "-a, --alpha=<otherField>", "other"), row[0]); // assertArrayEquals(Arrays.toString(row[1]), textArray(help, "", "", "", "", " Default: null"), row[1]); // #201 don't show null defaults }
assertEquals("", help.parameterListHeading()); // because no parameters assertTrue(help.commandSpec().usageMessage().abbreviateSynopsis()); assertTrue(help.commandSpec().usageMessage().showDefaultValues()); assertFalse(help.commandSpec().usageMessage().sortOptions()); assertEquals(";", help.commandSpec().parser().separator());
assertEquals("sub param heading", help.commandSpec().usageMessage().parameterListHeading()); assertTrue(help.commandSpec().usageMessage().abbreviateSynopsis()); assertTrue(help.commandSpec().usageMessage().showDefaultValues()); assertFalse(help.commandSpec().usageMessage().sortOptions()); assertEquals(":", help.commandSpec().parser().separator());
sep = appendStringArray(pw, sep, indent, "version = %s", spec.version(), EMPTY_ARRAY); sep = appendClassName(pw, sep, indent, "versionProvider = %s", spec.versionProvider()); sep = append(pw, sep, indent, "showDefaultValues = %s", spec.usageMessage().showDefaultValues(), false); sep = appendClassName(pw, sep, indent, "defaultValueProvider = %s", spec.defaultValueProvider()); sep = append(pw, sep, indent, "resourceBundle = \"%s\"", spec.resourceBundleBaseName(), "null");
assertTrue("abbreviateSynopsis", commandSpec.usageMessage().abbreviateSynopsis()); assertArrayEquals(new String[] {"Mixin custom synopsis"}, commandSpec.usageMessage().customSynopsis()); assertTrue("showDefaultValues", commandSpec.usageMessage().showDefaultValues()); assertFalse("sortOptions", commandSpec.usageMessage().sortOptions());
assertEquals('&', help.commandSpec().usageMessage().requiredOptionMarker()); assertTrue(help.commandSpec().usageMessage().abbreviateSynopsis()); assertTrue(help.commandSpec().usageMessage().showDefaultValues()); assertFalse(help.commandSpec().usageMessage().sortOptions());
@Test public void testDefaultOptionRenderer_rendersCommaOnlyIfBothShortAndLongOptionNamesExist() { class Example { @Option(names = {"-v"}, description = "shortBool") boolean shortBoolean; @Option(names = {"--verbose"}, description = "longBool") boolean longBoolean; @Option(names = {"-x", "--xeno"}, description = "combiBool") boolean combiBoolean; @Option(names = {"-s"}, description = "shortOnly") String shortOnlyField; @Option(names = {"--long"}, description = "longOnly") String longOnlyField; @Option(names = {"-b", "--beta"}, description = "combi") String combiField; } Help help = new Help(new Example()); help.commandSpec().usageMessage().showDefaultValues(false); // omit default values from description column Help.IOptionRenderer renderer = help.createDefaultOptionRenderer(); Help.IParamLabelRenderer parameterRenderer = help.createDefaultParamLabelRenderer(); String[][] expected = new String[][] { {"", "-v", "", "", "shortBool"}, {"", "", "", "--verbose", "longBool"}, {"", "-x", ",", "--xeno", "combiBool"}, {"", "-s", "=", "<shortOnlyField>", "shortOnly"}, {"", "", "", "--long=<longOnlyField>", "longOnly"}, {"", "-b", ",", "--beta=<combiField>", "combi"}, }; int i = -1; for (OptionSpec option : help.options()) { Text[][] row = renderer.render(option, parameterRenderer, help.colorScheme()); assertEquals(1, row.length); assertArrayEquals(Arrays.toString(row[0]), textArray(help, expected[++i]), row[0]); } }
void initFromMixin(UsageMessageSpec mixin, CommandSpec commandSpec) { if (initializable(synopsisHeading, mixin.synopsisHeading(), DEFAULT_SYNOPSIS_HEADING)) {synopsisHeading = mixin.synopsisHeading();} if (initializable(commandListHeading, mixin.commandListHeading(), DEFAULT_COMMAND_LIST_HEADING)) {commandListHeading = mixin.commandListHeading();} if (initializable(requiredOptionMarker, mixin.requiredOptionMarker(), DEFAULT_REQUIRED_OPTION_MARKER)) {requiredOptionMarker = mixin.requiredOptionMarker();} if (initializable(abbreviateSynopsis, mixin.abbreviateSynopsis(), DEFAULT_ABBREVIATE_SYNOPSIS)) {abbreviateSynopsis = mixin.abbreviateSynopsis();} if (initializable(sortOptions, mixin.sortOptions(), DEFAULT_SORT_OPTIONS)) {sortOptions = mixin.sortOptions();} if (initializable(showDefaultValues, mixin.showDefaultValues(), DEFAULT_SHOW_DEFAULT_VALUES)) {showDefaultValues = mixin.showDefaultValues();} if (initializable(hidden, mixin.hidden(), DEFAULT_HIDDEN)) {hidden = mixin.hidden();} if (initializable(customSynopsis, mixin.customSynopsis(), DEFAULT_MULTI_LINE)) {customSynopsis = mixin.customSynopsis().clone();} if (initializable(description, mixin.description(), DEFAULT_MULTI_LINE)) {description = mixin.description().clone();} if (initializable(descriptionHeading, mixin.descriptionHeading(), DEFAULT_SINGLE_VALUE)) {descriptionHeading = mixin.descriptionHeading();} if (initializable(header, mixin.header(), DEFAULT_MULTI_LINE)) {header = mixin.header().clone();} if (initializable(headerHeading, mixin.headerHeading(), DEFAULT_SINGLE_VALUE)) {headerHeading = mixin.headerHeading();} if (initializable(footer, mixin.footer(), DEFAULT_MULTI_LINE)) {footer = mixin.footer().clone();} if (initializable(footerHeading, mixin.footerHeading(), DEFAULT_SINGLE_VALUE)) {footerHeading = mixin.footerHeading();} if (initializable(parameterListHeading, mixin.parameterListHeading(), DEFAULT_SINGLE_VALUE)) {parameterListHeading = mixin.parameterListHeading();} if (initializable(optionListHeading, mixin.optionListHeading(), DEFAULT_SINGLE_VALUE)) {optionListHeading = mixin.optionListHeading();} if (Messages.empty(messages)) { messages(Messages.copy(commandSpec, mixin.messages())); } } void initFrom(UsageMessageSpec settings, CommandSpec commandSpec) {
/** Returns a new default OptionRenderer which converts {@link OptionSpec Options} to five columns of text to match * the default {@linkplain TextTable TextTable} column layout. The first row of values looks like this: * <ol> * <li>the required option marker</li> * <li>2-character short option name (or empty string if no short option exists)</li> * <li>comma separator (only if both short option and long option exist, empty string otherwise)</li> * <li>comma-separated string with long option name(s)</li> * <li>first element of the {@link OptionSpec#description()} array</li> * </ol> * <p>Following this, there will be one row for each of the remaining elements of the {@link * OptionSpec#description()} array, and these rows look like {@code {"", "", "", "", option.description()[i]}}.</p> * <p>If configured, this option renderer adds an additional row to display the default field value.</p> * @return a new default OptionRenderer */ public IOptionRenderer createDefaultOptionRenderer() { return new DefaultOptionRenderer(commandSpec.usageMessage.showDefaultValues(), "" +commandSpec.usageMessage().requiredOptionMarker()); } /** Returns a new minimal OptionRenderer which converts {@link OptionSpec Options} to a single row with two columns
@Test public void testOptionSpec_defaultValue_overwritesInitialValue() { @Command(showDefaultValues = true) class Params { @Option(names = {"-x", "--array"}, required = true, paramLabel = "INT", description = "the array") int[] array = {1, 5, 11, 23}; } CommandLine cmd = new CommandLine(new Params()); OptionSpec x = cmd.getCommandSpec().posixOptionsMap().get('x').toBuilder().defaultValue("5,4,3,2,1").splitRegex(",").build(); cmd = new CommandLine(CommandSpec.create().addOption(x)); cmd.getCommandSpec().usageMessage().showDefaultValues(true); String result = usageString(cmd, Help.Ansi.OFF); assertEquals(format("" + "Usage: <main class> [-x=INT[,INT...]]...%n" + " -x, --array=INT[,INT...] the array%n" + " Default: 5,4,3,2,1%n"), result); }
/** Returns a new default ParameterRenderer which converts {@linkplain PositionalParamSpec positional parameters} to four columns of * text to match the default {@linkplain TextTable TextTable} column layout. The first row of values looks like this: * <ol> * <li>empty string </li> * <li>empty string </li> * <li>parameter(s) label as rendered by the {@link IParamLabelRenderer}</li> * <li>first element of the {@link PositionalParamSpec#description()} array</li> * </ol> * <p>Following this, there will be one row for each of the remaining elements of the {@link * PositionalParamSpec#description()} array, and these rows look like {@code {"", "", "", param.description()[i]}}.</p> * <p>If configured, this parameter renderer adds an additional row to display the default field value.</p> * @return a new default ParameterRenderer */ public IParameterRenderer createDefaultParameterRenderer() { return new DefaultParameterRenderer(commandSpec.usageMessage.showDefaultValues(), "" + commandSpec.usageMessage().requiredOptionMarker()); } /** Returns a new minimal ParameterRenderer which converts {@linkplain PositionalParamSpec positional parameters}