args4j – command line option parsing in Java

I was a bit sceptical about args4j to start with, but it has grown on me. There is an initial extra step you have to make to add it to a program, but this is mostly boilerplate like this:

@Option(name = "--help", usage = "Show option help", aliases={"-?", "-h"})
boolean showHelp = false;   
 
private void parseArgs(String[] args)
        {
        CmdLineParser parser = new CmdLineParser(this);
        try
            {
            // parse the arguments.
            parser.parseArgument(args);
 
// might add checks here if some of your options clash or interact
 
            }
        catch (CmdLineException e)
        {
            // if there's a problem in the command line,
            // you'll get this exception. this will report
            // an error message.
            System.err.println(e.getMessage());
            System.err.println("java Tester [options...]");
            // print the list of available options
            parser.printUsage(System.err);
            System.err.println();
 
            System.exit(1);
        }
 
        if (showHelp)
        {
            System.err.println("java Tester [options...]");
            parser.printUsage(System.err);
            System.exit(0);
        }
    }

Once you’ve got that set up, adding new options is very easy. Some might say I’ve got a bit carried away with them on my current test program. Just add a field or method which sets the value you want, and put a @Option annotation on it.

I found I wanted to have options which could either be disabled, enabled with a default value, or enabled with a provided argument. I managed to put together my own OptionHandler implementation to deal with this. (Though the astute reader will notice it only deals with Integer or Double valued options at the moment).

import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.OptionDef;
import org.kohsuke.args4j.spi.DoubleOptionHandler;
import org.kohsuke.args4j.spi.IntOptionHandler;
import org.kohsuke.args4j.spi.OptionHandler;
import org.kohsuke.args4j.spi.Parameters;
import org.kohsuke.args4j.spi.Setter;
 
/**
 * allow for an optional option argument in args4j.
 * Does its own check to figure out the type of the option, so it's a bit dodgy
 * @since 2008-12-05
 * @author eharman
 */
public class OptionalOptionHandler extends OptionHandler
{
    private OptionHandler delegate;
 
    public OptionalOptionHandler(CmdLineParser parser, OptionDef option, Setter setter)
    {
        super(parser, option, setter);
        Class t = setter.getType();
        if(t == Integer.class)
        {
            delegate = new IntOptionHandler(parser, option, setter);
        }
        else if(t == Double.class)
        {
            delegate = new DoubleOptionHandler(parser, option, setter);
        }
        else if(t.isPrimitive())
        {
            throw new IllegalArgumentException("OptionalOptionHandler does not work with arguments with primitive types");
        }
        else
        {
            throw new UnsupportedOperationException("OptionalOptionHandler does not yet handle arguments of type " + t);
        }
    }
 
    @Override
    public int parseArguments(Parameters params) throws CmdLineException
    {
        try
        {
            //test whether next argument is an int
            String testVal = params.getParameter(0);
            if(testVal != null && !testVal.startsWith("-"))
            {
                return delegate.parseArguments(params);
            }
        }
        catch(CmdLineException e)
        {
            //ignore and believe there is no value for the option
        }
        setter.addValue(null);
        return 0;
    }
 
    @Override
    public String getDefaultMetaVariable()
    {
        return "FOO";
    }
 
}

One Comment

  1. steveo
    Posted February 4, 2009 at 11:56 pm | Permalink

    Don’t know if you would be interested in the command line argument parser that I wrote:
    http://ostermiller.org/utils/CmdLn.html
    It handles optional arguments without any additional work on your part. It doesn’t support annotations though.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*