blob: e734763c996c1ae1e4a8982b05fcce0ba3b13057 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html> <head>
<title>JCommander</title>
<link rel="stylesheet" href="testng.css" type="text/css" />
<link type="text/css" rel="stylesheet" href="http://beust.com/beust.css" />
<script type="text/javascript" src="http://beust.com/prettify.js"></script>
<script type="text/javascript" src="http://testng.org/doc/banner.js"></script>
<script type="text/javascript" src="http://beust.com/scripts/shCore.js"></script>
<script type="text/javascript" src="http://beust.com/scripts/shBrushJava.js"></script>
<script type="text/javascript" src="http://beust.com/scripts/shBrushXml.js"></script>
<script type="text/javascript" src="http://beust.com/scripts/shBrushBash.js"></script>
<script type="text/javascript" src="http://beust.com/scripts/shBrushPlain.js"></script>
<link type="text/css" rel="stylesheet" href="http://beust.com/styles/shCore.css"/>
<link type="text/css" rel="stylesheet" href="http://beust.com/styles/shThemeCedric.css"/>
<script type="text/javascript">
SyntaxHighlighter.config.clipboardSwf = 'scripts/clipboard.swf';
SyntaxHighlighter.defaults['gutter'] = false;
SyntaxHighlighter.all();
</script>
</head>
<body>
<table width="100%">
<tr>
<td align="center">
<h1>JCommander</h1>
<h2>Because life is too short to parse command line parameters</h2>
</td>
</tr>
<tr>
<td align="right">
Created: July 13th, 2010
</td>
</tr>
<tr><td align="right"><a href="mailto:cedric@beust.com">C&eacute;dric Beust</a></td></tr>
</table>
<h2>
Overview
</h2>
JCommander is a very small Java framework that makes it trivial to parse command line parameters.
<p>
You annotate fields with descriptions of your options:
<pre class="brush: java">
import com.beust.jcommander.Parameter;
public class JCommanderTest {
@Parameter
public List&lt;String&gt; parameters = Lists.newArrayList();
@Parameter(names = { "-log", "-verbose" }, description = "Level of verbosity")
public Integer verbose = 1;
@Parameter(names = "-groups", description = "Comma-separated list of group names to be run")
public String groups;
@Parameter(names = "-debug", description = "Debug mode")
public boolean debug = false;
}
</pre>
and then you simply ask JCommander to parse:
<pre class="brush: java">
JCommanderTest jct = new JCommanderTest();
String[] argv = { "-log", "2", "-groups", "unit", "a", "b", "c" };
new JCommander(jct, argv);
Assert.assertEquals(jct.verbose.intValue(), 2);
</pre>
<h2>
Types of options
</h2>
JCommander supports many types of options.
<h4>Boolean</h4>
When a <tt>Parameter</tt> annotation is found on a field of type <tt>boolean</tt> or <tt>Boolean</tt>, JCommander interprets it as an option with an <em>arity</em> of 0:
<pre class="brush: java">
@Parameter(names = "-debug", description = "Debug mode")
public boolean debug = false;
</pre>
Such a parameter does not require any additional parameter on the command line and if it's detected during parsing, the corresponding field will be set to <tt>true</tt>.
<h4>String, Integer, Long</h4>
When a <tt>Parameter</tt> annotation is found on a field of type <tt>String</tt>, <tt>Integer</tt>, <tt>int</tt>, <tt>Long</tt> or <tt>long</tt>, JCommander will parse the following parameter and it will attempt to cast it to the right type:
<pre class="brush: java">
@Parameter(names = "-log", description = "Level of verbosity")
public Integer verbose = 1;
</pre>
<pre class="brush: bash">
java Main -log 3
</pre>
will cause the field <tt>verbose</tt> to receive the value 3, however:
<pre class="brush: bash">
java Main -log test
</pre>
will cause an exception to be thrown.
<h4>Lists</h4>
When a <tt>Parameter</tt> annotation is found on a field of type <tt>List</tt>, JCommander will interpret it as an option that can occur multiple times:
<pre class="brush: java">
@Parameter(names = "-hosts", description = "Level of verbosity")
public List&lt;String&gt; hosts = new ArrayList&lt;String&gt;();
</pre>
will allow you to parse the following command line:
<pre class="brush: bash">
java Main -host host1 -verbose -host host2
</pre>
When JCommander is done parsing the line above, the field <tt>hosts</tt> will contain the strings "host1" and "host2".
<h4>Main parameter</h4>
So far, all the <tt>@Parameter</tt> annotations we have seen had defined an attribute called <tt>names</tt>. You can define one (and at most one) parameter without any such attribute. This parameter needs to be a <tt>List&lt;String&gt;</tt> and it will contain all the parameters that are not options:
<pre class="brush: java">
@Parameter(description = "Files")
public List&lt;String&gt; files = new ArrayList&lt;String&gt;();
@Parameter(names = "-debug", description = "Debugging level")
public Integer verbose = 1;
</pre>
will allow you to parse:
<pre class="brush: bash">
java Main -debug file1 file2
</pre>
and the field <tt>files</tt> will receive the strings "file1" and
"file2".
<h2>Multiple descriptions</h2>
You can spread the description of your parameters on more than one
class. For example, you can define the following two classes:
<p>
<h3 class="sourcetitle">ArgsMaster.java</h3>
<pre class="brush: java">
public class ArgsMaster {
@Parameter(names = "-master")
public String master;
}
</pre>
<h3 class="sourcetitle">ArgsSlave.java</h3>
<pre class="brush: java">
public class ArgsSlave {
@Parameter(names = "-slave")
public String slave;
}
</pre>
and pass these two objects to JCommander:
<pre class="brush: java">
ArgsMaster m = new ArgsMaster();
ArgsSlave s = new ArgsSlave();
String[] argv = { "-master", "master", "-slave", "slave" };
new JCommander(new Object[] { m , s }, argv);
Assert.assertEquals(m.master, "master");
Assert.assertEquals(s.slave, "slave");
</pre>
<h2>@ syntax</h2>
JCommander supports the @ syntax, which allows you to put all your options into a file and pass this file as parameter:
<p>
<h3 class="sourcetitle">/tmp/parameters</h3>
<pre class="brush: bash">
-verbose
file1
file2
file3
</pre>
<pre class="brush: bash">
java Main @/tmp/parameters
</pre>
<h2>Arities (multiple values for parameters)</h2>
If some of your parameters require more than one value, such as the
following example where two values are expected after <tt>-pairs</tt>:
<pre class="brush: bash">
java Main -pairs slave master foo.xml
</pre>
then you need to define your parameter with the <tt>arity</tt>
attribute and make that parameter a <tt>List&lt;String&gt;</tt>:
<pre class="brush: java">
@Parameter(names = "-pairs", arity = 2, description = "Pairs")
public List&lt;String&gt; pairs;
</pre>
You don't need to specify an arity for parameters of type
<tt>boolean</tt> or <tt>Boolean</tt> (which have a default arity of 0)
and of types <tt>String</tt>, <tt>Integer</tt>, <tt>int</tt>,
<tt>Long</tt> and <tt>long</tt> (which have a default arity of 1).
<p>
Also, note that only <tt>List&lt;String&gt;</tt> is allowed for
parameters that define an arity. You will have to convert these values
yourself if the parameters you need are of type <tt>Integer</tt> or
other (this limitation is due to Java's erasure).
<h2>Multiple option names</h2>
You can specify more than one option name:
<pre class="brush: java">
@Parameter(names = { "-d", "--outputDirectory" }, description = "Directory")
public String outputDirectory;
</pre>
will allow both following syntaxes:
<pre class="brush: bash">
java Main -d /tmp
java Main --outputDirectory /tmp
</pre>
<h2>Required and optional parameters</h2>
If some of your parameters are mandatory, you can use the
<tt>required</tt> attribute (which default to <tt>false</tt>):
<pre class="brush: java">
@Parameter(names = "-host", required = true)
public String host;
</pre>
If this parameter is not specified, JCommander will throw an exception
telling you which options are missing.
<h2>Exception</h2>
Whenever JCommander detects an error, it will throw a
<tt>ParameterException</tt>. Note that this is a Runtime Exception,
since your application is probably not initialized correctly at this
point.
<h2>Usage</h2>
You can invoke <tt>usage()</tt> on the <tt>JCommander</tt> instance that you used to parse your command line in order to generate a summary of all the options that your program understands:
<pre class="brush: bash">
Usage:
-port The port number
-debug Debug mode
-src, --sources The source directory
-testclass List of classes
</pre>
<h2>Internationalization</h2>
You can internationalize the descriptions of your parameters. First,
you use the <tt>descriptionKey</tt> attribute instead of
<tt>description</tt>. This <tt>descriptionKey</tt> is the key to the
string into your message bundle:
<h3 class="sourcetitle">I18N.java</h3>
<pre class="brush:java">
@Parameter(names = "-host", descriptionKey = "host")
String hostName;
</pre>
Your bundle needs to define this key:
<br>
<h3 class="sourcetitle">MessageBundle_fr_FR.properties</h3>
<pre class="brush: bash">
host: H&ocirc;te
</pre>
Then you pass the <tt>Locale</tt> when you initialize the JCommander
object:
<pre class="brush: java">
Locale locale = new Locale("fr", "FR");
ResourceBundle bundle = ResourceBundle.getBundle("MessageBundle", locale);
I18N i18n = new I18N();
String[] argv = { "-host", "localhost" };
JCommander jc = new JCommander(i18n, bundle, argv);
jc.usage();
</pre>
will display:
<pre class="brush: bash">
Usage:
-host H&ocirc;te
</pre>
<h2>More examples</h2>
TestNG uses JCommander to parse its command line, here is <a href="http://github.com/cbeust/testng/blob/master/src/main/java/org/testng/CommandLineArgs.java">its definition file</a>.
<h2>Download</h2>
You can download JCommander from the following locations:
<ul>
<li><a href="http://beust.com/jcommander/jcommander-1.0-SNAPSHOT.jar">Binary</a></li>
<li><a href="http://github.com/cbeust/jcommander">Source on github</a></li>
</ul>
</body>
</html>