style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-7505528228218001"
data-ad-slot="1225241371">

Easy Command Line Parser

Quick Start

Here is the jEasyCmd library for parsing command line arguments. This library strides to accomplish the most with the least amount of work on the user's part. Further more, the code truly documents itself, as the annotations used are simple, clear and easy to read within the source code. Javadoc comments on the class fields used as command line options, further allow the user to produce complete documentation and usage for command line arguments, just by doing what we normally do in java anyway. By using class fields, you would typically use anyhow to store the state of various command line options the user has chosen, results in most compact command line parsing code.

Lets start with an example and the simplest case possible, a single boolean option that a user can set from the command line:

public class BasicTest {

	@Arg
	public static boolean boolValue;

	public static void main(String[] args) {
		Cmdline.set(BasicTest.class, args);

		System.out.printf("boolValue=%s\n", boolValue);
	}
}

And that's it. If I want to add any other arguments, we just create a class field (static or dynamic) and annotate it with @Arg annotation. The Cmdline parser does the rest.

To use the above class we issue the command:

shell> java -jar jeasycmd.jar BasicTest --boolean-value
boolValue=true

Cmdline also handles String[] and any java Collection from the Collection Framework, for gathering multiple arguments for an option. The @Arg annotation has several options and allows you to provide additional aliases or custom names, descriptions, min/max number of arguments to each option, and more. The library is actually quiet capable at doing most of the things other command line parsing libraries have you define within your main method. Yet still be so compact and simple to use.

Lets do another example that gathers multiple arguments. Lets say we have a limit of 15 file names we want to allow anyone to specify. So here are the command line options we want to setup:

-v for verbose (a boolean flag)
-i for input file list
-p for prime number

public class BasicTest {

	@Arg(name = "-v")
	public static boolean verbose;

	@Arg(name = "-p")
	public static int primeNumber;

	@Arg(name = "-i", max = 15)
	public final static List<String> inputFiles = new ArrayList<String>();

	public static void main(String[] args) {
		Cmdline.set(BasicTest.class, args);

		for (String file : inputFiles) {
			System.out.println(file);
		}
	}
}

And thats that. If we specify on the command line:

-i file1 file2 file3 file4 -p 7 -v

The options would be processed as expected and the corresponding static fields would be set to their values. We would also get our list on stdout:

file1
file2
file3
file4

If we added the @Arg attribute 'catchall = true' to inputFiles option, it would allow us to place the list of file names at the end of the command line, even without the -i option, although -i option could be sprinkled through out the command line (even several times).

The static convenience method (Cmdline.set) is provided which combines everything into a single step. However, may want to break things into individual steps for not so simple cases:

public static void main(String[] args) {
	Cmdline cmdline = new Cmdline(BasicTest.class);
        cmdline.parseArgs(args);
}

There are still no "checked" exceptions being thrown by the above two forms. This is because the constructor assumes the annotated options are compliant and have been previously checked. Upon any command line argument errors, an error message is displayed and usage is printing for the convenience of the user. There are however methods that do throw exceptions and allow the programmer to handle the error conditions instead of the default handlers.

Lastly, as stated before, the fields do not have to be static. Dynamic fields are also supported but you have to pass an object instead of a class to Cmdline parser. Static fields typically are sufficient for most uses.


Here are several "semi" examples.

Get usage and exit via builtin action

The first is how to setup usage and help without having to implement anything in the main method:

@Arg(name = "-h", action = Action.HELP)
public static boolean help;

Note: the field type must be a boolean for builtin action.

The above invokes a builtin action "HELP" which will generate usage, display it to stdout and exit the application. Here is the output that would generate if we had some other options defined:

Usage: BasicTest
 -h                        usage help
 -v                        
 -p,--prime-number         
 -i <FILES...>             (required) list of input files
 -b,--bool-value           a boolean flag
    --int-value <COUNT>    a really long int option description that needs to be
                           split up into multiple lines, because its too long
                           otherwise and we want nice usage output whenever
                           possible
    --string-value         A little shorter description
    --string-array         Just a tad
 -o <OUTPUT...>            A collection of a number of strings

Get usage and do not exit

This next example does same thing as above, but does not exit immediately. Instead any action performed, always sets the underlying field's value to 'true' upon completion of the action. We can check for that condition in our main method and perform some cleanup action, for example. Usage is automatically displayed so all we need to add is our own cleanup logic.

@Arg(name = "-h", action = Action.HELP_NO_EXIT)
public static boolean help;

and in our main method:

public static void main(String[] args) {
  Cmdline.set(Test.class, args);

  if (help == true) {
    System.exit(0); // perform cleanup
  }
}

Here we were allowed to perfom cleanup or whatever.

Print help manually, triggered by option

Of course, if we want to display the help ourselves and not have it be a builtin action, we could have done this:

@Arg(name = "-h")
public static boolean help;

and in our main method:

public static void main(String[] args) {
  Cmdline cmd = new Cmdline("Test.class, args);

  if (help == true) {
    cmd.printUsage();
    System.exit(0);
  }
}

We did not no specify a builtin action, we simply used a boolean flag. We also had to use the Cmdline constructor and construct a full object so that we could invoke the printUsage which uses the currently defined options found in Test.class to build suitable help display for the user.

Print help using an OptionAction interface

(Advanced!!!) There is actually another way to accomplish the above. This time we can use an OptionAction interface, which allows complete control over what happens with the arguments for our option. This time again there is nothing that we need to do in the main method, except parse the option class and arguments. Here is what the class field looks like for an action:

@Arg(name = "-h")
public final static OptionAction helpAction = new OptionAction() {
	public void parse(Option context, String[] args) throws ArgException {
		Cmdline cmd = context.getParent();
		cmd.printUsage();
		System.exit(0);
	}
};

We could invoke it like this in our test main method or from the args:

Cmdline.set(BasicTest.class, "-h");

The action will be triggered and will generate usage message and exit. Notice that any class field using OptionAction are required to be marked as 'final'. This forces the user, and allows the compiler, to make sure that we have a OptionAction object always ready to go whenever the option is triggered.

Of course, any type of action can be performed this way. We could specify 'min' and 'max' @Arg attributes which define minimum and maximum number of arguments an option can take, and receive a list of arguments, however many we requested (the default is 0 args). These type of actions allow us to hook a more complex operation to an option without having to code for that in our main method, if that is something we desire. We could for example parse a complex date, or some complex set of arguments and modify other fields with the result from our action object. So a single option could for example setup a set of class fields for a complex test to be run, etc..