airlift / airline

Java annotation-based framework for parsing Git like command line structures
Apache License 2.0
846 stars 138 forks source link

Automatically show help when user types invalid command? #45

Open ChrisLMerrill opened 9 years ago

ChrisLMerrill commented 9 years ago

When the user enters a command that doesn't exist (e.g. mis-typed a command), an exception is thrown.

Exception in thread "main" io.airlift.airline.ParseArgumentsUnexpectedException: Found unexpected parameters: [blah, something] at io.airlift.airline.Cli.validate(Cli.java:148) at io.airlift.airline.Cli.parse(Cli.java:116) at io.airlift.airline.Cli.parse(Cli.java:97)

Since the end-user mistyping a command is an obvious use case, I'm assuming I've done something wrong. I've set Help as the default command, but I guess that isn't it.

    Cli.CliBuilder<Runnable> builder = Cli.<Runnable>builder("muse")
        .withDescription("Muse command-line tools")
        .withDefaultCommand(Help.class)
        .withCommands(Help.class)
        .withCommands(implementors);
    Cli<Runnable> muse_parser = builder.build();
    muse_parser.parse(args).run();

My fix thus far is to catch the exception and run the Help command by re-parsing an empty command line. That seems like a hack. new Help().run() threw an exception, too, so that wasn't any better.

I feel like I'm missing an obvious solution, since none of the examples include catching an exception.

TIA! Chris

petercoulton commented 8 years ago

Totally agree --help is the first thing I run on a new command so seems like it should be supported. I have a workaround for now though

try {
  parser.parse(args).run();
} catch (ParseArgumentsUnexpectedException e) {

  final List<String> commandNames =
      reportingParser.getMetadata().getCommandGroups().stream()
          .flatMap(cg -> cg.getCommands().stream().map(CommandMetadata::getName))
          .collect(Collectors.toList());

  Help.help(parser.getMetadata(), commandNames);
}

I haven't looked much into the airline code base yet, but I'll have a look and try to put a pull request together with a better solution, unless the maintainers are philosophically against this behaviour for some reason.

rvesse commented 6 years ago

Now possible in my fork and documented here