Tuesday, July 8, 2008

Command-Line Parsing Libraries for Java

I've recently had the need to do some command-line argument parsing in Java, and so I took the opportunity to quickly evaluate some of the command-line parsing libraries that are available for Java.  After looking briefly, the following options seemed to be relatively well-known:

  • args4j
  • JewelCLI
  • jArgs
  • Commons CLI
Of the options, I spent the most time with args4j; it seemed to be relatively modern, it was available in a Maven repository, it was written at least in part by Kohsuke Kawaguchi, whose Hudson project seems to have turned a lot of heads.

Most java.net projects have pretty weak websites and documentation, I've noticed.  The args4j project is no exception.  It has a sample page, a blog post and some javadoc, and if you piece all three of those together, you'll basically have enough information to get started, after which you'll occasionally have to dive into the code.

I was able to make this work for me, but it lacks most of the bells and whistles that I had hoped adopting a third-party library designed for this purpose would provide.  Args4j will not easily:
  • Limit the number of arguments
  • Restrict arguments to matching arbitrary rules like regexp pattern-matching
  • Display great help for the available options (it has usage, but it seems to leave out information like whether or not an option is required)
Although I haven't dug through the source code in detail, it doesn't look to me like there's a very complete suite of tests.  That doesn't matter if the code is solid and the documentation's good, but with the gaps in the documentation, some tests would have helped to make things a little easier to understand.

JewelCLI has a pretty spartan (Maven-built) site, but seems to have good functionality and clear, if simple, documentation by example.  As far as I can tell, it isn't available in any Maven repositories, which is too bad because it seems to be built with Maven and, at first glance, I'd say it looks slightly more capable than args4j, and it seems to have a full test suite, although it doesn't look like anything's changed much recently.

It's another anotation-based implementation.  It uses an interface instead of a class, which has pros and cons.  It's vaguely fun because it allows them to implement some simple things under the hood like interrogatory methods for optional parameters.  That said, args4j's class approach gives you the flexibility of putting the behavior inside the same class as the data, if you choose to accept that option.

jArgs seemed like it might be reasonable, but the last release was in 2005, the site is sometimes unresponsive, preventing you from looking into it in more detail, the implementation seems like more work to set up - programmatic configuration instead of class-based or interface-based reflection/generation.  Ultimately, if I can't get to the project consistently, I tend to take that as an omen.

Commons CLI
Apparently the oldest of the options here, and doesn't get a lot of respect from commenters, so I didn't really look at this very closely..

In Summary
I ended up using Args4j for now, but I think I'd use Jewel CLI next time, and if it works out as well as it seems at a distance, probably stick with that. 

This is also a good time to point out that Java's console programming model is pretty limited.  Key bindings?  Clear screen?  Move around?  Nope, sorry.  There seem to be third-party tools to get you there, but the core console functionality is basically suited to log output and the occasional thin piece of input.

Taylor Gautier looked into some of the before, if you're looking for further comparisons.


pholser said...

I'll offer up my JOpt Simple for your consideration. I'm almost ready to declare a 3.0 final version. Let me know what you think.

Jarrod said...

how did you manage to miss Java Simple Argument Parser

By far the best and most mature of all the alternatives.

Geoffrey Wiseman said...

I'll have to try JOpt Simple and JSAP sometime; would be nice to revise this based on recent versions. I have a project that could use argument parsing in mind, although I don't know when I get to 'em.

Geoffrey Wiseman said...

Trying --jopt-simple; looks nice so far.

Tim said...

Just to update you, JewelCli is available in maven central (has been for a while, but actually recently moved):

groupId: com.lexicalscope.jewelcli
artifactId: jewelcli

Remko Popma said...

Late to the party, but please take a look at picocli. It offers support for two out of three feature requests mentioned in the article: limiting the number of arguments and displaying great help.

The usage help uses ANSI styles and colors to reduce the cognitive load on the user: it uses contrast to make important information like commands, options, and parameters stand out from the surrounding text.

Another feature worth mentioning is that picocli offers support for command line auto-completion.

There are many more reasons why picocli may be interesting. Subcommands, GraalVM support, integration with Dependency Injection containers are just some of the features.

The user manual is very high quality and the project is actively maintained.