2008-05-12

Command-line arguments with JOpt Simple

Novelang started as an interactive tool because it was easier to use a Web browser for a quick preview of generated documents. But now that I want to publish documentation on the still-to-come website I need to automate document generation, because Novelang website has to be generated with Novelang (or I'd get ashamed). So I have to support a command-line based interface. By now it's a fairly simple one. Helps prints with one of the -h -? --help options whenever other options are activated. That seemed useful to me because when I type some long command and get lost with options, I don't want to run it (starting dangerous things or polluting the console with error message) nor hit Ctrl-C to request help on the next prompt -- and have to copy-paste it again. Here is the help message for now:
Usage:   Main [Options] <document [document2 [...]]>

<document>: logical name of a document to generate.
Starts with '/part/' or '/book/' (like URLs).
Valid names: /part/somedir/mydoc.html or /book/mybook.pdf

Option                      Description                                      
--------------------------- ------------------------------------------------------
-?, -h, --help              Shows this help message                          
-t, --targetDirectory <dir> Where generated files go to (default is './generated')
It's surprisingly hard to write concise help messages. I had to trick the terms to make -t option as short as possible and I'm still above 80 chars. Including line breaks and whitespace to make the "(default is [...]" message appear on another line doesn't work well as the framework generating help message understands this as one single line and generates many, many dashes in the table header. It could have limited dashes to an underline of "Option" and "Description" headers. I chose to explain document names right after general command syntax because the option list "breaks" the layout somehow. On the other hand, if the option list grows a lot, general syntax will scroll up out of view. But there is always the option to add a "verbose help" option later. One special case arises when a document file starts with a dash (-) and therefore can be confused with an option. A double dash (--) as the last option disambiguates this and we can write (though I'm not sure Novelang supports file names starting with a dash but it's another story):
Main -- -mybook.pdf
Main -t somewhere -- -mybook.pdf
Writing nice command-line interface is always more complicated than it seems. Lucky me, I found JOpt Simple, an excellent framework that perfectly suited my needs (including the double dash support). It worked flawlessly for everything I needed, including double dash disambiguation. I just ran through some minor annoyances:
  • Esoteric Artistic Free License.
  • Maven-only distribution hidden somewhere on the website.
  • Doesn't use Java Generics (at least OptionSet#nonOptionArguments() should return a List<String>).
I'd also appreciate multiline option description. Paul R. Holser, author of JOpt Simple, claims that his tool is better that competing ones, and he's not afraid to link on them from his project's home page. After repeated disappointements with Jakarta Commons-CLI and a few tries to grok the API of his competitors, I agree that JOpt Simple is far above others.

1 comment:

pholser said...

Thanks for the positive feedback!