/** Generates a generic synopsis like {@code <command name> [OPTIONS] [PARAM1 [PARAM2]...]}, omitting parts * that don't apply to the command (e.g., does not show [OPTIONS] if the command has no options). * @return a generic synopsis */ public String abbreviatedSynopsis() { StringBuilder sb = new StringBuilder(); if (!commandSpec.optionsMap().isEmpty()) { // only show if annotated object actually has options sb.append(" [OPTIONS]"); } // sb.append(" [--] "); // implied for (PositionalParamSpec positionalParam : commandSpec.positionalParameters()) { if (!positionalParam.hidden()) { sb.append(' ').append(parameterLabelRenderer().renderParameterLabel(positionalParam, ansi(), colorScheme.parameterStyles)); } } // only show if object has subcommands if (!commandSpec.subcommands().isEmpty()) { sb.append(" [COMMAND]"); } return colorScheme.commandText(commandSpec.qualifiedName()).toString() + (sb.toString()) + System.getProperty("line.separator"); } /** Generates a detailed synopsis message showing all options and parameters. Follows the unix convention of
/** Returns the command header text as a string. Header text can be zero or more lines, and can be specified * declaratively with the {@link Command#header()} annotation attribute or programmatically by * setting the Help instance's {@link Help#header} field. * @param params Arguments referenced by the format specifiers in the header strings * @return the header lines combined into a single String (which may be empty) */ public String header(Object... params) { return join(ansi(), width(), commandSpec.usageMessage().header(), new StringBuilder(), params).toString(); } /** Returns command footer text as a string. Footer text can be zero or more lines, and can be specified
/** Returns command description text as a string. Description text can be zero or more lines, and can be specified * declaratively with the {@link Command#description()} annotation attribute or programmatically by * setting the Help instance's {@link Help#description} field. * @param params Arguments referenced by the format specifiers in the description strings * @return the description lines combined into a single String (which may be empty) */ public String description(Object... params) { return join(ansi(), width(), commandSpec.usageMessage().description(), new StringBuilder(), params).toString(); } /** Returns the command header text as a string. Header text can be zero or more lines, and can be specified
@Test public void testMinimalOptionRenderer_rendersFirstDeclaredOptionNameAndDescription() { class Example { @Option(names = {"---long", "-L"}, description = "long description") String longField; @Option(names = {"-b", "-a", "--alpha"}, description = "other") String otherField; } Help.IOptionRenderer renderer = Help.createMinimalOptionRenderer(); Help help = new Help(new Example(), Help.Ansi.ON); Help.IParamLabelRenderer parameterRenderer = help.createDefaultParamLabelRenderer(); OptionSpec option = help.options().get(0); Text[][] row1 = renderer.render(option, parameterRenderer, Help.defaultColorScheme( help.ansi())); assertEquals(1, row1.length); //assertArrayEquals(new String[]{"---long=<longField>", "long description"}, row1[0]); assertArrayEquals(new Text[]{ help.ansi().new Text(format("%s---long%s=%s<longField>%s", "@|fg(yellow) ", "|@", "@|italic ", "|@")), help.ansi().new Text("long description")}, row1[0]); OptionSpec option2 = help.options().get(1); Text[][] row2 = renderer.render(option2, parameterRenderer, Help.defaultColorScheme( help.ansi())); assertEquals(1, row2.length); //assertArrayEquals(new String[]{"-b=<otherField>", "other"}, row2[0]); assertArrayEquals(new Text[]{ help.ansi().new Text(format("%s-b%s=%s<otherField>%s", "@|fg(yellow) ", "|@", "@|italic ", "|@")), help.ansi().new Text("other")}, row2[0]); }
/** Returns a 2-column list with command names and the first line of their header or (if absent) description. * @return a usage help section describing the added commands */ public String commandList() { if (subcommands().isEmpty()) { return ""; } int commandLength = maxLength(subcommands().keySet()); Help.TextTable textTable = Help.TextTable.forColumns(ansi(), new Help.Column(commandLength + 2, 2, Help.Column.Overflow.SPAN), new Help.Column(width() - (commandLength + 2), 2, Help.Column.Overflow.WRAP)); for (Map.Entry<String, Help> entry : subcommands().entrySet()) { Help help = entry.getValue(); UsageMessageSpec usage = help.commandSpec().usageMessage(); String header = !empty(usage.header()) ? usage.header()[0] : (!empty(usage.description()) ? usage.description()[0] : ""); Text[] lines = ansi().text(format(header)).splitLines(); for (int i = 0; i < lines.length; i++) { textTable.addRowValues(i == 0 ? help.commandNamesText(", ") : Ansi.EMPTY_TEXT, lines[i]); } } return textTable.toString(); } private static int maxLength(Collection<String> any) {
/** * Returns the detailed synopsis text by inserting the command name before the specified text with options and positional parameters details. * @param synopsisHeadingLength length of the synopsis heading string to be displayed on the same line as the first synopsis line. * For example, if the synopsis heading is {@code "Usage: "}, this value is 7. * @param optionsAndPositionalsAndCommandsDetails formatted string with options, positional parameters and subcommands. * Follows the unix convention of showing optional options and parameters in square brackets ({@code [ ]}). * @return the detailed synopsis text, in multiple lines if the length exceeds the usage width */ protected String insertSynopsisCommandName(int synopsisHeadingLength, Text optionsAndPositionalsAndCommandsDetails) { // Fix for #142: first line of synopsis overshoots max. characters String commandName = commandSpec.qualifiedName(); int firstColumnLength = commandName.length() + synopsisHeadingLength; // synopsis heading ("Usage: ") may be on the same line, so adjust column width TextTable textTable = TextTable.forColumnWidths(ansi(), firstColumnLength, width() - firstColumnLength); textTable.indentWrappedLines = 1; // don't worry about first line: options (2nd column) always start with a space // right-adjust the command name by length of synopsis heading Text PADDING = Ansi.OFF.new Text(stringOf('X', synopsisHeadingLength)); textTable.addRowValues(PADDING.concat(colorScheme.commandText(commandName)), optionsAndPositionalsAndCommandsDetails); return textTable.toString().substring(synopsisHeadingLength); // cut off leading synopsis heading spaces }
@Test public void testDefaultParameterRenderer_appliesToPositionalArgumentsIgnoresSeparator() { class WithLabel { @Parameters(paramLabel = "POSITIONAL_ARGS") String positional; } class WithoutLabel { @Parameters() String positional; } Help withLabel = new Help(new WithLabel()); Help.IParamLabelRenderer equals = withLabel.createDefaultParamLabelRenderer(); withLabel.commandSpec().parser().separator("="); Help.IParamLabelRenderer spaced = withLabel.createDefaultParamLabelRenderer(); Text withSpace = spaced.renderParameterLabel(withLabel.positionalParameters().get(0), withLabel.ansi(), Collections.<IStyle>emptyList()); assertEquals(withSpace.toString(), "POSITIONAL_ARGS", withSpace.toString()); Text withEquals = equals.renderParameterLabel(withLabel.positionalParameters().get(0), withLabel.ansi(), Collections.<IStyle>emptyList()); assertEquals(withEquals.toString(), "POSITIONAL_ARGS", withEquals.toString()); Help withoutLabel = new Help(new WithoutLabel()); withSpace = spaced.renderParameterLabel(withoutLabel.positionalParameters().get(0), withoutLabel.ansi(), Collections.<IStyle>emptyList()); assertEquals(withSpace.toString(), "<positional>", withSpace.toString()); withEquals = equals.renderParameterLabel(withoutLabel.positionalParameters().get(0), withoutLabel.ansi(), Collections.<IStyle>emptyList()); assertEquals(withEquals.toString(), "<positional>", withEquals.toString()); }
/** Returns a Text object containing a partial detailed synopsis showing only the positional parameters, starting with a {@code " "} space. * Follows the unix convention of showing optional options and parameters in square brackets ({@code [ ]}). * @return the formatted positional parameters, starting with a {@code " "} space, or an empty Text if this command has no positional parameters * @since 3.9 */ protected Text createDetailedSynopsisPositionalsText() { Text positionalParamText = ansi().new Text(0); for (PositionalParamSpec positionalParam : commandSpec.positionalParameters()) { if (!positionalParam.hidden()) { positionalParamText = positionalParamText.concat(" "); Text label = parameterLabelRenderer().renderParameterLabel(positionalParam, colorScheme.ansi(), colorScheme.parameterStyles); positionalParamText = positionalParamText.concat(label); } } return positionalParamText; }
public static Text[] textArray(Help help, String... str) { return textArray(help.ansi(), str); }
public String render(Help help) { CommandSpec spec = help.commandSpec(); if (spec.subcommands().isEmpty()) { return ""; } // prepare layout: two columns // the left column overflows, the right column wraps if text is too long TextTable textTable = TextTable.forColumns(help.ansi(), new Column(15, 2, Overflow.SPAN), new Column(spec.usageMessage().width() - 15, 2, Overflow.WRAP)); for (CommandLine subcommand : spec.subcommands().values()) { addHierarchy(subcommand, textTable, ""); } return textTable.toString(); }
/** Returns a Text object containing a partial detailed synopsis showing only the subcommands, starting with a {@code " "} space. * Follows the unix convention of showing optional elements in square brackets ({@code [ ]}). * @return this implementation returns a hard-coded string {@code " [COMMAND]"} if this command has subcommands, an empty Text otherwise * @since 3.9 */ protected Text createDetailedSynopsisCommandText() { Text commandText = ansi().new Text(0); if (!commandSpec.subcommands().isEmpty()){ commandText = commandText.concat(" [") .concat("COMMAND") .concat("]"); } return commandText; }
/** Returns command footer text as a string. Footer text can be zero or more lines, and can be specified * declaratively with the {@link Command#footer()} annotation attribute or programmatically by * setting the Help instance's {@link Help#footer} field. * @param params Arguments referenced by the format specifiers in the footer strings * @return the footer lines combined into a single String (which may be empty) */ public String footer(Object... params) { return join(ansi(), width(), commandSpec.usageMessage().footer(), new StringBuilder(), params).toString(); }
/** Returns command custom synopsis as a string. A custom synopsis can be zero or more lines, and can be * specified declaratively with the {@link Command#customSynopsis()} annotation attribute or programmatically * by setting the Help instance's {@link Help#customSynopsis} field. * @param params Arguments referenced by the format specifiers in the synopsis strings * @return the custom synopsis lines combined into a single String (which may be empty) */ public String customSynopsis(Object... params) { return join(ansi(), width(), commandSpec.usageMessage().customSynopsis(), new StringBuilder(), params).toString(); } /** Returns command description text as a string. Description text can be zero or more lines, and can be specified
/** Returns the text displayed before the description text; an empty string if there is no description, * otherwise the result of {@code String.format(descriptionHeading, params)}. * @param params the parameters to use to format the description heading * @return the formatted description heading */ public String descriptionHeading(Object... params) { return empty(commandSpec.usageMessage().descriptionHeading()) ? "" : heading(ansi(), width(), commandSpec.usageMessage().descriptionHeading(), params); }
/** Returns the text displayed before the header text; the result of {@code String.format(headerHeading, params)}. * @param params the parameters to use to format the header heading * @return the formatted header heading */ public String headerHeading(Object... params) { return heading(ansi(), width(), commandSpec.usageMessage().headerHeading(), params); }
/** Returns the text displayed before the footer text; the result of {@code String.format(footerHeading, params)}. * @param params the parameters to use to format the footer heading * @return the formatted footer heading */ public String footerHeading(Object... params) { return heading(ansi(), width(), commandSpec.usageMessage().footerHeading(), params); } /** Returns a 2-column list with command names and the first line of their header or (if absent) description.
/** Returns the text displayed before the option list; an empty string if there are no options, * otherwise the result of {@code String.format(optionListHeading, params)}. * @param params the parameters to use to format the option list heading * @return the formatted option list heading */ public String optionListHeading(Object... params) { return commandSpec.optionsMap().isEmpty() ? "" : heading(ansi(), width(), commandSpec.usageMessage().optionListHeading(), params); }
/** Returns the text displayed before the command list; an empty string if there are no commands, * otherwise the result of {@code String.format(commandListHeading, params)}. * @param params the parameters to use to format the command list heading * @return the formatted command list heading */ public String commandListHeading(Object... params) { return commands.isEmpty() ? "" : heading(ansi(), width(), commandSpec.usageMessage().commandListHeading(), params); }
/** Returns the text displayed before the positional parameter list; an empty string if there are no positional * parameters, otherwise the result of {@code String.format(parameterListHeading, params)}. * @param params the parameters to use to format the parameter list heading * @return the formatted parameter list heading */ public String parameterListHeading(Object... params) { return commandSpec.positionalParameters().isEmpty() ? "" : heading(ansi(), width(), commandSpec.usageMessage().parameterListHeading(), params); }
/** Returns the text displayed before the synopsis text; the result of {@code String.format(synopsisHeading, params)}. * @param params the parameters to use to format the synopsis heading * @return the formatted synopsis heading */ public String synopsisHeading(Object... params) { return heading(ansi(), width(), commandSpec.usageMessage().synopsisHeading(), params); }