picocli CLI parser: hide the Java variable name while rendering the output

234 views Asked by At

I am using picocli to show the usage of my command-line application. What I am not able to reach is to hide the name of the Java variable which appears in the printed output and from my point of view it looks so ugly.

This is the configutation of my CommandLine.Option:

@CommandLine.Option(
        names = {"-a", "--abc"},
        description = "Please, hide the Java variable name...")
private String xxx;

And this is how it is rendered:

-a, --abc=<xxx>   Please, hide the Java variable name...

As you can see the name of the Java variable appears after the equal sign: <xxx>

I would like to hide it, like this:

-a, --abc   Please, hide the Java variable name...

I checked the API but I could not see anything related to this. Is there any way to turn it off?

1

There are 1 answers

2
Remko Popma On BEST ANSWER

The picocli annotations API does not provide for this, but it is possible to achieve this by overriding the Help API and plugging in your own option renderer. For example:

public class HideOptionParams {

@Option(names = {"-u", "--user"}, defaultValue = "${user.name}",
        description = "The connecting user name.")
private String user;

@Option(names = {"-p", "--password"}, interactive = true,
        description = "Password for the user.")
private String password;

@Option(names = {"-o", "--port"}, defaultValue = "12345",
        description = "Listening port, default is ${DEFAULT-VALUE}.")
private int port;

public static void main(String[] args) {
    CommandLine cmd = new CommandLine(new HideOptionParams());
    cmd.setHelpFactory(new IHelpFactory() {
        public Help create(final CommandSpec commandSpec, ColorScheme colorScheme) {
            return new Help(commandSpec, colorScheme) {
                @Override
                public IOptionRenderer createDefaultOptionRenderer() {
                    return new IOptionRenderer() {
                        public Text[][] render(OptionSpec option,
                                               IParamLabelRenderer ignored,
                                               ColorScheme scheme) {
                            return makeOptionList(option, scheme);
                        }
                    };
                }
            };
        }
    });
    cmd.usage(System.out);
}

private static Text[][] makeOptionList(OptionSpec option, ColorScheme scheme) {
    String shortOption = option.shortestName(); // assumes every option has a short option
    String longOption = option.longestName(); // assumes every option has a short and a long option

    if (option.negatable()) { // ok to omit if you don't have negatable options
        INegatableOptionTransformer transformer =
                option.command().negatableOptionTransformer();
        shortOption = transformer.makeSynopsis(shortOption, option.command());
        longOption = transformer.makeSynopsis(longOption, option.command());
    }

    // assume one line of description text (may contain embedded %n line separators)
    String[] description = option.description();
    Text[] descriptionFirstLines = scheme.text(description[0]).splitLines();

    Text EMPTY = Ansi.OFF.text("");
    List<Text[]> result = new ArrayList<Text[]>();
    result.add(new Text[]{
            scheme.optionText(String.valueOf(
                    option.command().usageMessage().requiredOptionMarker())),
            scheme.optionText(shortOption),
            scheme.text(","), // we assume every option has a short and a long name
            scheme.optionText(longOption), // just the option name without parameter
            descriptionFirstLines[0]});
    for (int i = 1; i < descriptionFirstLines.length; i++) {
        result.add(new Text[]{EMPTY, EMPTY, EMPTY, EMPTY, descriptionFirstLines[i]});
    }
    // if @Command(showDefaultValues = true) was set, append line with default value
    if (option.command().usageMessage().showDefaultValues()) {
        Text defaultValue = scheme.text("  Default: " + option.defaultValueString(true));
        result.add(new Text[]{EMPTY, EMPTY, EMPTY, EMPTY, defaultValue});
    }
    return result.toArray(new Text[result.size()][]);
}
}

This shows the following usage help message:

Usage: <main class> [-p] [-o=<port>] [-u=<user>]
  -o, --port          Listening port, default is 12345.
  -p, --password      Password for the user.
  -u, --user          The connecting user name.

Note that the parameter label is omitted in the options list, but is still shown in the synopsis. If you do not want any parameter labels shown in the synopsis, you can specify a custom synopsis in the @Command annotation, see this section in the user manual.