User:Wvengen@nikhef.nl/Apache Commons CLI Tips

From GridWiki
Jump to: navigation, search

Java command-line tools can quite easily be made using Apache Commons CLI. This gives the user a standard way to specify options and get help on them in a way that nicely blends into the larger ecosystem.

There are a some simple tweaks that make it even more natural.

Detecting the terminal width

Commons CLI doesn't seem to know by default how wide lines may be, so you either specify it yourself or use the default. But most Unix command-line tools detect this automatically. This can also be done using Commons CLI. The width is taken from environment variable COLUMNS:

  public static void main(String[] args) throws Exception {
    // example options object
    final Options options = new Options();
    opts.addOption(new Option("h", "help", false,
      "show a help message that does have a considerable length today"));
    CommandLineParser parser = new GnuParser();
    CommandLine line = parser.parse(opts, args);
    // show help message when requested
    if (line.hasOption("help")) {
      HelpFormatter fmt = new HelpFormatter();
      if (System.getenv("COLUMNS")!=null)
        fmt.setWidth(Integer.valueOf(System.getenv("COLUMNS")));
      fmt.printHelp("test", options);
    } else {
      System.out.println("Nothing to do!");
    }
 }

If you are running the Java program from a shellscript, you have to make sure to export the variable COLUMNS. For a standard Bourne shell, include the command

  export COLUMNS

before calling the java tool from a wrapper script. This doesn't detect width-changes happening during the invocation of the program, however (see SIGWINCH).

Detecting the real commandline

Often command-line Java tools are invoked by a wrapper script that calls the Java main class. This hides the fact that a utility is implemented in Java for the user, which is a good thing when everything works properly. As a finishing touch, one would want to mention the wrapper script in the default Commons CLI help message -- unless the script is not installed and the program is invoked directly with java.

This can be achieved by setting a variable in the shell script to indicate what the invoked program name is. For example:

  #!/bin/sh
  INVOKED_PROGRAM="$0"
  export INVOKED_PROGRAM
  java my.cool.MainSuperClass $@

with the Java method in my.cool.MainSuperClass:

  public static void main(String[] args) throws Exception {
    // example options object
    final Options options = new Options();
    opts.addOption(new Option("h", "help", false, "show help");
    CommandLineParser parser = new GnuParser();
    CommandLine line = parser.parse(opts, args);
    // show help message when requested
    if (line.hasOption("help")) {
      String prog = System.getenv("INVOKED_PROGRAM");
      if (prog==null) prog = "java "+MainSuperClass.class.getName();
      HelpFormatter fmt = new HelpFormatter();
      fmt.printHelp(prog, options);
    } else {
      System.out.println("Nothing to do!");
    }
 }
Personal tools