Skip to content

Instantly share code, notes, and snippets.

@mkarg
Created October 29, 2019 06:09
Show Gist options
  • Save mkarg/9d9ca23e6da32b47c7fadaf10ae16ba6 to your computer and use it in GitHub Desktop.
Save mkarg/9d9ca23e6da32b47c7fadaf10ae16ba6 to your computer and use it in GitHub Desktop.
JCommander subcommand PoC
public class CLI {
@Parameter(names = { "-h", "--help" }, help = true)
private boolean help;
public static void main(final String[] args) {
final Builder builder = JCommander.newBuilder().addObject(new CLI());
final Optional<Application> application = StreamSupport.stream(ServiceLoader.load(Application.class).spliterator(), false).findFirst();
application.map(Application::programName).ifPresent(builder::programName);
application.map(Application::environmentVariable).ifPresent(varName -> builder.defaultProvider(new EnvironmentVariableDefaultProvider(varName, "-")));
final JCommander jCommander = builder.build();
ServiceLoader.load(Command.class).forEach(command -> CLI.registerCommand(jCommander, command));
JCommander leafCommander = jCommander;
try {
jCommander.parse(args);
final String rootVerb = jCommander.getParsedCommand();
final JCommander rootCommander = jCommander.getCommands().get(rootVerb);
if (rootCommander == null) {
jCommander.usage();
System.exit(1);
}
leafCommander = rootCommander;
do {
final String subVerb = leafCommander.getParsedCommand();
final JCommander subCommander = leafCommander.getCommands().get(subVerb);
if (subCommander != null)
leafCommander = subCommander;
else
break;
} while (true);
final Command command = (Command) leafCommander.getObjects().get(0);
command.execute();
} catch (final CommandException e) {
System.err.printf("%1$s: %2$s. See '%1$s --help'.%n", leafCommander.getProgramName(), e.getMessage());
System.exit(e.getStatus());
} catch (final Exception e) {
System.err.printf("%1$s: %2$s. See '%1$s --help'.%n", leafCommander.getProgramName(), e.getMessage());
System.exit(1);
}
}
private static final void registerCommand(final JCommander jCommander, final Command command) {
jCommander.addCommand(command);
final Parameters commandParameters = command.getClass().getAnnotation(Parameters.class);
if (commandParameters == null || commandParameters.commandNames().length == 0)
return;
final JCommander subCommander = jCommander.getCommands().get(commandParameters.commandNames()[0]);
final Collection<Command> subCommands = command.commands();
if (subCommands != null)
subCommands.forEach(subCommand -> CLI.registerCommand(subCommander, subCommand));
}
public interface Command {
default Collection<Command> commands() {
return null;
}
void execute() throws CommandException;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment