public class Options
extends java.lang.Object
--help
option), and
The programmer does not have to write any code, only declare and document variables. For each
field that you want to set from a command-line argument, you write Javadoc and an @Option
annotation. Then, the field is automatically set from a command-line
option of the same name, and usage messages and printed documentation are generated
automatically.
The following code enables a user to invoke theprogram using the command-line arguments --outfile
, -o
(shorthand for --outfile
), --ignore-case
, -i
, (shorthand for --ignore-case
), and --temperature
:
import org.plumelib.options.*; public class MyProgram { @Option("-o <filename> the output file ") public static File outfile = new File("/tmp/foobar"); @Option("-i ignore case") public static boolean ignore_case; @Option("set the initial temperature") public static double temperature = 75.0; public static void main(String[] args) { MyProgram myInstance = new MyProgram(); Options options = new Options("MyProgram [options] infile outfile", myInstance, MyUtilityClass.class); String[] remainingArgs = options.parse(true, args); ... } }In the code above, the call to
parse(boolean, String[])
sets fields in object myInstance
and sets static fields in class MyUtilityClass
. It returns the original
command line, with all options removed. If a command-line argument is incorrect, it prints a
usage message and terminates the program.
For examples of usage, see the documentation for Lookup, Randoop, and Javarifier.
@Option indicates a command-line option
The @Option
annotation on a field specifies brief user documentation and, optionally,
a one-character short name that a user may supply on the command line. The long name is taken
from the name of the variable. When the name contains an underscore, the user may substitute a
hyphen on the command line instead; for example, the --multi-word-variable
command-line option would set the variable multi_word_variable
.
On the command line, the values for options are specified in the form "--name=value" or "-name value". The value (after the "=" or " ") is mandatory for all options except booleans. Booleans are set to true if no value is specified. Booleans support "--no-optionname" which is equivalent to "--optionname=false".
A user may provide an option multiple times on the command line. If the field is a list, each entry is added to the list. If the field is not a list, then only the last occurrence is used (subsequent occurrences override the previous value).
All arguments that start with "-" are processed as
options. By default, the entire command line is scanned for options. To terminate option
processing at the first non-option argument, see setParseAfterArg(boolean)
. Also, the
special option "--" always terminates option
processing; "--" is discarded, but no subsequent parts
of the command line are scanned for options.
Unpublicized options
The @Unpublicized
annotation causes an option not to be displayed in the usage
message. This can be useful for options that are preliminary, experimental, or for internal
purposes only. The @Unpublicized
annotation must be specified in addition to the @Option
annotation.
The usage message can optionally include unpublicized options; see usage(boolean,String...)
.
Option groups
In a usage message or manual, it is useful to group related options and give the group a name. For examples of this, see the documentation for Lookup, Randoop, and Javarifier.
To specify option groups, declare related fields together in your .java
file, then
write @OptionGroup
on the first field in each group (including the first
@Option
-annotated field of every class and object passed to the Options(String,
Object...)
constructor).
The group name (the first argument of an @OptionGroup
annotation) must be unique among
all classes and objects passed to the Options(String, Object...)
constructor.
If an option group itself is unpublicized:
Option aliases
The @Option
annotation has an optional parameter aliases
, which accepts an
array of strings. Each string in the array is an alias for the option being defined and can be
used in place of an option's long name or short name.
One example is that a program might support "--optimize" and "--optimise" which are interchangeable. Another example is that a program might support "--help" and "-help" with the same meaning:
// The user may supply --help, -h, or -help, all of which mean the same thing and set this variable @Option(value="-h Print a help message", aliases={"-help"}) public static boolean help;Aliases should start with a single dash or double dash. If there is only a single, one-character alias, it can be put at the beginning of the value field or in the aliases field. It is the programmer's responsibility to ensure that no alias is the same as other options or aliases.
Generating documentation for a manual or manpage
It is helpful to include a summary of all command-line options in amanual, manpage, or the
class Javadoc for a class that has a main method. The OptionsDoclet
class generates HTML documentation.
Supported field types
A field with an @Option
annotation may be of the following types:
Customization
Option processing can be customized in a number of ways.
setUseSingleDash(boolean)
is true, then the long names take the form "-longname" instead of "--longname". It defaults to false.
setParseAfterArg(boolean)
is true, then options are searched for throughout a
command line, to its end. If it is false, then processing stops at the first non-option
argument. It defaults to true.
spaceSeparatedLists
is true, then when an argument contains spaces, it is
treated as multiple elements to be added to a list. It defaults to false.
usageSynopsis
to masquerade as another program.
useDashes
is false, then usage messages advertise long options with underscores
(as in --my_option_name
) instead of dashes (as in --my-option-name
). The
user can always specify either; this just affects usage messages. It defaults to false.
Limitations
Option
,
OptionGroup
,
Unpublicized
,
OptionsDoclet
Modifier and Type | Class and Description |
---|---|
static class |
Options.ArgException
Indicates an exception encountered during argument processing.
|
(package private) static class |
Options.OptionGroupInfo
Information about an option group.
|
(package private) class |
Options.OptionInfo
Information about an option.
|
private static class |
Options.ParseResult |
Modifier and Type | Field and Description |
---|---|
private boolean |
debugEnabled |
private java.util.Map<java.lang.String,Options.OptionGroupInfo> |
groupMap
Map from option group name to option group information.
|
private boolean |
hasGroups
If true, then the user is using
@OptionGroup annotations correctly (as per the
requirement specified above). |
private boolean |
hasListOption
True if some documented option accepts a list as a parameter.
|
private static java.lang.String |
lineSeparator
The system-dependent line separator.
|
private static java.lang.String |
LIST_HELP
String describing "[+]" (copied from Mercurial).
|
private java.lang.Class<?> |
mainClass
First specified class.
|
private java.util.Map<java.lang.String,Options.OptionInfo> |
nameMap
Map from short or long option names (with leading dashes) to option information.
|
private java.util.List<Options.OptionInfo> |
options
List of all of the defined options.
|
private java.lang.String |
optionsString
All of the argument options as a single string.
|
private boolean |
parseAfterArg
Whether to parse options after a non-option command-line argument.
|
static boolean |
spaceSeparatedLists
Whether to treat arguments to lists as space-separated.
|
@Nullable java.lang.String |
usageSynopsis
Synopsis of usage.
|
boolean |
useDashes
In usage messages, use dashes (hyphens) to split words in option names.
|
boolean |
useSingleDash
When true, long options take the form
-longOption with a single dash, rather than the default --longOption with two dashes. |
Constructor and Description |
---|
Options(java.lang.Object... args)
Prepare for option processing.
|
Options(java.lang.String usageSynopsis,
java.lang.Object... args)
Prepare for option processing.
|
Modifier and Type | Method and Description |
---|---|
void |
enableDebugLogging(boolean enabled)
Enable or disable debug logging.
|
private java.lang.String |
formatOptions(java.util.List<Options.OptionInfo> optList,
int maxLength,
boolean showUnpublicized)
Format a list of options for use in generating usage messages.
|
private <T extends java.lang.Enum<T>> |
getEnumValue(java.lang.Class<T> enumType,
java.lang.String name)
Behaves like
Enum.valueOf(java.lang.Class<T>, java.lang.String) , except that name is case-insensitive and
hyphen-insensitive (hyphens can be used in place of underscores). |
(package private) java.util.Collection<Options.OptionGroupInfo> |
getOptionGroups() |
(package private) java.util.List<Options.OptionInfo> |
getOptions() |
java.lang.String |
getOptionsString()
Returns a string containing all of the options that were set and their arguments.
|
private @NonNull java.lang.Object |
getRefArg(Options.OptionInfo oi,
java.lang.String argName,
java.lang.String argValue)
Given a value string supplied on the command line, create an object.
|
(package private) boolean |
getUseSingleDash() |
(package private) boolean |
hasGroups() |
private int |
maxOptionLength(java.util.List<Options.OptionInfo> optList,
boolean showUnpublicized)
Return the length of the longest synopsis message in a list of options.
|
java.lang.String[] |
parse(boolean showUsageOnError,
java.lang.String[] args)
Sets option variables from the given command line; if any command-line argument is illegal,
prints the usage message and terminates the program.
|
java.lang.String[] |
parse(java.lang.String[] args)
Sets option variables from the given command line.
|
java.lang.String[] |
parse(java.lang.String message,
java.lang.String[] args)
Sets option variables from the given command line; if any command-line argument is illegal,
prints the given message and terminates the program.
|
private static Options.ParseResult |
parseOption(java.lang.String val)
Parse an option value (the argument to
@Option ) and return its three components
(shortName, typeName, and description). |
(package private) static void |
printClassPath()
Print the classpath.
|
void |
printUsage()
Prints, to standard output, usage information.
|
void |
printUsage(java.io.PrintStream ps)
Prints usage information to the given PrintStream.
|
private static <T extends java.lang.annotation.Annotation> |
safeGetAnnotation(java.lang.reflect.Field f,
java.lang.Class<T> annotationClass)
Like
Field.getAnnotation(java.lang.Class<T>) , but returns null (and prints a warning) rather than throwing
an exception. |
private void |
setArg(Options.OptionInfo oi,
java.lang.String argName,
@Nullable java.lang.String argValue)
Set the specified option to the value specified in argValue.
|
void |
setParseAfterArg(boolean val)
If true, Options will parse arguments even after a non-option command-line argument.
|
java.lang.String |
settings()
Returns a string containing the current setting for each option, in command-line format that
can be parsed by Options.
|
java.lang.String |
settings(boolean showUnpublicized)
Returns a string containing the current setting for each option, in command-line format that
can be parsed by Options.
|
void |
setUseSingleDash(boolean val)
If true, long options (those derived from field names) are expected with a single dash prefix
as in
-long-option rather than --long-option . |
private static <K extends java.lang.Comparable<? super K>,V> |
sortedKeySet(java.util.Map<K,V> m)
Returns a sorted version of m.keySet().
|
static java.lang.String[] |
tokenize(java.lang.String args)
Splits the argument string into an array of tokens (command-line flags and arguments),
respecting single and double quotes.
|
java.lang.String |
toString()
Return a description of all of the known options.
|
private static java.lang.String |
typeShortName(java.lang.Class<?> type)
Return a short name for the specified type for use in messages.
|
java.lang.String |
usage(boolean showUnpublicized,
java.lang.String... groupNames)
Returns a usage message for command-line options.
|
java.lang.String |
usage(java.lang.String... groupNames)
Returns a usage message for command-line options.
|
public boolean useSingleDash
-longOption
with a single dash, rather than the default --longOption
with two dashes.private boolean parseAfterArg
setParseAfterArg(boolean)
public static boolean spaceSeparatedLists
When true, an argument to an option of list type is split, on whitespace, into multiple arguments each of which is added to the list. When false, each argument to an option of list type is treated as a single element, no matter what characters it contains.
For example, when this is true, a command line containing --my-option="foo bar"
is equivalent to --my-option="foo" --my-option="bar"
. Both of them have the effect of
adding two elements, "foo" and "bar", to the list my_option
.
public @Nullable java.lang.String usageSynopsis
This field is public so that clients can reset it. Setting it enables one program to masquerade as another program, based on parsed options.
public boolean useDashes
private java.lang.Class<?> mainClass
private final java.util.List<Options.OptionInfo> options
private final java.util.Map<java.lang.String,Options.OptionInfo> nameMap
private final java.util.Map<java.lang.String,Options.OptionGroupInfo> groupMap
private boolean hasGroups
@OptionGroup
annotations correctly (as per the
requirement specified above). If false, then @OptionGroup
annotations have not been
specified on any @Option
-annotated fields. When @OptionGroup
annotations are
used incorrectly, an Error is thrown by the Options constructor.OptionGroup
private static final java.lang.String LIST_HELP
private boolean debugEnabled
private java.lang.String optionsString
private static java.lang.String lineSeparator
private boolean hasListOption
public Options(java.lang.Object... args)
Option
) must be
unique across all the arguments.args
- the classes whose options to processpublic Options(java.lang.String usageSynopsis, java.lang.Object... args)
Option
) must be unique across all the arguments.usageSynopsis
- a synopsis of how to call your programargs
- the classes whose options to processpublic void enableDebugLogging(boolean enabled)
enabled
- whether to enable or disable loggingprivate static <T extends java.lang.annotation.Annotation> T safeGetAnnotation(java.lang.reflect.Field f, java.lang.Class<T> annotationClass)
Field.getAnnotation(java.lang.Class<T>)
, but returns null (and prints a warning) rather than throwing
an exception.T
- the type of the annotation to query for and return if presentf
- the Field that may contain the annotationannotationClass
- the Class object corresponding to the annotation type, or nullstatic void printClassPath()
public void setParseAfterArg(boolean val)
val
- whether to parse arguments after a non-option command-line argumentpublic void setUseSingleDash(boolean val)
-long-option
rather than --long-option
. The default is false and long
options will be parsed with a double dash prefix as in --longOption
.val
- whether to parse long options with a single dash, as in -longOption
public java.lang.String[] parse(java.lang.String[] args) throws Options.ArgException
args
- the commandline to be parsedOptions.ArgException
- if the command line contains unknown option or misused optionspublic static java.lang.String[] tokenize(java.lang.String args)
This method is only appropriate when the String[]
version of the arguments is not
available — for example, for the premain
method of a Java agent.
args
- the command line to be tokenizedmain
.public java.lang.String[] parse(java.lang.String message, java.lang.String[] args)
If an error occurs, prints the exception's message, prints the given message, and then terminates the program. The program is terminated rather than throwing an error to create cleaner output.
message
- a message to print, such as "Pass --help for a list of all command-line
arguments."args
- the command line to parseparse(String[])
public java.lang.String[] parse(boolean showUsageOnError, java.lang.String[] args)
If an error occurs and showUsageOnError
is true, prints the exception's message,
prints usage inoframtion, and then terminates the program. The program is terminated rather
than throwing an error to create cleaner output.
showUsageOnError
- if a command-line argument is incorrect, print a usage messageargs
- the command line to parseparse(String[])
public void printUsage(java.io.PrintStream ps)
ps
- where to print usage informationpublic void printUsage()
public java.lang.String usage(java.lang.String... groupNames)
groupNames
- the list of option groups to include in the usage message. If empty and
option groups are being used, will return usage for all option groups that are not
unpublicized. If empty and option groups are not being used, will return usage for all
options that are not unpublicized.public java.lang.String usage(boolean showUnpublicized, java.lang.String... groupNames)
showUnpublicized
- if true, treat all unpublicized options and option groups as publicizedgroupNames
- the list of option groups to include in the usage message. If empty and
option groups are being used, will return usage for all option groups that are not
unpublicized. If empty and option groups are not being used, will return usage for all
options that are not unpublicized.private java.lang.String formatOptions(java.util.List<Options.OptionInfo> optList, int maxLength, boolean showUnpublicized)
hasListOption
if any option has list type.optList
- the options to formatmaxLength
- the maximum number of characters in the outputshowUnpublicized
- if true, include unpublicized options in the outputprivate int maxOptionLength(java.util.List<Options.OptionInfo> optList, boolean showUnpublicized)
optList
- the options whose synopsis messages to measureshowUnpublicized
- if true, include unpublicized options in the computation@Pure boolean hasGroups()
@Pure boolean getUseSingleDash()
java.util.List<Options.OptionInfo> getOptions()
java.util.Collection<Options.OptionGroupInfo> getOptionGroups()
private void setArg(Options.OptionInfo oi, java.lang.String argName, @Nullable java.lang.String argValue) throws Options.ArgException
oi
- the option to setargName
- the name of the argument as passed on the command line; used only for debuggingargValue
- a string representation of the valueOptions.ArgException
- if there are any errorsprivate @NonNull java.lang.Object getRefArg(Options.OptionInfo oi, java.lang.String argName, java.lang.String argValue) throws Options.ArgException
oi
- the option corresponding to argName
and argValue
argName
- the argument name -- used only for diagnosticsargValue
- the value supplied on the command line, which this method parsesargValue
Options.ArgException
- if the user supplied an incorrect string (contained in argValue
)private <T extends java.lang.Enum<T>> T getEnumValue(java.lang.Class<T> enumType, java.lang.String name)
Enum.valueOf(java.lang.Class<T>, java.lang.String)
, except that name
is case-insensitive and
hyphen-insensitive (hyphens can be used in place of underscores). This allows for greater
flexibility when specifying enum types as command-line arguments.T
- the enum type whose constant is to be returnedenumType
- the Class object of the enum type from which to return a constantname
- the name of the constant to returnprivate static java.lang.String typeShortName(java.lang.Class<?> type)
type
- the type whoso short name to returnpublic java.lang.String getOptionsString()
settings()
public java.lang.String settings()
tokenize(java.lang.String)
, containing the current
setting for each optionpublic java.lang.String settings(boolean showUnpublicized)
showUnpublicized
- if true, treat all unpublicized options and option groups as publicizedtokenize(java.lang.String)
, containing the current
setting for each option@SideEffectFree public java.lang.String toString(@GuardSatisfied Options this)
toString
in class java.lang.Object
private static Options.ParseResult parseOption(java.lang.String val)
@Option
) and return its three components
(shortName, typeName, and description). The shortName and typeName are null if they are not
specified in the string.val
- the string to parse, which is an argument to @Option
private static <K extends java.lang.Comparable<? super K>,V> java.util.Collection<K> sortedKeySet(java.util.Map<K,V> m)
K
- type of the map keysV
- type of the map valuesm
- a map whose keyset will be sorted