Reputation: 22746
I would like to show the help automatically when I run my CLI app without parameters. I have seen that this question appears multiply times on StackOverflow. I spent significant time figuring this out, I have read the official document, checked articles, but still not clear how to achieve this.
This is what I have:
Main class
@Command(
subcommands = {C1.class, C2.class}
)
public class HelloCli implements Callable<Integer> {
@Option(names = {"?", "-h", "--help"},
usageHelp = true,
description = "display this help message")
boolean usageHelpRequested;
@Override
public Integer call() throws Exception {
System.out.println("wanna show the help here");
return 1;
}
public static void main(String... args) {
int exitCode = new CommandLine(new HelloCli()).execute(args);
System.exit(exitCode);
}
}
The class that handles the show-user function:
@CommandLine.Command(name = "show-user",
aliases = "-show-user")
public class C1 implements Callable<Integer> {
@CommandLine.Option(names = {"?", "-h", "--help"},
usageHelp = true,
description = "display this help message")
boolean usageHelpRequested;
@CommandLine.Option(names = {"-p1"},
description = "show-user: param 1")
String p1;
@Override
public Integer call() throws Exception {
System.out.println("executing the 'show-user' business logic...");
System.out.println("param 1: " + p1);
return 4;
}
}
The class to handle the create-user command:
@CommandLine.Command(name = "create-user",
aliases = "-create-user")
public class C2 implements Callable<Integer> {
@CommandLine.Option(names = {"?", "-h", "--help"},
usageHelp = true,
description = "display this help message")
boolean usageHelpRequested;
@CommandLine.Option(names = {"-p1"},
description = "create-user: another param 1")
String p1;
@Override
public Integer call() throws Exception {
System.out.println("executing the 'create-user' business logic...");
System.out.println("param 1: " + p1);
return 5;
}
}
Case 1: when I call this app with -h
then the help is displayed properly:
Usage: <main class> [?] [COMMAND]
?, -h, --help display this help message
Commands:
show-user, -show-user
create-user, -create-user
Case 2: showing help for the 1st function, calling show-user -h
:
Usage: <main class> show-user [?] [-p1=<p1>]
?, -h, --help display this help message
-p1=<p1> show-user: param 1
Case 3: chowing help for the 1st function, calling create-user -h
:
Usage: <main class> create-user [?] [-p1=<p1>]
?, -h, --help display this help message
-p1=<p1> create-user: another param 1
Case 4: calling my app without param shows this:
wanna show the help here
My question is simple:
How to show the help when I run my CLI tool without params (Case 4
)?
I guess that I need to add custom code into the HelloCli.call()
method with a loop that collects the help texts from the two classes that implement the functions. But not sure how. I have not found any sample code for this popular use case.
My additional question is similar to the first one:
Can I show somehow the full help that is shown together everything from Case 2
and Case 3
?
Upvotes: 3
Views: 1979
Reputation: 406
If you're finding this and are not using subcommands, the answer is pretty simple:
Upvotes: 0
Reputation: 12136
You can also do this with CommandSpec
, as shown in the Git example in the picocli-examples repository. Just add spec.commandLine().usage(System.err)
to the call()
/run()
method of your top-level command.
@Command(name = "cli", subcommands = {ShowUserCommand.class})
public class CLI implements Runnable {
@Option(names = {"-h", "--help"}, usageHelp = true, description = "Display this usage menu")
private boolean help;
@Spec
CommandSpec spec;
@Override
public void run() {
// print the help menu if no subcommand is passed
spec.commandLine().usage(System.err);
}
public static void main(String[] args) {
final int exitCode = new CommandLine(new CLI()).execute(args);
System.exit(exitCode);
}
}
@Command(name = "show-user", description = "Show the current user")
public class ShowUserCommand implements Runnable {
@Option(names = {"-h", "--help"}, usageHelp = true, description = "Display this usage menu")
private boolean help;
@Option(names = {"-u", "--uppercase"}, description = "Print the username as uppercase")
private boolean uppercase;
@Spec
CommandSpec spec;
@Override
public void run() {
String username = System.getProperty("user.name");
System.out.println("User: " + (uppercase ? username.toUpperCase() : username));
}
}
Executing the command without any parameters will print the help menu:
In regards to your followup question, there doesn't seem to be a way to print the full help message (including options for the subcommands), it's required to pass the subcommand with -h
to see the help for that specific subcommand.
Upvotes: 1
Reputation: 36834
This is documented in the section on subcommands, Making Subcommands Required.
Essentially, do not implement Callable or Runnable in the top-level command. This makes it mandatory for end users to specify a subcommand. The manual has an example.
About your second question, how to customize the usage help message, please take a look at the picocli-examples module of the picocli GitHub project. A lot of the examples are about custom help. For example, this one shows the full hierarchy of subcommands (and sub-subcommands) in the usage help of the top-level command.
Upvotes: 1