Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I avoid a ParserException for required options when user just wants to print usage?

So I have an Options instance which among other options has (notice the isRequired()):

        options.addOption(OptionBuilder
                .withLongOpt("seq1")
                .withDescription("REQUIRED : blah blah")
                .hasArg().isRequired().create());
        options.addOption(OptionBuilder
                .withLongOpt("seq2")
                .withDescription("REQUIRED : blih blih")
                .hasArg().isRequired().create());
        options.addOption(new Option("?", "help", false,
                "print this message and exit"));

When I call parser.parse(args) throws an exception if seq1 and seq2 are not present - but I want to have it print my message and no exception thrown - how to go about it ? This throws NPE in line.hasOption("help"), naturally :

CommandLine line = null;
try {
    CommandLineParser parser = new GnuParser();
    // parse the command line arguments
    line = parser.parse(options, args);
} catch (ParseException e) {
    if (line.hasOption("help")) { //NPE
        usage(0);
    }
    System.err.println("Parsing failed.  Reason: " + e.getMessage());
    usage(1);
}

private static void usage(int exitCode) {
    // automatically generate the help statement
    HelpFormatter formatter = new HelpFormatter();
    formatter.printHelp("Smith Waterman", OPTIONS, true);
    System.exit(exitCode);
}
like image 588
Mr_and_Mrs_D Avatar asked Jan 13 '13 23:01

Mr_and_Mrs_D


3 Answers

Solution adapted from here

private static final Options OPTIONS = new Options();
private static final Options HELP_OPTIONS = new Options();
OPTIONS.addOption(OptionBuilder
        .withLongOpt("seq1")
        .withArgName("file1")
        .withDescription(
                "REQUIRED : the file containing sequence 1")
        .hasArg().isRequired().create());
// etc
final Option help = new Option("?", "help", false,
        "print this message and exit");
HELP_OPTIONS.addOption(help);
OPTIONS.addOption(help);
// later
CommandLineParser parser = new GnuParser();
CommandLine line = parser.parse(HELP_OPTIONS, args, true); // true so it
// does not throw on unrecognized options
if (line.hasOption("help")) {
    usage(0); // calls exit
}
line = parser.parse(OPTIONS, args);

If anything more elegant comes up I would gladly accept it

like image 122
Mr_and_Mrs_D Avatar answered Nov 14 '22 04:11

Mr_and_Mrs_D


This may or may not be useful depending on your usage. Mine is as follows:

  • I have one wrapper program (called 'controller')
  • there are many commands (called 'tasks') that the controller can run
  • each command has its own set of unique command line argument sets

For example:

$ controller startall -rsrc foo -dir bar -where baz

The first thing done with the arguments is to determine what the command is. For that I set up a TaskFactory which looks at the first argument, strips off any leading hyphen, and looks it up to see if it's a known task. I have a 'help' task, which lets my user do:

$ controller -help

and

$ controller help

Each task also has a help option, so the user can do:

$ controller startall -help

That may not help you, though. I'll post an alternative.

like image 43
Joe Casadonte Avatar answered Nov 14 '22 04:11

Joe Casadonte


I used the following check before parsing to make sure -h or --help overrules everything else.

// check if help is requested
if (Arrays.asList(args).contains("-h")
        || Arrays.asList(args).contains("--help")) {
    usage(0); // print usage with exit 0
}
// parse options

Not the nicest solution but it serves my needs.

like image 44
mjspier Avatar answered Nov 14 '22 02:11

mjspier