picocli
picocli copied to clipboard
Hide the default System section from the HELP command
Hi,
I am currently working on a project where we have implemented a few custom commands. When I just type help
command (without any subcommand), it displays two sections. One is the default System commands that are registered inherently showing help
and exit
commands. The other section shows our custom commands.
However, our application is currently not supporting the exit
command so we want to hide this part. How do I remove or hide the System section from the help menu?
Hi! That’s hard to say without seeing the code, but I guess you would undo (or comment out) what you did to show these sections.
Hi Remko,
Here is how we build up the command registries.
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
class NormalMode implements CliMode {
private MessageSource i18n
private Supplier<Path> pwd
private CommandLine parentCommandLine
@Autowired
NormalMode(
MessageSource messageSource,
@Qualifier("currentWorkingDir") Supplier<Path> pwd,
@Qualifier("rootCommandLine") CommandLine rootCommandLine,
SetupCommand setupCommand,
SetFactoryCommand setFactoryCommand,
ShowCommand showCommand,
ServiceCommand serviceCommand,
BackDoorCommand backDoorCommand
) {
this.i18n = messageSource
this.pwd = pwd
this.parentCommandLine = rootCommandLine
attachSubCommands(
rootCommandLine,
setupCommand,
setFactoryCommand,
showCommand,
serviceCommand,
backDoorCommand
)
}
protected void attachSubCommands(CommandLine commandLine, CliCommand<?>... subCommands) {
for (CliCommand<?> command : subCommands) {
commandLine.addSubcommand(command)
}
}
@Override
Supplier<String> supplyPromptString() {
return () -> i18n.getMessage("mode.normal.prompt", null, Locale.getDefault())
}
@Override
Supplier<Path> supplyCurrentWorkingDirectory() {
return pwd
}
@Override
CommandRegistry getCommandRegistry() {
return new PicocliCommands(pwd, parentCommandLine) {
@Override
String name() {
return i18n.getMessage("mode.normal.name", null, Locale.getDefault())
}
}
}
}
Let me paste one of the command implementation here.
The business logic was made under its subcommand.
And I include the CommandLine.HelpCommand
class here so that we can allow the user to type show help
to see what subcommands we offer.
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@Command(name = "show",
subcommands = [
ShowInterfaceCommand,
ShowPm2ServiceCommand,
ShowSystemCommand,
CommandLine.HelpCommand ],
description = "Show system information")
@Slf4j
final class ShowCommand extends AbstractCliCommand<Integer> {
@Override
Integer call() throws Exception {
return 0
}
}
At the point of reading the user's commands as shown below, we instantiate a SystemRegistryImpl
object, set the command registries and create the LineReader
object and then start to continuously read in user's command and execute it.
@Override
void repl(CliMode mode) throws EndOfFileException, Exception {
SystemRegistry aggregator = new SystemRegistryImpl(parser, terminal, mode.supplyCurrentWorkingDirectory(),
null)
aggregator.setCommandRegistries(mode.getCommandRegistry())
LineReader lineReader = LineReaderBuilder
.builder()
.terminal(terminal)
.parser(parser)
.option(Option.CASE_INSENSITIVE, true)
.option(Option.AUTO_GROUP, false)
.option(Option.GROUP, false)
.completer(aggregator.completer()).variable(LineReader.LIST_MAX, 50).build()
while (true) {
try {
aggregator.cleanUp()
String line = lineReader.readLine(mode.supplyPromptString().get())
aggregator.execute(line)
} catch (UserInterruptException ctrlc) {
log.error("The user pressed Ctrl+C.", ctrlc)
...
We did not interfere with how the API will perform the root help behavior, that is, when we just type the help
command, it prints out all the commands including the System section shown in the screenshot. We understand that it should print out all the custom commands listed under the Normal Mode section, but how can we get rid of the System section so the user will not know they can type the exit
or help
command.
Cheers, Dave
Oh I see now, this is a JLine3 application, that was not clear to me initially.
Not sure if this is possible, but it may be. I believe that the Exit command is a JLine3 command, that does not use the picocli API... You will have to dig a bit into the integration code that combines JLine3 with picocli, and where these commands are added.
@allguitars it has been a while so it may not be on your radar any longer, but another suggestion I could make is to contact the JLine3 project and ask if they have any suggestions.
@allguitars Is this still an issue for you or can I close this ticket?