/* Copyright 2017 Remko Popma Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package picocli; import java.io.*; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.*; import java.math.BigDecimal; import java.math.BigInteger; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.NetworkInterface; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.nio.ByteOrder; import java.nio.charset.Charset; import java.text.BreakIterator; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; import java.util.regex.Pattern; import picocli.CommandLine.Help.Ansi.IStyle; import picocli.CommandLine.Help.Ansi.Style; import picocli.CommandLine.Help.Ansi.Text; import picocli.CommandLine.Model.*; import picocli.CommandLine.ParseResult.GroupMatchContainer; import static java.util.Locale.ENGLISH; import static picocli.CommandLine.Help.Column.Overflow.SPAN; import static picocli.CommandLine.Help.Column.Overflow.TRUNCATE; import static picocli.CommandLine.Help.Column.Overflow.WRAP; /** *

* CommandLine interpreter that uses reflection to initialize an annotated user object with values obtained from the * command line arguments. *

* The full user manual is hosted at https://picocli.info. *

Example

*

* An example that implements {@code Callable} and uses the {@link #execute(String...) CommandLine.execute} convenience API to run in a single line of code: *

*
 * @Command(name = "checksum", mixinStandardHelpOptions = true, version = "checksum 4.0",
 *          description = "Prints the checksum (SHA-1 by default) of a file to STDOUT.")
 * class CheckSum implements Callable<Integer> {
 *
 *     @Parameters(index = "0", description = "The file whose checksum to calculate.")
 *     private File file;
 *
 *     @Option(names = {"-a", "--algorithm"}, description = "MD5, SHA-1, SHA-256, ...")
 *     private String algorithm = "SHA-1";
 *
 *     @Override
 *     public Integer call() throws Exception { // your business logic goes here...
 *         byte[] fileContents = Files.readAllBytes(file.toPath());
 *         byte[] digest = MessageDigest.getInstance(algorithm).digest(fileContents);
 *         System.out.printf("%0" + (digest.length*2) + "x%n", new BigInteger(1,digest));
 *         return 0;
 *     }
 *
 *     // CheckSum implements Callable, so parsing, error handling and handling user
 *     // requests for usage help or version help can be done with one line of code.
 *     public static void main(String[] args) {
 *         int exitCode = new CommandLine(new CheckSum()).execute(args);
 *         System.exit(exitCode);
 *     }
 * }
 * 
*

Another example where the application calls {@code parseArgs} and takes responsibility * for error handling and checking whether the user requested help:

*
import static picocli.CommandLine.*;
 *
 * @Command(mixinStandardHelpOptions = true, version = "v3.0.0",
 *         header = "Encrypt FILE(s), or standard input, to standard output or to the output file.")
 * public class Encrypt {
 *
 *     @Parameters(description = "Any number of input files")
 *     private List<File> files = new ArrayList<File>();
 *
 *     @Option(names = { "-o", "--out" }, description = "Output file (default: print to console)")
 *     private File outputFile;
 *
 *     @Option(names = { "-v", "--verbose"}, description = "Verbose mode. Helpful for troubleshooting. Multiple -v options increase the verbosity.")
 *     private boolean[] verbose;
 * }
 * 
*

* Use {@code CommandLine} to initialize a user object as follows: *

 * public static void main(String... args) {
 *     Encrypt encrypt = new Encrypt();
 *     try {
 *         ParseResult parseResult = new CommandLine(encrypt).parseArgs(args);
 *         if (!CommandLine.printHelpIfRequested(parseResult)) {
 *             runProgram(encrypt);
 *         }
 *     } catch (ParameterException ex) { // command line arguments could not be parsed
 *         System.err.println(ex.getMessage());
 *         ex.getCommandLine().usage(System.err);
 *     }
 * }
 * 

* Invoke the above program with some command line arguments. The below are all equivalent: *

*
 * --verbose --out=outfile in1 in2
 * --verbose --out outfile in1 in2
 * -v --out=outfile in1 in2
 * -v -o outfile in1 in2
 * -v -o=outfile in1 in2
 * -vo outfile in1 in2
 * -vo=outfile in1 in2
 * -v -ooutfile in1 in2
 * -vooutfile in1 in2
 * 
*

Classes and Interfaces for Defining a CommandSpec Model

*

* Classes and Interfaces for Defining a CommandSpec Model *

*

Classes Related to Parsing Command Line Arguments

*

* Classes Related to Parsing Command Line Arguments *

*/ public class CommandLine { /** This is picocli version {@value}. */ public static final String VERSION = "4.7.6-SNAPSHOT"; private static final Tracer TRACER = new Tracer(); private CommandSpec commandSpec; private final Interpreter interpreter; private final IFactory factory; private Object executionResult; private PrintWriter out; private PrintWriter err; private Help.ColorScheme colorScheme = Help.defaultColorScheme(Help.Ansi.AUTO); private IExitCodeExceptionMapper exitCodeExceptionMapper; private IExecutionStrategy executionStrategy = new RunLast(); private IParameterExceptionHandler parameterExceptionHandler = new IParameterExceptionHandler() { public int handleParseException(ParameterException ex, String[] args) { CommandLine cmd = ex.getCommandLine(); DefaultExceptionHandler.internalHandleParseException(ex, cmd.getErr(), cmd.getColorScheme()); return mappedExitCode(ex, cmd.getExitCodeExceptionMapper(), cmd.getCommandSpec().exitCodeOnInvalidInput()); } }; private IExecutionExceptionHandler executionExceptionHandler = new IExecutionExceptionHandler() { public int handleExecutionException(Exception ex, CommandLine commandLine, ParseResult parseResult) throws Exception { throw ex; } }; /** * Constructs a new {@code CommandLine} interpreter with the specified object (which may be an annotated user object or a {@link CommandSpec CommandSpec}) and a default {@linkplain IFactory factory}. *

The specified object may be a {@link CommandSpec CommandSpec} object, or it may be a {@code @Command}-annotated * user object with {@code @Option} and {@code @Parameters}-annotated fields and methods, in which case picocli automatically * constructs a {@code CommandSpec} from this user object. *

If the specified command object is an interface {@code Class} with {@code @Option} and {@code @Parameters}-annotated methods, * picocli creates a {@link java.lang.reflect.Proxy Proxy} whose methods return the matched command line values. * If the specified command object is a concrete {@code Class}, picocli delegates to the default factory to get an instance. *

* If the specified object implements {@code Runnable} or {@code Callable}, or if it is a {@code Method} object, * the command can be run as an application in a single line of code by using the * {@link #execute(String...) execute} method to omit some boilerplate code for handling help requests and invalid input. * See {@link #getCommandMethods(Class, String) getCommandMethods} for a convenient way to obtain a command {@code Method}. *

* When the {@link #parseArgs(String...)} method is called, the {@link CommandSpec CommandSpec} object will be * initialized based on command line arguments. If the commandSpec is created from an annotated user object, this * user object will be initialized based on the command line arguments. *

* @param command an annotated user object or a {@code CommandSpec} object to initialize from the command line arguments * @throws InitializationException if the specified command object does not have a {@link Command}, {@link Option} or {@link Parameters} annotation */ public CommandLine(Object command) { this(command, new DefaultFactory()); } /** * Constructs a new {@code CommandLine} interpreter with the specified object (which may be an annotated user object or a {@link CommandSpec CommandSpec}) and object factory. *

The specified object may be a {@link CommandSpec CommandSpec} object, or it may be a {@code @Command}-annotated * user object with {@code @Option} and {@code @Parameters}-annotated fields and methods, in which case picocli automatically * constructs a {@code CommandSpec} from this user object. *

If the specified command object is an interface {@code Class} with {@code @Option} and {@code @Parameters}-annotated methods, * picocli creates a {@link java.lang.reflect.Proxy Proxy} whose methods return the matched command line values. * If the specified command object is a concrete {@code Class}, picocli delegates to the {@linkplain IFactory factory} to get an instance. *

* If the specified object implements {@code Runnable} or {@code Callable}, or if it is a {@code Method} object, * the command can be run as an application in a single line of code by using the * {@link #execute(String...) execute} method to omit some boilerplate code for handling help requests and invalid input. * See {@link #getCommandMethods(Class, String) getCommandMethods} for a convenient way to obtain a command {@code Method}. *

* When the {@link #parseArgs(String...)} method is called, the {@link CommandSpec CommandSpec} object will be * initialized based on command line arguments. If the commandSpec is created from an annotated user object, this * user object will be initialized based on the command line arguments. *

* @param command an annotated user object or a {@code CommandSpec} object to initialize from the command line arguments * @param factory the factory used to create instances of {@linkplain Command#subcommands() subcommands}, {@linkplain Option#converter() converters}, etc., that are registered declaratively with annotation attributes * @throws InitializationException if the specified command object does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @since 2.2 */ public CommandLine(Object command, IFactory factory) { this(command, factory, true); } private CommandLine(Object command, IFactory factory, boolean userCalled) { this.factory = Assert.notNull(factory, "factory"); interpreter = new Interpreter(); commandSpec = CommandSpec.forAnnotatedObject(command, factory); commandSpec.commandLine(this); if (userCalled) { this.applyModelTransformations(); } commandSpec.validate(); if (commandSpec.unmatchedArgsBindings().size() > 0) { setUnmatchedArgumentsAllowed(true); } } /** Apply transformers to command spec recursively. */ private void applyModelTransformations() { if (commandSpec.modelTransformer != null) { commandSpec = commandSpec.modelTransformer.transform(commandSpec); } for (CommandLine cmd : getSubcommands().values()) { cmd.applyModelTransformations(); } } private CommandLine copy() { CommandLine result = new CommandLine(commandSpec.copy(), factory); // create a new sub-hierarchy result.err = err; result.out = out; result.colorScheme = colorScheme; result.executionStrategy = executionStrategy; result.exitCodeExceptionMapper = exitCodeExceptionMapper; result.executionExceptionHandler = executionExceptionHandler; result.parameterExceptionHandler = parameterExceptionHandler; result.interpreter.converterRegistry.clear(); result.interpreter.converterRegistry.putAll(interpreter.converterRegistry); return result; } /** * Returns the {@code CommandSpec} model that this {@code CommandLine} was constructed with. * @return the {@code CommandSpec} model * @since 3.0 */ public CommandSpec getCommandSpec() { return commandSpec; } /** * Adds the options and positional parameters in the specified mixin to this command. *

The specified object may be a {@link CommandSpec CommandSpec} object, or it may be a user object with * {@code @Option} and {@code @Parameters}-annotated fields, in which case picocli automatically * constructs a {@code CommandSpec} from this user object. *

* @param name the name by which the mixin object may later be retrieved * @param mixin an annotated user object or a {@link CommandSpec CommandSpec} object whose options and positional parameters to add to this command * @return this CommandLine object, to allow method chaining * @since 3.0 */ public CommandLine addMixin(String name, Object mixin) { getCommandSpec().addMixin(name, CommandSpec.forAnnotatedObject(mixin, factory)); return this; } /** * Returns a map of user objects whose options and positional parameters were added to ("mixed in" with) this command. * @return a new Map containing the user objects mixed in with this command. If {@code CommandSpec} objects without * user objects were programmatically added, use the {@link CommandSpec#mixins() underlying model} directly. * @since 3.0 */ public Map getMixins() { Map mixins = getCommandSpec().mixins(); Map result = new LinkedHashMap(); for (String name : mixins.keySet()) { result.put(name, mixins.get(name).userObject.getInstance()); } return result; } /** Registers a subcommand with the name obtained from the {@code @Command(name = "...")} {@linkplain Command#name() annotation attribute} of the specified command. * @param command the object to initialize with command line arguments following the subcommand name. * This may be a {@code Class} that has a {@code @Command} annotation, or an instance of such a * class, or a {@code CommandSpec} or {@code CommandLine} instance with its own (nested) subcommands. * @return this CommandLine object, to allow method chaining * @since 4.0 * @throws InitializationException if no name could be found for the specified subcommand, * or if another subcommand was already registered under the same name, or if one of the aliases * of the specified subcommand was already used by another subcommand. * @see #addSubcommand(String, Object) */ public CommandLine addSubcommand(Object command) { return addSubcommand(null, command, new String[0]); } /** Registers a subcommand with the specified name. For example: *
     * CommandLine commandLine = new CommandLine(new Git())
     *         .addSubcommand("status",   new GitStatus())
     *         .addSubcommand("commit",   new GitCommit();
     *         .addSubcommand("add",      new GitAdd())
     *         .addSubcommand("branch",   new GitBranch())
     *         .addSubcommand("checkout", new GitCheckout())
     *         //...
     *         ;
     * 
* *

The specified object can be an annotated object or a * {@code CommandLine} instance with its own nested subcommands. For example:

*
     * CommandLine commandLine = new CommandLine(new MainCommand())
     *         .addSubcommand("cmd1",                 new ChildCommand1()) // subcommand
     *         .addSubcommand("cmd2",                 new ChildCommand2())
     *         .addSubcommand("cmd3", new CommandLine(new ChildCommand3()) // subcommand with nested sub-subcommands
     *                 .addSubcommand("cmd3sub1",                 new GrandChild3Command1())
     *                 .addSubcommand("cmd3sub2",                 new GrandChild3Command2())
     *                 .addSubcommand("cmd3sub3", new CommandLine(new GrandChild3Command3()) // deeper nesting
     *                         .addSubcommand("cmd3sub3sub1", new GreatGrandChild3Command3_1())
     *                         .addSubcommand("cmd3sub3sub2", new GreatGrandChild3Command3_2())
     *                 )
     *         );
     * 
*

The default type converters are available on all subcommands and nested sub-subcommands, but custom type * converters are registered only with the subcommand hierarchy as it existed when the custom type was registered. * To ensure a custom type converter is available to all subcommands, register the type converter last, after * adding subcommands.

*

See also the {@link Command#subcommands()} annotation to register subcommands declaratively.

* * @param name the string to recognize on the command line as a subcommand. * If {@code null}, the {@linkplain CommandSpec#name() name} of the specified subcommand is used; * if this is also {@code null}, the first {@linkplain CommandSpec#aliases() alias} is used. * @param command the object to initialize with command line arguments following the subcommand name. * This may be a {@code Class} that has a {@code @Command} annotation, or an instance of such a * class, or a {@code CommandSpec} or {@code CommandLine} instance with its own (nested) subcommands. * @return this CommandLine object, to allow method chaining * @see #registerConverter(Class, ITypeConverter) * @since 0.9.7 * @see Command#subcommands() * @throws InitializationException if the specified name is {@code null}, and no alternative name could be found, * or if another subcommand was already registered under the same name, or if one of the aliases * of the specified subcommand was already used by another subcommand. */ public CommandLine addSubcommand(String name, Object command) { return addSubcommand(name, command, new String[0]); } /** Registers a subcommand with the specified name and all specified aliases. See also {@link #addSubcommand(String, Object)}. * @param name the string to recognize on the command line as a subcommand. * If {@code null}, the {@linkplain CommandSpec#name() name} of the specified subcommand is used; * if this is also {@code null}, the first {@linkplain CommandSpec#aliases() alias} is used. * @param command the object to initialize with command line arguments following the subcommand name. * This may be a {@code Class} that has a {@code @Command} annotation, or an instance of such a * class, or a {@code CommandSpec} or {@code CommandLine} instance with its own (nested) subcommands. * @param aliases zero or more alias names that are also recognized on the command line as this subcommand * @return this CommandLine object, to allow method chaining * @since 3.1 * @see #addSubcommand(String, Object) * @throws InitializationException if the specified name is {@code null}, and no alternative name could be found, * or if another subcommand was already registered under the same name, or if one of the aliases * of the specified subcommand was already used by another subcommand. */ public CommandLine addSubcommand(String name, Object command, String... aliases) { CommandLine subcommandLine = toCommandLine(command, factory); subcommandLine.getCommandSpec().aliases.addAll(Arrays.asList(aliases)); getCommandSpec().addSubcommand(name, subcommandLine); return this; } /** Returns a map with the subcommands {@linkplain #addSubcommand(String, Object) registered} on this instance. * @return a map with the registered subcommands * @since 0.9.7 */ public Map getSubcommands() { return new CaseAwareLinkedMap(getCommandSpec().commands); } /** * Returns the command that this is a subcommand of, or {@code null} if this is a top-level command. * @return the command that this is a subcommand of, or {@code null} if this is a top-level command * @see #addSubcommand(String, Object) * @see Command#subcommands() * @since 0.9.8 */ public CommandLine getParent() { CommandSpec parent = getCommandSpec().parent(); return parent == null ? null : parent.commandLine(); } /** Returns the annotated user object that this {@code CommandLine} instance was constructed with. * @param the type of the variable that the return value is being assigned to * @return the annotated object that this {@code CommandLine} instance was constructed with * @since 0.9.7 */ @SuppressWarnings("unchecked") public T getCommand() { return (T) getCommandSpec().userObject(); } /** Returns the factory that this {@code CommandLine} was constructed with. * @return the factory that this {@code CommandLine} was constructed with, never {@code null} * @since 4.6 */ public IFactory getFactory() { return factory; } /** Returns {@code true} if an option annotated with {@link Option#usageHelp()} was specified on the command line. * @return whether the parser encountered an option annotated with {@link Option#usageHelp()}. * @since 0.9.8 */ public boolean isUsageHelpRequested() { return interpreter.parseResultBuilder != null && interpreter.parseResultBuilder.usageHelpRequested; } /** Returns {@code true} if an option annotated with {@link Option#versionHelp()} was specified on the command line. * @return whether the parser encountered an option annotated with {@link Option#versionHelp()}. * @since 0.9.8 */ public boolean isVersionHelpRequested() { return interpreter.parseResultBuilder != null && interpreter.parseResultBuilder.versionHelpRequested; } /** Returns a new {@code Help} object created by the {@code IHelpFactory} with the {@code CommandSpec} and {@code ColorScheme} of this command. * @see Help#Help(CommandSpec, Help.ColorScheme) * @see #getHelpFactory() * @see #getCommandSpec() * @see #getColorScheme() * @since 4.1 */ public Help getHelp() { return getHelpFactory().create(getCommandSpec(), getColorScheme()); } /** Returns the {@code IHelpFactory} that is used to construct the usage help message. * @see #setHelpFactory(IHelpFactory) * @since 3.9 */ public IHelpFactory getHelpFactory() { return getCommandSpec().usageMessage().helpFactory(); } /** Sets a new {@code IHelpFactory} to customize the usage help message. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param helpFactory the new help factory. Must be non-{@code null}. * @return this {@code CommandLine} object, to allow method chaining * @since 3.9 */ public CommandLine setHelpFactory(IHelpFactory helpFactory) { getCommandSpec().usageMessage().helpFactory(helpFactory); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setHelpFactory(helpFactory); } return this; } /** * Returns the section keys in the order that the usage help message should render the sections. * This ordering may be modified with {@link #setHelpSectionKeys(List) setSectionKeys}. The default keys are (in order): *
    *
  1. {@link UsageMessageSpec#SECTION_KEY_HEADER_HEADING SECTION_KEY_HEADER_HEADING}
  2. *
  3. {@link UsageMessageSpec#SECTION_KEY_HEADER SECTION_KEY_HEADER}
  4. *
  5. {@link UsageMessageSpec#SECTION_KEY_SYNOPSIS_HEADING SECTION_KEY_SYNOPSIS_HEADING}
  6. *
  7. {@link UsageMessageSpec#SECTION_KEY_SYNOPSIS SECTION_KEY_SYNOPSIS}
  8. *
  9. {@link UsageMessageSpec#SECTION_KEY_DESCRIPTION_HEADING SECTION_KEY_DESCRIPTION_HEADING}
  10. *
  11. {@link UsageMessageSpec#SECTION_KEY_DESCRIPTION SECTION_KEY_DESCRIPTION}
  12. *
  13. {@link UsageMessageSpec#SECTION_KEY_PARAMETER_LIST_HEADING SECTION_KEY_PARAMETER_LIST_HEADING}
  14. *
  15. {@link UsageMessageSpec#SECTION_KEY_AT_FILE_PARAMETER SECTION_KEY_AT_FILE_PARAMETER}
  16. *
  17. {@link UsageMessageSpec#SECTION_KEY_PARAMETER_LIST SECTION_KEY_PARAMETER_LIST}
  18. *
  19. {@link UsageMessageSpec#SECTION_KEY_OPTION_LIST_HEADING SECTION_KEY_OPTION_LIST_HEADING}
  20. *
  21. {@link UsageMessageSpec#SECTION_KEY_OPTION_LIST SECTION_KEY_OPTION_LIST}
  22. *
  23. {@link UsageMessageSpec#SECTION_KEY_COMMAND_LIST_HEADING SECTION_KEY_COMMAND_LIST_HEADING}
  24. *
  25. {@link UsageMessageSpec#SECTION_KEY_COMMAND_LIST SECTION_KEY_COMMAND_LIST}
  26. *
  27. {@link UsageMessageSpec#SECTION_KEY_EXIT_CODE_LIST_HEADING SECTION_KEY_EXIT_CODE_LIST_HEADING}
  28. *
  29. {@link UsageMessageSpec#SECTION_KEY_EXIT_CODE_LIST SECTION_KEY_EXIT_CODE_LIST}
  30. *
  31. {@link UsageMessageSpec#SECTION_KEY_FOOTER_HEADING SECTION_KEY_FOOTER_HEADING}
  32. *
  33. {@link UsageMessageSpec#SECTION_KEY_FOOTER SECTION_KEY_FOOTER}
  34. *
* @since 3.9 */ public List getHelpSectionKeys() { return getCommandSpec().usageMessage().sectionKeys(); } /** * Sets the section keys in the order that the usage help message should render the sections. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

*

Use {@link UsageMessageSpec#sectionKeys(List)} to customize a command without affecting its subcommands.

* @see #getHelpSectionKeys * @since 3.9 */ public CommandLine setHelpSectionKeys(List keys) { getCommandSpec().usageMessage().sectionKeys(keys); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setHelpSectionKeys(keys); } return this; } /** * Returns the map of section keys and renderers used to construct the usage help message. * The usage help message can be customized by adding, replacing and removing section renderers from this map. * Sections can be reordered with {@link #setHelpSectionKeys(List) setSectionKeys}. * Sections that are either not in this map or not in the list returned by {@link #getHelpSectionKeys() getSectionKeys} are omitted. *

* NOTE: By modifying the returned {@code Map}, only the usage help message of this command is affected. * Use {@link #setHelpSectionMap(Map)} to customize the usage help message for this command and all subcommands. *

* @since 3.9 */ public Map getHelpSectionMap() { return getCommandSpec().usageMessage().sectionMap(); } /** * Sets the map of section keys and renderers used to construct the usage help message. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

*

Use {@link UsageMessageSpec#sectionMap(Map)} to customize a command without affecting its subcommands.

* @see #getHelpSectionMap * @since 3.9 */ public CommandLine setHelpSectionMap(Map map) { getCommandSpec().usageMessage().sectionMap(map); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setHelpSectionMap(map); } return this; } /** * Returns whether line breaks should take wide Chinese, Japanese and Korean characters into account for line-breaking purposes. The default is {@code true}. * @return true if wide Chinese, Japanese and Korean characters are counted as double the size of other characters for line-breaking purposes * @since 4.0 */ public boolean isAdjustLineBreaksForWideCJKCharacters() { return getCommandSpec().usageMessage().adjustLineBreaksForWideCJKCharacters(); } /** Sets whether line breaks should take wide Chinese, Japanese and Korean characters into account, and returns this UsageMessageSpec. The default is {@code true}. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param adjustForWideChars if true, wide Chinese, Japanese and Korean characters are counted as double the size of other characters for line-breaking purposes * @since 4.0 */ public CommandLine setAdjustLineBreaksForWideCJKCharacters(boolean adjustForWideChars) { getCommandSpec().usageMessage().adjustLineBreaksForWideCJKCharacters(adjustForWideChars); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setAdjustLineBreaksForWideCJKCharacters(adjustForWideChars); } return this; } /** Returns whether the value of boolean flag options should be "toggled" when the option is matched. * From 4.0, this is {@code false} by default, and when a flag option is specified on the command line picocli * will set its value to the opposite of its default value. * If this method returns {@code true}, flags are toggled, so if the value is {@code true} it is * set to {@code false}, and when the value is {@code false} it is set to {@code true}. * When toggling is enabled, specifying a flag option twice on the command line will have no effect because they cancel each other out. * @return {@code true} the value of boolean flag options should be "toggled" when the option is matched, {@code false} otherwise * @since 3.0 */ public boolean isToggleBooleanFlags() { return getCommandSpec().parser().toggleBooleanFlags(); } /** Sets whether the value of boolean flag options should be "toggled" when the option is matched. The default is {@code false}, * and when a flag option is specified on the command line picocli will set its value to the opposite of its default value. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param newValue the new setting * @return this {@code CommandLine} object, to allow method chaining * @since 3.0 */ public CommandLine setToggleBooleanFlags(boolean newValue) { getCommandSpec().parser().toggleBooleanFlags(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setToggleBooleanFlags(newValue); } return this; } /** Returns whether variables should be interpolated in String values. The default is {@code true}. * @since 4.0 */ public boolean isInterpolateVariables() { return getCommandSpec().interpolateVariables(); } /** Sets whether variables should be interpolated in String values. The default is {@code true}. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @since 4.0 */ public CommandLine setInterpolateVariables(boolean interpolate) { getCommandSpec().interpolateVariables(interpolate); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setInterpolateVariables(interpolate); } return this; } /** Returns whether options for single-value fields can be specified multiple times on the command line. * The default is {@code false} and a {@link OverwrittenOptionException} is thrown if this happens. * When {@code true}, the last specified value is retained. * @return {@code true} if options for single-value fields can be specified multiple times on the command line, {@code false} otherwise * @since 0.9.7 */ public boolean isOverwrittenOptionsAllowed() { return getCommandSpec().parser().overwrittenOptionsAllowed(); } /** Sets whether options for single-value fields can be specified multiple times on the command line without a {@link OverwrittenOptionException} being thrown. * The default is {@code false}. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param newValue the new setting * @return this {@code CommandLine} object, to allow method chaining * @since 0.9.7 */ public CommandLine setOverwrittenOptionsAllowed(boolean newValue) { getCommandSpec().parser().overwrittenOptionsAllowed(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setOverwrittenOptionsAllowed(newValue); } return this; } /** Returns whether the parser accepts clustered short options. The default is {@code true}. * @return {@code true} if short options like {@code -x -v -f SomeFile} can be clustered together like {@code -xvfSomeFile}, {@code false} otherwise * @since 3.0 */ public boolean isPosixClusteredShortOptionsAllowed() { return getCommandSpec().parser().posixClusteredShortOptionsAllowed(); } /** Sets whether short options like {@code -x -v -f SomeFile} can be clustered together like {@code -xvfSomeFile}. The default is {@code true}. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param newValue the new setting * @return this {@code CommandLine} object, to allow method chaining * @since 3.0 */ public CommandLine setPosixClusteredShortOptionsAllowed(boolean newValue) { getCommandSpec().parser().posixClusteredShortOptionsAllowed(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setPosixClusteredShortOptionsAllowed(newValue); } return this; } /** Returns whether the parser should ignore case when converting arguments to {@code enum} values. The default is {@code false}. * @return {@code true} if enum values can be specified that don't match the {@code toString()} value of the enum constant, {@code false} otherwise; * e.g., for an option of type java.time.DayOfWeek, * values {@code MonDaY}, {@code monday} and {@code MONDAY} are all recognized if {@code true}. * @since 3.4 */ public boolean isCaseInsensitiveEnumValuesAllowed() { return getCommandSpec().parser().caseInsensitiveEnumValuesAllowed(); } /** Sets whether the parser should ignore case when converting arguments to {@code enum} values. The default is {@code false}. * When set to true, for example, for an option of type java.time.DayOfWeek, * values {@code MonDaY}, {@code monday} and {@code MONDAY} are all recognized if {@code true}. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param newValue the new setting * @return this {@code CommandLine} object, to allow method chaining * @since 3.4 */ public CommandLine setCaseInsensitiveEnumValuesAllowed(boolean newValue) { getCommandSpec().parser().caseInsensitiveEnumValuesAllowed(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setCaseInsensitiveEnumValuesAllowed(newValue); } return this; } /** Returns whether the parser should trim quotes from command line arguments. The default is * read from the system property "picocli.trimQuotes" and will be {@code true} if the property is present and empty, * or if its value is "true". *

If this property is set to {@code true}, the parser will remove quotes from the command line arguments, as follows:

*
    *
  • if the command line argument contains just the leading and trailing quote, these quotes are removed
  • *
  • if the command line argument contains more quotes than just the leading and trailing quote, the parser first * tries to process the parameter with the quotes intact. For example, the {@code split} regular expression inside * a quoted region should be ignored, so arguments like {@code "a,b","x,y"} are handled correctly. * For arguments with nested quotes, quotes are removed later in the processing pipeline, after {@code split} operations are applied.
  • *
* @return {@code true} if the parser should trim quotes from command line arguments before processing them, {@code false} otherwise; * @see ParserSpec#trimQuotes() * @since 3.7 */ public boolean isTrimQuotes() { return getCommandSpec().parser().trimQuotes(); } /** Sets whether the parser should trim quotes from command line arguments before processing them. The default is * read from the system property "picocli.trimQuotes" and will be {@code true} if the property is set and empty, or * if its value is "true". *

If this property is set to {@code true}, the parser will remove quotes from the command line arguments, as follows:

*
    *
  • if the command line argument contains just the leading and trailing quote, these quotes are removed
  • *
  • if the command line argument contains more quotes than just the leading and trailing quote, the parser first * tries to process the parameter with the quotes intact. For example, the {@code split} regular expression inside * a quoted region should be ignored, so arguments like {@code "a,b","x,y"} are handled correctly. * For arguments with nested quotes, quotes are removed later in the processing pipeline, after {@code split} operations are applied.
  • *
*

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

*

Calling this method will cause the "picocli.trimQuotes" property to have no effect.

* @param newValue the new setting * @return this {@code CommandLine} object, to allow method chaining * @see ParserSpec#trimQuotes(boolean) * @since 3.7 */ public CommandLine setTrimQuotes(boolean newValue) { getCommandSpec().parser().trimQuotes(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setTrimQuotes(newValue); } return this; } /** Returns whether the parser is allowed to split quoted Strings or not. The default is {@code false}, * so quotes are respected: quoted strings are treated as a single value that should not be broken up. *

* For example, take a single command line parameter {@code "a,b","x,y"}. With a comma split regex, the default of {@code splitQuotedStrings = false} * means that this value will be split into two strings: {@code "a,b"} and {@code "x,y"}. This is usually what you want. *

* If {@code splitQuotedStrings} is set to {@code true}, quotes are not respected, and the value is split up into four parts: * the first is {@code "a}, the second is {@code b"}, the third is {@code "x}, and the last part is {@code y"}. This is generally not what you want. *

* @deprecated Most applications should not change the default. The rare application that does need to split parameter values * without respecting quotes should use {@link ParserSpec#splitQuotedStrings(boolean)}. * @return {@code true} if the parser is allowed to split quoted Strings, {@code false} otherwise; * @see ArgSpec#splitRegex() * @see ParserSpec#splitQuotedStrings() * @since 3.7 */ @Deprecated public boolean isSplitQuotedStrings() { return getCommandSpec().parser().splitQuotedStrings(); } /** Sets whether the parser is allowed to split quoted Strings. The default is {@code false}, * so quotes are respected: quoted strings are treated as a single value that should not be broken up. *

* For example, take a single command line parameter {@code "a,b","x,y"}. With a comma split regex, the default of {@code splitQuotedStrings = false} * means that this value will be split into two strings: {@code "a,b"} and {@code "x,y"}. This is usually what you want. *

* However, if {@code splitQuotedStrings} is set to {@code true}, quotes are not respected, and the value is split up into four parts: * the first is {@code "a}, the second is {@code b"}, the third is {@code "x}, and the last part is {@code y"}. This is generally not what you want. *

*

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @deprecated Most applications should not change the default. The rare application that does need to split parameter values * without respecting quotes should use {@link ParserSpec#splitQuotedStrings(boolean)}. * @param newValue the new setting * @return this {@code CommandLine} object, to allow method chaining * @see ArgSpec#splitRegex() * @see ParserSpec#splitQuotedStrings(boolean) * @since 3.7 */ @Deprecated public CommandLine setSplitQuotedStrings(boolean newValue) { getCommandSpec().parser().splitQuotedStrings(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setSplitQuotedStrings(newValue); } return this; } /** Returns the end-of-options delimiter that signals that the remaining command line arguments should be treated as positional parameters. * @return the end-of-options delimiter. The default is {@code "--"}. * @since 3.5 */ public String getEndOfOptionsDelimiter() { return getCommandSpec().parser().endOfOptionsDelimiter(); } /** Sets the end-of-options delimiter that signals that the remaining command line arguments should be treated as positional parameters. * @param delimiter the end-of-options delimiter; must not be {@code null}. The default is {@code "--"}. * @return this {@code CommandLine} object, to allow method chaining * @since 3.5 */ public CommandLine setEndOfOptionsDelimiter(String delimiter) { getCommandSpec().parser().endOfOptionsDelimiter(delimiter); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setEndOfOptionsDelimiter(delimiter); } return this; } /** Returns whether upper case and lower case should be ignored when matching subcommands. The default is {@code false}. * @return {@code true} if subcommands can be matched when they differ only in case from the {@code getCommandName()} value of a registered one, {@code false} otherwise. * For example, if true, for a subcommand with name {@code help}, inputs like {@code help}, {@code HeLp} and {@code HELP} are all recognized. * @since 4.3 */ public boolean isSubcommandsCaseInsensitive() { return getCommandSpec().subcommandsCaseInsensitive(); } /** Sets whether upper case and lower case should be ignored when matching subcommands. The default is {@code false}. * For example, when set to {@code true}, for a subcommand with name {@code help}, inputs like {@code help}, {@code HeLp} and {@code HELP} are all recognized. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param newValue the new setting * @return this {@code CommandLine} object, to allow method chaining * @since 4.3 */ public CommandLine setSubcommandsCaseInsensitive(boolean newValue) { getCommandSpec().subcommandsCaseInsensitive(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setSubcommandsCaseInsensitive(newValue); } return this; } /** Returns whether upper case and lower case should be ignored when matching option names. The default is {@code false}. * @return {@code true} if options can be matched when they differ only in case from the {@code names()} value of a registered one, {@code false} otherwise; * For example, if true, for an option with name {@code -h}, inputs like {@code -h}, {@code -H} are both recognized. * @since 4.3 */ public boolean isOptionsCaseInsensitive() { return getCommandSpec().optionsCaseInsensitive(); } /** Sets whether upper case and lower case should be ignored when matching option names. The default is {@code false}. * For example, when set to {@code true}, for an option with name {@code -h}, inputs like {@code -h}, {@code -H} are both recognized. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* Note that changing case sensitivity will also change the case sensitivity of {@linkplain Option#negatable() negatable} options: * any custom {@link INegatableOptionTransformer} that was previously installed will be replaced by the case-insensitive * version of the default transformer. To ensure your custom transformer is used, install it last, after changing case sensitivity. * @param newValue the new setting * @return this {@code CommandLine} object, to allow method chaining * @since 4.3 */ public CommandLine setOptionsCaseInsensitive(boolean newValue) { getCommandSpec().optionsCaseInsensitive(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setOptionsCaseInsensitive(newValue); } return this; } /** Returns whether abbreviation of subcommands should be allowed when matching subcommands. The default is {@code false}. * @return {@code true} if subcommands can be matched when they are abbreviations of the {@code getCommandName()} value of a registered one, {@code false} otherwise. * For example, if true, for a subcommand with name {@code helpCommand}, inputs like {@code h}, {@code h-c} and {@code hC} are all recognized. * @since 4.4 */ public boolean isAbbreviatedSubcommandsAllowed() { return getCommandSpec().parser().abbreviatedSubcommandsAllowed(); } /** Sets whether abbreviated subcommands should be matched. The default is {@code false}. * For example, when set to {@code true}, for a subcommand {@code helpCommand}, inputs like {@code h}, {@code h-c} and {@code hC} are all recognized. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param newValue the new setting * @return this {@code CommandLine} object, to allow method chaining * @since 4.4 */ public CommandLine setAbbreviatedSubcommandsAllowed(boolean newValue) { getCommandSpec().parser().abbreviatedSubcommandsAllowed(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setAbbreviatedSubcommandsAllowed(newValue); } return this; } /** Returns whether abbreviation of option names should be allowed when matching options. The default is {@code false}. * @return {@code true} if options can be matched when they are abbreviations of the {@code names()} value of a registered one, {@code false} otherwise. * For example, if true, for a subcommand with name {@code --helpMe}, inputs like {@code --h}, {@code --h-m} and {@code --hM} are all recognized. * @since 4.4 */ public boolean isAbbreviatedOptionsAllowed() { return getCommandSpec().parser().abbreviatedOptionsAllowed(); } /** Sets whether abbreviated option names should be matched. The default is {@code false}. * For example, when set to {@code true}, for an option with name {@code --helpMe}, inputs like {@code --h}, {@code --h-m} and {@code --hM} are all recognized. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param newValue the new setting * @return this {@code CommandLine} object, to allow method chaining * @since 4.4 */ public CommandLine setAbbreviatedOptionsAllowed(boolean newValue) { getCommandSpec().parser().abbreviatedOptionsAllowed(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setAbbreviatedOptionsAllowed(newValue); } return this; } /** Returns the default value provider for the command, or {@code null} if none has been set. * @return the default value provider for this command, or {@code null} * @since 3.6 * @see Command#defaultValueProvider() * @see CommandSpec#defaultValueProvider() * @see ArgSpec#defaultValueString() */ public IDefaultValueProvider getDefaultValueProvider() { return getCommandSpec().defaultValueProvider(); } /** Sets a default value provider for the command and sub-commands *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * sub-commands and nested sub-subcommands at the moment this method is called. Sub-commands added * later will have the default setting. To ensure a setting is applied to all * sub-commands, call the setter last, after adding sub-commands.

* @param newValue the default value provider to use * @return this {@code CommandLine} object, to allow method chaining * @since 3.6 */ public CommandLine setDefaultValueProvider(IDefaultValueProvider newValue) { getCommandSpec().defaultValueProvider(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setDefaultValueProvider(newValue); } return this; } /** Returns whether the parser interprets the first positional parameter as "end of options" so the remaining * arguments are all treated as positional parameters. The default is {@code false}. * @return {@code true} if all values following the first positional parameter should be treated as positional parameters, {@code false} otherwise * @since 2.3 */ public boolean isStopAtPositional() { return getCommandSpec().parser().stopAtPositional(); } /** Sets whether the parser interprets the first positional parameter as "end of options" so the remaining * arguments are all treated as positional parameters. The default is {@code false}. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param newValue {@code true} if all values following the first positional parameter should be treated as positional parameters, {@code false} otherwise * @return this {@code CommandLine} object, to allow method chaining * @since 2.3 */ public CommandLine setStopAtPositional(boolean newValue) { getCommandSpec().parser().stopAtPositional(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setStopAtPositional(newValue); } return this; } /** Returns whether the parser should stop interpreting options and positional parameters as soon as it encounters an * unmatched option. Unmatched options are arguments that look like an option but are not one of the known options, or * positional arguments for which there is no available slots (the command has no positional parameters or their size is limited). * The default is {@code false}. *

Setting this flag to {@code true} automatically sets the {@linkplain #isUnmatchedArgumentsAllowed() unmatchedArgumentsAllowed} flag to {@code true} also.

* @return {@code true} when an unmatched option should result in the remaining command line arguments to be added to the * {@linkplain #getUnmatchedArguments() unmatchedArguments list} * @since 2.3 */ public boolean isStopAtUnmatched() { return getCommandSpec().parser().stopAtUnmatched(); } /** Sets whether the parser should stop interpreting options and positional parameters as soon as it encounters an * unmatched option. Unmatched options are arguments that look like an option but are not one of the known options, or * positional arguments for which there is no available slots (the command has no positional parameters or their size is limited). * The default is {@code false}. *

Setting this flag to {@code true} automatically sets the {@linkplain #setUnmatchedArgumentsAllowed(boolean) unmatchedArgumentsAllowed} flag to {@code true} also.

*

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param newValue {@code true} when an unmatched option should result in the remaining command line arguments to be added to the * {@linkplain #getUnmatchedArguments() unmatchedArguments list} * @return this {@code CommandLine} object, to allow method chaining * @since 2.3 */ public CommandLine setStopAtUnmatched(boolean newValue) { getCommandSpec().parser().stopAtUnmatched(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setStopAtUnmatched(newValue); } if (newValue) { setUnmatchedArgumentsAllowed(true); } return this; } /** Returns whether options can have parameter values that match subcommand names or aliases, * or whether such values should be rejected with a missing parameter exception. * The default is {@code false}, so by default input like {@code -x=subcommand} is rejected if {@code -x} is an option that takes a String parameter, and {@code subcommand} is a subcommand of this command. * @return {@code true} when options can have parameter values that match subcommand names or aliases, {@code false} when such values should be rejected with a missing parameter exception * @since 4.7.6-SNAPSHOT * @see ParserSpec#allowSubcommandsAsOptionParameters() */ public boolean isAllowSubcommandsAsOptionParameters() { return getCommandSpec().parser().allowSubcommandsAsOptionParameters(); } /** Sets whether options can have parameter values that match subcommand names or aliases, or whether such values should be rejected with a missing parameter exception. * The default is {@code false}, so by default * input like {@code -x=subcommand} is rejected if {@code -x} is an option that takes a String parameter, and {@code subcommand} is a subcommand of this command. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param newValue the new setting. When {@code true}, options can have parameter values that match subcommand names or aliases, when {@code false}, such values are rejected with a missing parameter exception * @return this {@code CommandLine} object, to allow method chaining * @since 4.7.6-SNAPSHOT * @see ParserSpec#allowSubcommandsAsOptionParameters(boolean) */ public CommandLine setAllowSubcommandsAsOptionParameters(boolean newValue) { getCommandSpec().parser().allowSubcommandsAsOptionParameters(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setAllowSubcommandsAsOptionParameters(newValue); } return this; } /** Returns whether options can have parameter values that match the name of an option in this command, * or whether such values should be rejected with a missing parameter exception. * The default is {@code false}, so by default input like {@code -x=--some-option} is rejected if {@code -x} is an option that takes a String parameter, and {@code --some-option} is an option of this command. *

This method only considers actual options of this command, as opposed to {@link #isUnmatchedOptionsAllowedAsOptionParameters()}, which considers values that resemble options.

* @return {@code true} when options can have parameter values that match the name of an option in this command, {@code false} when such values should be rejected with a missing parameter exception * @since 4.7.6-SNAPSHOT * @see #isUnmatchedOptionsAllowedAsOptionParameters() * @see ParserSpec#allowOptionsAsOptionParameters() */ public boolean isAllowOptionsAsOptionParameters() { return getCommandSpec().parser().allowOptionsAsOptionParameters(); } /** Sets whether options can have parameter values that match the name of an option in this command, or whether such values should be rejected with a missing parameter exception. * The default is {@code false}, so by default * input like {@code -x=--some-option} is rejected if {@code -x} is an option that takes a String parameter, and {@code --some-option} is an option of this command. *

This method only considers actual options of this command, as opposed to {@link #setUnmatchedOptionsAllowedAsOptionParameters(boolean)}, which considers values that resemble options.

*

Use with caution! When set to {@code true}, any option in the command will consume the maximum number of arguments possible for its arity. * This means that an option with {@code arity = "*"} will consume all command line arguments following that option. * If this is not what you want, consider custom parameter processing.

*

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param newValue the new setting. When {@code true}, options can have parameter values that match the name of an option in this command, when {@code false}, such values are rejected with a missing parameter exception * @return this {@code CommandLine} object, to allow method chaining * @since 4.7.6-SNAPSHOT * @see #setUnmatchedOptionsAllowedAsOptionParameters(boolean) * @see ParserSpec#allowOptionsAsOptionParameters(boolean) */ public CommandLine setAllowOptionsAsOptionParameters(boolean newValue) { getCommandSpec().parser().allowOptionsAsOptionParameters(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setAllowOptionsAsOptionParameters(newValue); } return this; } /** Returns whether options can have parameter values that resemble an option, or whether such values should be rejected as unknown options. * The default is {@code true}, so by default input like {@code -x=-unknown} is accepted if {@code -x} is an option that takes a String parameter. *

This method only considers values that resemble options, as opposed to {@link #isAllowOptionsAsOptionParameters()}, which considers actual options of this command.

* @return {@code true} when options can have parameter values that resemble an option, {@code false} when such values should be rejected as unknown options * @since 4.4 * @see #isAllowOptionsAsOptionParameters() * @see ParserSpec#unmatchedOptionsAllowedAsOptionParameters() */ public boolean isUnmatchedOptionsAllowedAsOptionParameters() { return getCommandSpec().parser().unmatchedOptionsAllowedAsOptionParameters(); } /** Sets whether options can have parameter values that resemble an option, or whether such values should be rejected as unknown options. * The default is {@code true}, so by default * input like {@code -x=-unknown} is accepted if {@code -x} is an option that takes a String parameter. *

This method only considers values that resemble options, as opposed to {@link #setAllowOptionsAsOptionParameters(boolean)}, which considers actual options of this command.

*

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param newValue the new setting. When {@code true}, options can have parameter values that resemble an option, when {@code false}, such values are rejected as unknown options * @return this {@code CommandLine} object, to allow method chaining * @since 4.4 * @see #setAllowOptionsAsOptionParameters(boolean) * @see ParserSpec#unmatchedOptionsAllowedAsOptionParameters(boolean) */ public CommandLine setUnmatchedOptionsAllowedAsOptionParameters(boolean newValue) { getCommandSpec().parser().unmatchedOptionsAllowedAsOptionParameters(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setUnmatchedOptionsAllowedAsOptionParameters(newValue); } return this; } /** Returns whether arguments on the command line that resemble an option should be treated as positional parameters. * The default is {@code false} and the parser behaviour depends on {@link #isUnmatchedArgumentsAllowed()}. * @return {@code true} arguments on the command line that resemble an option should be treated as positional parameters, {@code false} otherwise * @see #getUnmatchedArguments() * @since 3.0 */ public boolean isUnmatchedOptionsArePositionalParams() { return getCommandSpec().parser().unmatchedOptionsArePositionalParams(); } /** Sets whether arguments on the command line that resemble an option should be treated as positional parameters. * The default is {@code false}. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param newValue the new setting. When {@code true}, arguments on the command line that resemble an option should be treated as positional parameters. * @return this {@code CommandLine} object, to allow method chaining * @since 3.0 * @see #getUnmatchedArguments() * @see #isUnmatchedArgumentsAllowed */ public CommandLine setUnmatchedOptionsArePositionalParams(boolean newValue) { getCommandSpec().parser().unmatchedOptionsArePositionalParams(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setUnmatchedOptionsArePositionalParams(newValue); } return this; } /** Returns whether the end user may specify arguments on the command line that are not matched to any option or parameter fields. * The default is {@code false} and a {@link UnmatchedArgumentException} is thrown if this happens. * When {@code true}, the last unmatched arguments are available via the {@link #getUnmatchedArguments()} method. * @return {@code true} if the end use may specify unmatched arguments on the command line, {@code false} otherwise * @see #getUnmatchedArguments() * @since 0.9.7 */ public boolean isUnmatchedArgumentsAllowed() { return getCommandSpec().parser().unmatchedArgumentsAllowed(); } /** Sets whether the end user may specify unmatched arguments on the command line without a {@link UnmatchedArgumentException} being thrown. * The default is {@code false}. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param newValue the new setting. When {@code true}, the last unmatched arguments are available via the {@link #getUnmatchedArguments()} method. * @return this {@code CommandLine} object, to allow method chaining * @since 0.9.7 * @see #getUnmatchedArguments() */ public CommandLine setUnmatchedArgumentsAllowed(boolean newValue) { getCommandSpec().parser().unmatchedArgumentsAllowed(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setUnmatchedArgumentsAllowed(newValue); } return this; } /** Returns the list of unmatched command line arguments, if any. * @return the list of unmatched command line arguments or an empty list * @see #isUnmatchedArgumentsAllowed() * @since 0.9.7 */ public List getUnmatchedArguments() { return interpreter.parseResultBuilder == null ? Collections.emptyList() : UnmatchedArgumentException.stripErrorMessage(interpreter.parseResultBuilder.unmatched); } /** * Defines some exit codes used by picocli as default return values from the {@link #execute(String...) execute} * and {@link #executeHelpRequest(ParseResult) executeHelpRequest} methods. *

Commands can override these defaults with annotations (e.g. {@code @Command(exitCodeOnInvalidInput = 64, exitCodeOnExecutionException = 70)} * or programmatically (e.g. {@link CommandSpec#exitCodeOnInvalidInput(int)}).

*

Additionally, there are several mechanisms for commands to return custom exit codes. * See the javadoc of the {@link #execute(String...) execute} method for details.

*

Standard Exit Codes

*

There are a few conventions, but there is no * standard. The specific set of codes returned is unique to the program that sets it. * Typically an exit code of zero indicates success, any non-zero exit code indicates failure. For reference, here are a few conventions:

* *

Valid Ranges

*

Note that *nix shells may restrict exit codes to the 0-255 range, DOS seems to allow larger numbers. * See this StackOverflow question.

* @since 4.0 */ public static final class ExitCode { /** Return value from the {@link #execute(String...) execute} and * {@link #executeHelpRequest(ParseResult) executeHelpRequest} methods signifying successful termination. *

The value of this constant is {@value}.

*/ public static final int OK = 0; /** Return value from the {@link #execute(String...) execute} method signifying internal software error: an exception occurred when invoking the Runnable, Callable or Method user object of a command.

The value of this constant is {@value}.

*/ public static final int SOFTWARE = 1; /** Return value from the {@link #execute(String...) execute} method signifying command line usage error: user input for the command was incorrect, e.g., the wrong number of arguments, a bad flag, a bad syntax in a parameter, or whatever.

The value of this constant is {@value}.

*/ public static final int USAGE = 2; private ExitCode() {} // don't instantiate } /** {@code @Command}-annotated classes can implement this interface to specify an exit code that will be returned * from the {@link #execute(String...) execute} method when the command is successfully invoked. * *

Example usage:

*
     * @Command
     * class MyCommand implements Runnable, IExitCodeGenerator {
     *     public void run() { System.out.println("Hello"); }
     *     public int getExitCode() { return 123; }
     * }
     * CommandLine cmd = new CommandLine(new MyCommand());
     * int exitCode = cmd.execute(args);
     * assert exitCode == 123;
     * System.exit(exitCode);
     * 
* @since 4.0 */ public interface IExitCodeGenerator { /** Returns the exit code that should be returned from the {@link #execute(String...) execute} method. * @return the exit code */ int getExitCode(); } /** Interface that provides the appropriate exit code that will be returned from the {@link #execute(String...) execute} * method for an exception that occurred during parsing or while invoking the command's Runnable, Callable, or Method. *

Example usage:

*
     * @Command
     * class FailingCommand implements Callable<Void> {
     *     public Void call() throws IOException {
     *         throw new IOException("error");
     *     }
     * }
     * IExitCodeExceptionMapper mapper = new IExitCodeExceptionMapper() {
     *     public int getExitCode(Throwable t) {
     *         if (t instanceof IOException && "error".equals(t.getMessage())) {
     *             return 123;
     *         }
     *         return 987;
     *     }
     * }
     *
     * CommandLine cmd = new CommandLine(new FailingCommand());
     * cmd.setExitCodeExceptionMapper(mapper);
     * int exitCode = cmd.execute(args);
     * assert exitCode == 123;
     * System.exit(exitCode);
     * 
* @see #setExitCodeExceptionMapper(IExitCodeExceptionMapper) * @since 4.0 */ public interface IExitCodeExceptionMapper { /** Returns the exit code that should be returned from the {@link #execute(String...) execute} method. * @param exception the exception that occurred during parsing or while invoking the command's Runnable, Callable, or Method. * @return the exit code */ int getExitCode(Throwable exception); } private static int mappedExitCode(Throwable t, IExitCodeExceptionMapper mapper, int defaultExitCode) { try { return (mapper != null) ? mapper.getExitCode(t) : defaultExitCode; } catch (Exception ex) { ex.printStackTrace(); return defaultExitCode; } } /** Returns the color scheme to use when printing help. * The default value is the {@linkplain picocli.CommandLine.Help#defaultColorScheme(CommandLine.Help.Ansi) default color scheme} with {@link Help.Ansi#AUTO Ansi.AUTO}. * @see #execute(String...) * @see #usage(PrintStream) * @see #usage(PrintWriter) * @see #getUsageMessage() * @see Help#defaultColorScheme(CommandLine.Help.Ansi) * @since 4.0 */ public Help.ColorScheme getColorScheme() { return colorScheme; } /** Sets the color scheme to use when printing help. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param colorScheme the new color scheme * @see #execute(String...) * @see #usage(PrintStream) * @see #usage(PrintWriter) * @see #getUsageMessage() * @since 4.0 */ public CommandLine setColorScheme(Help.ColorScheme colorScheme) { this.colorScheme = Assert.notNull(colorScheme, "colorScheme"); for (CommandLine sub : getSubcommands().values()) { sub.setColorScheme(colorScheme); } return this; } /** Returns the writer used when printing user-requested usage help or version help during command {@linkplain #execute(String...) execution}. * Defaults to a PrintWriter wrapper around {@code System.out} unless {@link #setOut(PrintWriter)} was called with a different writer. *

This method is used by {@link #execute(String...)}. Custom {@link IExecutionStrategy IExecutionStrategy} implementations should also use this writer. *

* By convention, when the user requests * help with a {@code --help} or similar option, the usage help message is printed to the standard output stream so that it can be easily searched and paged.

* @since 4.0 */ public PrintWriter getOut() { if (out == null) { setOut(newPrintWriter(System.out, getStdoutEncoding())); } return out; } /** Sets the writer to use when printing user-requested usage help or version help during command {@linkplain #execute(String...) execution}. *

This method is used by {@link #execute(String...)}. Custom {@link IExecutionStrategy IExecutionStrategy} implementations should also use this writer.

*

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param out the new PrintWriter to use * @return this CommandLine for method chaining * @since 4.0 */ public CommandLine setOut(PrintWriter out) { this.out = Assert.notNull(out, "out"); for (CommandLine sub : getSubcommands().values()) { sub.setOut(out); } return this; } /** Returns the writer to use when printing diagnostic (error) messages during command {@linkplain #execute(String...) execution}. * Defaults to a PrintWriter wrapper around {@code System.err}, unless {@link #setErr(PrintWriter)} was called with a different writer. *

This method is used by {@link #execute(String...)}. * {@link IParameterExceptionHandler IParameterExceptionHandler} and {@link IExecutionExceptionHandler IExecutionExceptionHandler} implementations * should use this writer to print error messages (which may include a usage help message) when an unexpected error occurs.

* @since 4.0 */ public PrintWriter getErr() { if (err == null) { setErr(newPrintWriter(System.err, getStderrEncoding())); } return err; } /** Sets the writer to use when printing diagnostic (error) messages during command {@linkplain #execute(String...) execution}. *

This method is used by {@link #execute(String...)}. * {@link IParameterExceptionHandler IParameterExceptionHandler} and {@link IExecutionExceptionHandler IExecutionExceptionHandler} implementations * should use this writer to print error messages (which may include a usage help message) when an unexpected error occurs.

*

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param err the new PrintWriter to use * @return this CommandLine for method chaining * @since 4.0 */ public CommandLine setErr(PrintWriter err) { this.err = Assert.notNull(err, "err"); for (CommandLine sub : getSubcommands().values()) { sub.setErr(err); } return this; } /** * Returns the mapper that was set by the application to map from exceptions to exit codes, for use by the {@link #execute(String...) execute} method. * @return the mapper that was {@linkplain #setExitCodeExceptionMapper(IExitCodeExceptionMapper) set}, or {@code null} if none was set * @since 4.0 */ public IExitCodeExceptionMapper getExitCodeExceptionMapper() { return exitCodeExceptionMapper; } /** Sets the mapper used by the {@link #execute(String...) execute} method to map exceptions to exit codes. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param exitCodeExceptionMapper the new value * @return this CommandLine for method chaining * @since 4.0 */ public CommandLine setExitCodeExceptionMapper(IExitCodeExceptionMapper exitCodeExceptionMapper) { this.exitCodeExceptionMapper = Assert.notNull(exitCodeExceptionMapper, "exitCodeExceptionMapper"); for (CommandLine sub : getSubcommands().values()) { sub.setExitCodeExceptionMapper(exitCodeExceptionMapper); } return this; } /** Returns the execution strategy used by the {@link #execute(String...) execute} method to invoke * the business logic on the user objects of this command and/or the user-specified subcommand(s). * The default value is {@link RunLast RunLast}. * @return the execution strategy to run the user-specified command * @since 4.0 */ public IExecutionStrategy getExecutionStrategy() { return executionStrategy; } /** Sets the execution strategy that the {@link #execute(String...) execute} method should use to invoke * the business logic on the user objects of this command and/or the user-specified subcommand(s). *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param executionStrategy the new execution strategy to run the user-specified command * @return this CommandLine for method chaining * @since 4.0 */ public CommandLine setExecutionStrategy(IExecutionStrategy executionStrategy) { this.executionStrategy = Assert.notNull(executionStrategy, "executionStrategy"); for (CommandLine sub : getSubcommands().values()) { sub.setExecutionStrategy(executionStrategy); } return this; } /** * Returns the handler for dealing with invalid user input when the command is {@linkplain #execute(String...) executed}. *

The default implementation prints an error message describing the problem, followed by either {@linkplain UnmatchedArgumentException#printSuggestions(PrintWriter) suggested alternatives} * for mistyped options, or the full {@linkplain #usage(PrintWriter, Help.ColorScheme) usage} help message of the {@linkplain ParameterException#getCommandLine() problematic command}; * it then delegates to the {@linkplain #getExitCodeExceptionMapper() exit code exception mapper} for an exit code, with * {@link CommandSpec#exitCodeOnInvalidInput() exitCodeOnInvalidInput} as the default exit code.

*

* Alternatively, you can install a "short error message handler" like this: *

*
     * static class ShortErrorMessageHandler implements IParameterExceptionHandler {
     *     public int handleParseException(ParameterException ex, String[] args) {
     *         CommandLine cmd = ex.getCommandLine();
     *         PrintWriter writer = cmd.getErr();
     *
     *         writer.println(ex.getMessage());
     *         UnmatchedArgumentException.printSuggestions(ex, writer);
     *         writer.print(cmd.getHelp().fullSynopsis());
     *
     *         CommandSpec spec = cmd.getCommandSpec();
     *         writer.printf("Try '%s --help' for more information.%n", spec.qualifiedName());
     *
     *         return cmd.getExitCodeExceptionMapper() != null
     *                     ? cmd.getExitCodeExceptionMapper().getExitCode(ex)
     *                     : spec.exitCodeOnInvalidInput();
     *     }
     * }
     * 
*

Install this error handler like this:

*
     * new CommandLine(new MyApp())
     *     .setParameterExceptionHandler(new ShortErrorMessageHandler())
     *     .execute(args);
     * 
* @return the handler for dealing with invalid user input * @since 4.0 */ public IParameterExceptionHandler getParameterExceptionHandler() { return parameterExceptionHandler; } /** * Sets the handler for dealing with invalid user input when the command is {@linkplain #execute(String...) executed}. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param parameterExceptionHandler the new handler for dealing with invalid user input * @return this CommandLine for method chaining * @see #getParameterExceptionHandler() an example short exception handler * @since 4.0 */ public CommandLine setParameterExceptionHandler(IParameterExceptionHandler parameterExceptionHandler) { this.parameterExceptionHandler = Assert.notNull(parameterExceptionHandler, "parameterExceptionHandler"); for (CommandLine sub : getSubcommands().values()) { sub.setParameterExceptionHandler(parameterExceptionHandler); } return this; } /** Returns the handler for dealing with exceptions that occurred in the {@code Callable}, {@code Runnable} or {@code Method} * user object of a command when the command was {@linkplain #execute(String...) executed}. *

The default implementation rethrows the specified exception.

* @return the handler for dealing with exceptions that occurred in the business logic when the {@link #execute(String...) execute} method was invoked. * @since 4.0 */ public IExecutionExceptionHandler getExecutionExceptionHandler() { return executionExceptionHandler; } /** * Sets a custom handler for dealing with exceptions that occurred in the {@code Callable}, {@code Runnable} or {@code Method} * user object of a command when the command was executed via the {@linkplain #execute(String...) execute} method. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param executionExceptionHandler the handler for dealing with exceptions that occurred in the business logic when the {@link #execute(String...) execute} method was invoked. * @return this CommandLine for method chaining * @since 4.0 */ public CommandLine setExecutionExceptionHandler(IExecutionExceptionHandler executionExceptionHandler) { this.executionExceptionHandler = Assert.notNull(executionExceptionHandler, "executionExceptionHandler"); for (CommandLine sub : getSubcommands().values()) { sub.setExecutionExceptionHandler(executionExceptionHandler); } return this; } /** *

* Convenience method that initializes the specified annotated object from the specified command line arguments. *

* This is equivalent to *

     * new CommandLine(command).parseArgs(args);
     * return command;
     * 
*

All this method does is parse the arguments and populate the annotated fields and methods. * The caller is responsible for catching any exceptions, handling requests for usage help * or version information, and invoking the business logic. * Applications may be interested in using the {@link #execute(String...)} method instead.

* * @param command the object to initialize. This object contains fields annotated with * {@code @Option} or {@code @Parameters}. * @param args the command line arguments to parse * @param the type of the annotated object * @return the specified annotated object * @throws InitializationException if the specified command object does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @throws ParameterException if the specified command line arguments are invalid * @see #execute(String...) * @since 0.9.7 */ public static T populateCommand(T command, String... args) { CommandLine cli = toCommandLine(command, new DefaultFactory()); cli.parse(args); return command; } /** *

* Convenience method that derives the command specification from the specified interface class, and returns an * instance of the specified interface. The interface is expected to have annotated getter methods. Picocli will * instantiate the interface and the getter methods will return the option and positional parameter values matched on the command line. *

* This is equivalent to *

     * CommandLine cli = new CommandLine(spec);
     * cli.parse(args);
     * return cli.getCommand();
     * 
*

All this method does is parse the arguments and return an instance whose annotated methods return the specified values. * The caller is responsible for catching any exceptions, handling requests for usage help * or version information, and invoking the business logic. * Applications may be interested in using the {@link #execute(String...)} method instead.

* * @param spec the interface that defines the command specification. This object contains getter methods annotated with * {@code @Option} or {@code @Parameters}. * @param args the command line arguments to parse * @param the type of the annotated object * @return an instance of the specified annotated interface * @throws InitializationException if the specified command object does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @throws ParameterException if the specified command line arguments are invalid * @see #execute(String...) * @since 3.1 */ public static T populateSpec(Class spec, String... args) { CommandLine cli = toCommandLine(spec, new DefaultFactory()); cli.parse(args); return cli.getCommand(); } /** Expands any {@linkplain CommandLine#isExpandAtFiles() @-files} in the specified command line arguments, then * parses the arguments and returns a list of {@code CommandLine} objects representing the * top-level command and any subcommands (if any) that were recognized and initialized during the parsing process. *

* If parsing succeeds, the first element in the returned list is always {@code this CommandLine} object. The * returned list may contain more elements if subcommands were {@linkplain #addSubcommand(String, Object) registered} * and these subcommands were initialized by matching command line arguments. If parsing fails, a * {@link ParameterException} is thrown. *

*

All this method does is parse the arguments and populate the annotated fields and methods. * The caller is responsible for catching any exceptions, handling requests for usage help * or version information, and invoking the business logic. * Applications may be interested in using the {@link #execute(String...)} method instead.

* * @param args the command line arguments to parse * @return a list with the top-level command and any subcommands initialized by this method * @throws ParameterException if the specified command line arguments are invalid; use * {@link ParameterException#getCommandLine()} to get the command or subcommand whose user input was invalid * @deprecated use {@link #parseArgs(String...)} instead */ @Deprecated public List parse(String... args) { return interpreter.parse(args); } /** Expands any {@linkplain CommandLine#isExpandAtFiles() @-files} in the specified command line arguments, then * parses the arguments and returns a {@code ParseResult} with the options, positional * parameters, and subcommands (if any) that were recognized and initialized during the parsing process. *

If parsing fails, a {@link ParameterException} is thrown.

*

All this method does is parse the arguments and populate the annotated fields and methods. * The caller is responsible for catching any exceptions, handling requests for usage help * or version information, and invoking the business logic. * Applications may be interested in using the {@link #execute(String...)} method instead.

* * @param args the command line arguments to parse * @return a list with the top-level command and any subcommands initialized by this method * @throws ParameterException if the specified command line arguments are invalid; use * {@link ParameterException#getCommandLine()} to get the command or subcommand whose user input was invalid * @see #execute(String...) */ public ParseResult parseArgs(String... args) { interpreter.parse(args); return getParseResult(); } public ParseResult getParseResult() { return interpreter.parseResultBuilder == null ? null : interpreter.parseResultBuilder.build(); } /** Returns the result of calling the user object {@code Callable} or invoking the user object {@code Method} * after parsing the user input, or {@code null} if this command has not been {@linkplain #execute(String...) executed} * or if this {@code CommandLine} is for a subcommand that was not specified by the end user on the command line. *

Implementation note:

*

It is the responsibility of the {@link IExecutionStrategy IExecutionStrategy} to set this value.

* @param type of the result value * @return the result of the user object {@code Callable} or {@code Method} (may be {@code null}), or {@code null} if this (sub)command was not executed * @since 4.0 */ @SuppressWarnings("unchecked") public T getExecutionResult() { return (T) executionResult; } /** Sets the result of calling the business logic on the command's user object. * @param result the business logic result, may be {@code null} * @see #execute(String...) * @see IExecutionStrategy * @since 4.0 */ public void setExecutionResult(Object result) { executionResult = result; } /** Clears the {@linkplain #getExecutionResult() execution result} of a previous invocation from this {@code CommandLine} and all subcommands. * @since 4.0 */ public void clearExecutionResults() { executionResult = null; for (CommandLine sub : getSubcommands().values()) { sub.clearExecutionResults(); } } /** * Represents a function that can process a List of {@code CommandLine} objects resulting from successfully * {@linkplain #parse(String...) parsing} the command line arguments. This is a * functional interface * whose functional method is {@link #handleParseResult(List, PrintStream, CommandLine.Help.Ansi)}. *

* Implementations of this functions can be passed to the {@link #parseWithHandlers(IParseResultHandler, PrintStream, Help.Ansi, IExceptionHandler, String...) CommandLine::parseWithHandler} * methods to take some next step after the command line was successfully parsed. *

* @see RunFirst * @see RunLast * @see RunAll * @deprecated Use {@link IExecutionStrategy} instead. * @since 2.0 */ @Deprecated public interface IParseResultHandler { /** Processes a List of {@code CommandLine} objects resulting from successfully * {@linkplain #parse(String...) parsing} the command line arguments and optionally returns a list of results. * @param parsedCommands the {@code CommandLine} objects that resulted from successfully parsing the command line arguments * @param out the {@code PrintStream} to print help to if requested * @param ansi for printing help messages using ANSI styles and colors * @return a list of results, or an empty list if there are no results * @throws ParameterException if a help command was invoked for an unknown subcommand. Any {@code ParameterExceptions} * thrown from this method are treated as if this exception was thrown during parsing and passed to the {@link IExceptionHandler} * @throws ExecutionException if a problem occurred while processing the parse results; use * {@link ExecutionException#getCommandLine()} to get the command or subcommand where processing failed */ List handleParseResult(List parsedCommands, PrintStream out, Help.Ansi ansi) throws ExecutionException; } /** * Represents a function that can process the {@code ParseResult} object resulting from successfully * {@linkplain #parseArgs(String...) parsing} the command line arguments. This is a * functional interface * whose functional method is {@link IParseResultHandler2#handleParseResult(CommandLine.ParseResult)}. *

* Implementations of this function can be passed to the {@link #parseWithHandlers(IParseResultHandler2, IExceptionHandler2, String...) CommandLine::parseWithHandlers} * methods to take some next step after the command line was successfully parsed. *

* This interface replaces the {@link IParseResultHandler} interface; it takes the parse result as a {@code ParseResult} * object instead of a List of {@code CommandLine} objects, and it has the freedom to select the {@link Help.Ansi} style * to use and what {@code PrintStreams} to print to. *

* @param the return type of this handler * @see RunFirst * @see RunLast * @see RunAll * @deprecated use {@link IExecutionStrategy} instead, see {@link #execute(String...)} * @since 3.0 */ @Deprecated public interface IParseResultHandler2 { /** Processes the {@code ParseResult} object resulting from successfully * {@linkplain CommandLine#parseArgs(String...) parsing} the command line arguments and returns a return value. * @param parseResult the {@code ParseResult} that resulted from successfully parsing the command line arguments * @throws ParameterException if a help command was invoked for an unknown subcommand. Any {@code ParameterExceptions} * thrown from this method are treated as if this exception was thrown during parsing and passed to the {@link IExceptionHandler2} * @throws ExecutionException if a problem occurred while processing the parse results; use * {@link ExecutionException#getCommandLine()} to get the command or subcommand where processing failed */ R handleParseResult(ParseResult parseResult) throws ExecutionException; } /** * Implementations are responsible for "executing" the user input and returning an exit code. * The {@link #execute(String...)} method delegates to a {@linkplain #setExecutionStrategy(IExecutionStrategy) configured} execution strategy. *

Implementation Requirements:

*

Implementers responsibilities are:

*
    *
  • From the {@code ParseResult}, select which {@code CommandSpec} should be executed. This is especially important for commands that have subcommands.
  • *
  • "Execute" the selected {@code CommandSpec}. Often this means invoking a method on the spec's {@linkplain CommandSpec#userObject() user object}.
  • *
  • Call {@link CommandLine#setExecutionResult(Object) setExecutionResult} to make the return value of that method invocation available to the application
  • *
  • Return an exit code. Common sources of exit values are the invoked method's return value, or the user object if it implements {@link IExitCodeGenerator}.
  • *
*

Implementors that need to print messages to the console should use the {@linkplain #getOut() output} and {@linkplain #getErr() error} PrintWriters, * and the {@linkplain #getColorScheme() color scheme} from the CommandLine object obtained from ParseResult's CommandSpec.

*

API Note:

*

This interface supersedes {@link IParseResultHandler2}.

* @since 4.0 */ public interface IExecutionStrategy { /** * "Executes" the user input and returns an exit code. * Execution often means invoking a method on the selected CommandSpec's {@linkplain CommandSpec#userObject() user object}, * and making the return value of that invocation available via {@link CommandLine#setExecutionResult(Object) setExecutionResult}. * @param parseResult the parse result from which to select one or more {@code CommandSpec} instances to execute. * @return an exit code * @throws ParameterException if the invoked method on the CommandSpec's user object threw a ParameterException to signify invalid user input. * @throws ExecutionException if any problem occurred while executing the command. Any exceptions (other than ParameterException) should be wrapped in a ExecutionException and not thrown as is. */ int execute(ParseResult parseResult) throws ExecutionException, ParameterException; } /** * Represents a function that can handle a {@code ParameterException} that occurred while * {@linkplain #parse(String...) parsing} the command line arguments. This is a * functional interface * whose functional method is {@link #handleException(CommandLine.ParameterException, PrintStream, CommandLine.Help.Ansi, String...)}. *

* Implementations of this function can be passed to the {@link #parseWithHandlers(IParseResultHandler, PrintStream, Help.Ansi, IExceptionHandler, String...) CommandLine::parseWithHandlers} * methods to handle situations when the command line could not be parsed. *

* @deprecated see {@link #execute(String...)}, {@link IParameterExceptionHandler} and {@link IExecutionExceptionHandler} * @since 2.0 */ @Deprecated public interface IExceptionHandler { /** Handles a {@code ParameterException} that occurred while {@linkplain #parse(String...) parsing} the command * line arguments and optionally returns a list of results. * @param ex the ParameterException describing the problem that occurred while parsing the command line arguments, * and the CommandLine representing the command or subcommand whose input was invalid * @param out the {@code PrintStream} to print help to if requested * @param ansi for printing help messages using ANSI styles and colors * @param args the command line arguments that could not be parsed * @return a list of results, or an empty list if there are no results */ List handleException(ParameterException ex, PrintStream out, Help.Ansi ansi, String... args); } /** * Classes implementing this interface know how to handle {@code ParameterExceptions} (usually from invalid user input) * and {@code ExecutionExceptions} that occurred while executing the {@code Runnable} or {@code Callable} command. *

* Implementations of this interface can be passed to the * {@link #parseWithHandlers(IParseResultHandler2, IExceptionHandler2, String...) CommandLine::parseWithHandlers} method. *

* This interface replaces the {@link IParseResultHandler} interface. *

* @param the return type of this handler * @see DefaultExceptionHandler * @deprecated see {@link #execute(String...)}, {@link IParameterExceptionHandler} and {@link IExecutionExceptionHandler} * @since 3.0 */ @Deprecated public interface IExceptionHandler2 { /** Handles a {@code ParameterException} that occurred while {@linkplain #parseArgs(String...) parsing} the command * line arguments and optionally returns a list of results. * @param ex the ParameterException describing the problem that occurred while parsing the command line arguments, * and the CommandLine representing the command or subcommand whose input was invalid * @param args the command line arguments that could not be parsed * @return an object resulting from handling the exception */ R handleParseException(ParameterException ex, String[] args); /** Handles a {@code ExecutionException} that occurred while executing the {@code Runnable} or * {@code Callable} command and optionally returns a list of results. * @param ex the ExecutionException describing the problem that occurred while executing the {@code Runnable} or * {@code Callable} command, and the CommandLine representing the command or subcommand that was being executed * @param parseResult the result of parsing the command line arguments * @return an object resulting from handling the exception */ R handleExecutionException(ExecutionException ex, ParseResult parseResult); } /** Classes implementing this interface know how to handle {@code ParameterExceptions} (usually from invalid user input). *

Implementation Requirements:

*

Implementors that need to print messages to the console should use the {@linkplain #getOut() output} and {@linkplain #getErr() error} PrintWriters, * and the {@linkplain #getColorScheme() color scheme} from the CommandLine object obtained from the exception.

*

Implementation Note:

*

See {@link #getParameterExceptionHandler()} for a description of the default handler.

*

API Note:

*

This interface supersedes {@link IExceptionHandler2}.

* @see CommandLine#setParameterExceptionHandler(IParameterExceptionHandler) * @since 4.0 */ public interface IParameterExceptionHandler { /** Handles a {@code ParameterException} that occurred while {@linkplain #parseArgs(String...) parsing} the command * line arguments and returns an exit code suitable for returning from {@link #execute(String...)}. * @param ex the ParameterException describing the problem that occurred while parsing the command line arguments, * and the CommandLine representing the command or subcommand whose input was invalid * @param args the command line arguments that could not be parsed * @return an exit code */ int handleParseException(ParameterException ex, String[] args) throws Exception; } /** * Classes implementing this interface know how to handle Exceptions that occurred while executing the {@code Runnable}, {@code Callable} or {@code Method} user object of the command. *

Implementation Requirements:

*

Implementors that need to print messages to the console should use the {@linkplain #getOut() output} and {@linkplain #getErr() error} PrintWriters, * and the {@linkplain #getColorScheme() color scheme} from the CommandLine object obtained from the exception.

*

API Note:

*

This interface supersedes {@link IExceptionHandler2}.

*

Example usage:

*
     * IExecutionExceptionHandler errorHandler = new IExecutionExceptionHandler() {
     *     public int handleExecutionException(Exception ex,
     *                                         CommandLine commandLine,
     *                                         ParseResult parseResult) {
     *         //ex.printStackTrace(); // no stack trace
     *         commandLine.getErr().println(ex.getMessage());
     *         commandLine.usage(commandLine.getErr());
     *         return commandLine.getCommandSpec().exitCodeOnExecutionException();
     *     }
     * };
     * int exitCode = new CommandLine(new App())
     *         .setExecutionExceptionHandler(errorHandler)
     *         .execute(args);
     * 
* @see CommandLine#setExecutionExceptionHandler(IExecutionExceptionHandler) * @since 4.0 */ public interface IExecutionExceptionHandler { /** Handles an {@code Exception} that occurred while executing the {@code Runnable} or * {@code Callable} command and returns an exit code suitable for returning from {@link #execute(String...)}. * @param ex the Exception thrown by the {@code Runnable}, {@code Callable} or {@code Method} user object of the command * @param commandLine the CommandLine representing the command or subcommand where the exception occurred * @param parseResult the result of parsing the command line arguments * @return an exit code */ int handleExecutionException(Exception ex, CommandLine commandLine, ParseResult parseResult) throws Exception; } /** Abstract superclass for {@link IParseResultHandler2} and {@link IExceptionHandler2} implementations. *

Note that {@code AbstractHandler} is a generic type. This, along with the abstract {@code self} method, * allows method chaining to work properly in subclasses, without the need for casts. An example subclass can look like this:

*
{@code
     * class MyResultHandler extends AbstractHandler implements IParseResultHandler2 {
     *
     *     public MyReturnType handleParseResult(ParseResult parseResult) { ... }
     *
     *     protected MyResultHandler self() { return this; }
     * }
     * }
* @param the return type of this handler * @param The type of the handler subclass; for fluent API method chaining * @deprecated see {@link #execute(String...)} * @since 3.0 */ @Deprecated public static abstract class AbstractHandler> { private Help.ColorScheme colorScheme = Help.defaultColorScheme(Help.Ansi.AUTO); private Integer exitCode; private PrintStream out = System.out; private PrintStream err = System.err; /** Returns the stream to print command output to. Defaults to {@code System.out}, unless {@link #useOut(PrintStream)} * was called with a different stream. *

{@code IParseResultHandler2} implementations should use this stream. * By convention, when the user requests * help with a {@code --help} or similar option, the usage help message is printed to the standard output stream so that it can be easily searched and paged.

*/ public PrintStream out() { return out; } /** Returns the stream to print diagnostic messages to. Defaults to {@code System.err}, unless {@link #useErr(PrintStream)} * was called with a different stream.

{@code IExceptionHandler2} implementations should use this stream to print error * messages (which may include a usage help message) when an unexpected error occurs.

*/ public PrintStream err() { return err; } /** Returns the ANSI style to use. Defaults to {@code Help.Ansi.AUTO}, unless {@link #useAnsi(CommandLine.Help.Ansi)} was called with a different setting. * @deprecated use {@link #colorScheme()} instead */ @Deprecated public Help.Ansi ansi() { return colorScheme.ansi(); } /** Returns the ColorScheme to use. Defaults to {@code Help#defaultColorScheme(Help.Ansi.AUTO)}. * @since 4.0*/ public Help.ColorScheme colorScheme() { return colorScheme; } /** Returns the exit code to use as the termination status, or {@code null} (the default) if the handler should * not call {@link System#exit(int)} after processing completes. * @see #andExit(int) */ public Integer exitCode() { return exitCode; } /** Returns {@code true} if an exit code was set with {@link #andExit(int)}, or {@code false} (the default) if * the handler should not call {@link System#exit(int)} after processing completes. */ public boolean hasExitCode() { return exitCode != null; } /** Convenience method for subclasses that returns the specified result object if no exit code was set, * or otherwise, if an exit code {@linkplain #andExit(int) was set}, calls {@code System.exit} with the configured * exit code to terminate the currently running Java virtual machine. */ protected R returnResultOrExit(R result) { if (hasExitCode()) { exit(exitCode()); } return result; } /** Convenience method for subclasses that throws the specified ExecutionException if no exit code was set, * or otherwise, if an exit code {@linkplain #andExit(int) was set}, prints the stacktrace of the specified exception * to the diagnostic error stream and calls {@code System.exit} with the configured * exit code to terminate the currently running Java virtual machine. */ protected R throwOrExit(ExecutionException ex) { if (hasExitCode()) { ex.printStackTrace(this.err()); exit(exitCode()); return null; } throw ex; } /** Calls {@code System.exit(int)} with the specified exit code. */ protected void exit(int exitCode) { System.exit(exitCode); } /** Returns {@code this} to allow method chaining when calling the setters for a fluent API. */ protected abstract T self(); /** Sets the stream to print command output to. * @deprecated use {@link CommandLine#setOut(PrintWriter)} and {@link CommandLine#execute(String...)} instead */ @Deprecated public T useOut(PrintStream out) { this.out = Assert.notNull(out, "out"); return self(); } /** Sets the stream to print diagnostic messages to. * @deprecated use {@link CommandLine#setErr(PrintWriter)} and {@link CommandLine#execute(String...)} instead */ @Deprecated public T useErr(PrintStream err) { this.err = Assert.notNull(err, "err"); return self(); } /** Sets the ANSI style to use and resets the color scheme to the default. * @deprecated use {@link CommandLine#setColorScheme(Help.ColorScheme)} and {@link CommandLine#execute(String...)} instead * @see #ansi() */ @Deprecated public T useAnsi(Help.Ansi ansi) { this.colorScheme = Help.defaultColorScheme(Assert.notNull(ansi, "ansi")); return self(); } /** Indicates that the handler should call {@link System#exit(int)} after processing completes and sets the exit code to use as the termination status. * @deprecated use {@link CommandLine#execute(String...)} instead, and call {@code System.exit()} in the application. */ @Deprecated public T andExit(int exitCode) { this.exitCode = exitCode; return self(); } } /** * Default exception handler that handles invalid user input by printing the exception message, followed by the usage * message for the command or subcommand whose input was invalid. *

{@code ParameterExceptions} (invalid user input) is handled like this:

*
     *     err().println(paramException.getMessage());
     *     paramException.getCommandLine().usage(err(), ansi());
     *     if (hasExitCode()) System.exit(exitCode()); else return returnValue;
     * 
*

{@code ExecutionExceptions} that occurred while executing the {@code Runnable} or {@code Callable} command are simply rethrown and not handled.

* @deprecated see {@link #execute(String...)}, {@link #getParameterExceptionHandler()} and {@link #getExecutionExceptionHandler()} * @since 2.0 */ @Deprecated public static class DefaultExceptionHandler extends AbstractHandler> implements IExceptionHandler, IExceptionHandler2 { public List handleException(ParameterException ex, PrintStream out, Help.Ansi ansi, String... args) { internalHandleParseException(ex, newPrintWriter(out, getStdoutEncoding()), Help.defaultColorScheme(ansi)); return Collections.emptyList(); } /** Prints the message of the specified exception, followed by the usage message for the command or subcommand * whose input was invalid, to the stream returned by {@link #err()}. * @param ex the ParameterException describing the problem that occurred while parsing the command line arguments, * and the CommandLine representing the command or subcommand whose input was invalid * @param args the command line arguments that could not be parsed * @return the empty list * @since 3.0 */ public R handleParseException(ParameterException ex, String[] args) { internalHandleParseException(ex, newPrintWriter(err(), getStderrEncoding()), colorScheme()); return returnResultOrExit(null); } static void internalHandleParseException(ParameterException ex, PrintWriter writer, Help.ColorScheme colorScheme) { writer.println(colorScheme.errorText(ex.getMessage())); if (!UnmatchedArgumentException.printSuggestions(ex, writer)) { ex.getCommandLine().usage(writer, colorScheme); } Tracer tracer = CommandLine.tracer(); if (tracer.isDebug()) { // #956 show error details if DEBUG is enabled ex.printStackTrace(tracer.stream); } } /** This implementation always simply rethrows the specified exception. * @param ex the ExecutionException describing the problem that occurred while executing the {@code Runnable} or {@code Callable} command * @param parseResult the result of parsing the command line arguments * @return nothing: this method always rethrows the specified exception * @throws ExecutionException always rethrows the specified exception * @since 3.0 */ public R handleExecutionException(ExecutionException ex, ParseResult parseResult) { return throwOrExit(ex); } @Override protected DefaultExceptionHandler self() { return this; } } /** Convenience method that returns {@code new DefaultExceptionHandler>()}. */ public static DefaultExceptionHandler> defaultExceptionHandler() { return new DefaultExceptionHandler>(); } /** @deprecated use {@link #printHelpIfRequested(ParseResult)} instead * @since 2.0 */ @Deprecated public static boolean printHelpIfRequested(List parsedCommands, PrintStream out, Help.Ansi ansi) { return printHelpIfRequested(parsedCommands, out, out, ansi); } /** * Delegates to {@link #executeHelpRequest(ParseResult)}. * @param parseResult contains the {@code CommandLine} objects found during parsing; check these to see if help was requested * @return {@code true} if help was printed, {@code false} otherwise * @since 3.0 */ public static boolean printHelpIfRequested(ParseResult parseResult) { return executeHelpRequest(parseResult) != null; } /** * Delegates to the implementation of {@link #executeHelpRequest(ParseResult)}. * @deprecated use {@link #executeHelpRequest(ParseResult)} instead * @param parsedCommands the list of {@code CommandLine} objects to check if help was requested * @param out the {@code PrintStream} to print help to if requested * @param err the error string to print diagnostic messages to, in addition to the output from the exception handler * @param ansi for printing help messages using ANSI styles and colors * @return {@code true} if help was printed, {@code false} otherwise * @since 3.0 */ @Deprecated public static boolean printHelpIfRequested(List parsedCommands, PrintStream out, PrintStream err, Help.Ansi ansi) { return printHelpIfRequested(parsedCommands, out, err, Help.defaultColorScheme(ansi)); } /** * Delegates to the implementation of {@link #executeHelpRequest(ParseResult)}. * @deprecated use {@link #executeHelpRequest(ParseResult)} instead * @param parsedCommands the list of {@code CommandLine} objects to check if help was requested * @param out the {@code PrintStream} to print help to if requested * @param err the error string to print diagnostic messages to, in addition to the output from the exception handler * @param colorScheme for printing help messages using ANSI styles and colors * @return {@code true} if help was printed, {@code false} otherwise * @since 3.6 */ @Deprecated public static boolean printHelpIfRequested(List parsedCommands, PrintStream out, PrintStream err, Help.ColorScheme colorScheme) { // for backwards compatibility for (CommandLine cmd : parsedCommands) { cmd.setOut(newPrintWriter(out, getStdoutEncoding())).setErr(newPrintWriter(err, getStderrEncoding())).setColorScheme(colorScheme); } return executeHelpRequest(parsedCommands) != null; } /** * Helper method that may be useful when processing the {@code ParseResult} that results from successfully * {@linkplain #parseArgs(String...) parsing} command line arguments. This method prints out * {@linkplain #usage(PrintWriter, Help.ColorScheme) usage help} to the {@linkplain CommandLine#getOut() configured output writer} * if {@linkplain #isUsageHelpRequested() requested} or {@linkplain #printVersionHelp(PrintWriter, Help.Ansi, Object...) version help} * to the {@linkplain CommandLine#getOut() configured output writer} if {@linkplain #isVersionHelpRequested() requested} * and returns {@link CommandSpec#exitCodeOnUsageHelp()} or {@link CommandSpec#exitCodeOnVersionHelp()}, respectively. * If the command is a {@link Command#helpCommand()} and {@code runnable} or {@code callable}, * that command is executed and this method returns {@link CommandSpec#exitCodeOnUsageHelp()}. * Otherwise, if none of the specified {@code CommandLine} objects have help requested, * this method returns {@code null}.

* Note that this method only looks at the {@link Option#usageHelp() usageHelp} and * {@link Option#versionHelp() versionHelp} attributes. The {@link Option#help() help} attribute is ignored. *

Implementation note:

* When an error occurs while processing the help request, it is recommended custom Help commands throw a * {@link ParameterException} with a reference to the parent command. This will print the error message and the * usage for the parent command, and will use the exit code of the exception handler if one was set. *

* @param parseResult contains the {@code CommandLine} objects found during parsing; check these to see if help was requested * @return {@link CommandSpec#exitCodeOnUsageHelp()} if usage help was requested, * {@link CommandSpec#exitCodeOnVersionHelp()} if version help was requested, and {@code null} otherwise * @see IHelpCommandInitializable2 * @since 4.0 */ public static Integer executeHelpRequest(ParseResult parseResult) { return executeHelpRequest(parseResult.asCommandLineList()); } /** @since 4.0 */ static Integer executeHelpRequest(List parsedCommands) { Tracer t = CommandLine.tracer(); for (CommandLine parsed : parsedCommands) { Help.ColorScheme colorScheme = parsed.getColorScheme(); PrintWriter out = parsed.getOut(); if (parsed.isUsageHelpRequested()) { t.debug("Printing usage help for '%s' as requested.", parsed.commandSpec.qualifiedName()); parsed.usage(out, colorScheme); return parsed.getCommandSpec().exitCodeOnUsageHelp(); } else if (parsed.isVersionHelpRequested()) { t.debug("Printing version info for '%s' as requested.", parsed.commandSpec.qualifiedName()); parsed.printVersionHelp(out, colorScheme.ansi); return parsed.getCommandSpec().exitCodeOnVersionHelp(); } else if (parsed.getCommandSpec().helpCommand()) { String fullName = parsed.commandSpec.qualifiedName(); PrintWriter err = parsed.getErr(); if (((Object) parsed.getCommand()) instanceof IHelpCommandInitializable2) { t.debug("Initializing helpCommand '%s' (IHelpCommandInitializable2::init)...", fullName); ((IHelpCommandInitializable2) parsed.getCommand()).init(parsed, colorScheme, out, err); } else if (((Object) parsed.getCommand()) instanceof IHelpCommandInitializable) { t.debug("Initializing helpCommand '%s' (IHelpCommandInitializable::init)...", fullName); ((IHelpCommandInitializable) parsed.getCommand()).init(parsed, colorScheme.ansi, System.out, System.err); } else { t.debug("helpCommand '%s' does not implement IHelpCommandInitializable2 or IHelpCommandInitializable...", fullName); } t.debug("Executing helpCommand '%s'...", fullName); executeUserObject(parsed, new ArrayList()); return parsed.getCommandSpec().exitCodeOnUsageHelp(); } } t.debug("Help was not requested. Continuing to process ParseResult..."); return null; } private static List executeUserObject(CommandLine parsed, List executionResultList) { Tracer tracer = CommandLine.tracer(); Object command = parsed.getCommand(); if (command instanceof Runnable) { try { tracer.debug("Invoking Runnable::run on user object %s@%s...", command.getClass().getName(), Integer.toHexString(command.hashCode())); ((Runnable) command).run(); parsed.setExecutionResult(null); // 4.0 executionResultList.add(null); // for compatibility with picocli 2.x return executionResultList; } catch (ParameterException ex) { throw ex; } catch (ExecutionException ex) { throw ex; } catch (Exception ex) { throw new ExecutionException(parsed, "Error while running command (" + command + "): " + ex, ex); } } else if (command instanceof Callable) { try { tracer.debug("Invoking Callable::call on user object %s@%s...", command.getClass().getName(), Integer.toHexString(command.hashCode())); @SuppressWarnings("unchecked") Callable callable = (Callable) command; Object executionResult = callable.call(); parsed.setExecutionResult(executionResult); executionResultList.add(executionResult); return executionResultList; } catch (ParameterException ex) { throw ex; } catch (ExecutionException ex) { throw ex; } catch (Exception ex) { throw new ExecutionException(parsed, "Error while calling command (" + command + "): " + ex, ex); } } else if (command instanceof Method) { try { Method method = (Method) command; Object[] parsedArgs = parsed.getCommandSpec().commandMethodParamValues(); Object executionResult; if (Modifier.isStatic(method.getModifiers())) { tracer.debug("Invoking static method %s with parameters %s", method, Arrays.toString(parsedArgs)); executionResult = method.invoke(null, parsedArgs); // invoke static method } else { Object instance = (parsed.getCommandSpec().parent() != null) ? parsed.getCommandSpec().parent().userObject() : parsed.factory.create(method.getDeclaringClass()); tracer.debug("Invoking method %s on %s@%s with parameters %s", method, instance.getClass().getName(), Integer.toHexString(instance.hashCode()), Arrays.toString(parsedArgs)); executionResult = method.invoke(instance, parsedArgs); } parsed.setExecutionResult(executionResult); executionResultList.add(executionResult); return executionResultList; } catch (InvocationTargetException ex) { Throwable t = ex.getTargetException(); if (t instanceof ParameterException) { throw (ParameterException) t; } else if (t instanceof ExecutionException) { throw (ExecutionException) t; } else { throw new ExecutionException(parsed, "Error while calling command (" + command + "): " + t, t); } } catch (Exception ex) { throw new ExecutionException(parsed, "Unhandled error while calling command (" + command + "): " + ex, ex); } } if (parsed.getSubcommands().isEmpty()) { throw new ExecutionException(parsed, "Parsed command (" + command + ") is not a Method, Runnable or Callable"); } else { throw new ParameterException(parsed, "Missing required subcommand"); } } /** * Convenience method to allow command line application authors to avoid some boilerplate code in their application. * To use this method, the annotated object that this {@code CommandLine} is constructed with needs to * either implement {@link Runnable}, {@link Callable}, or be a {@code Method} object. * See {@link #getCommandMethods(Class, String) getCommandMethods} for a convenient way to obtain a command {@code Method}. *

This method replaces the {@link #run(Runnable, String...) run}, {@link #call(Callable, String...) call} * and {@link #invoke(String, Class, String...) invoke} convenience methods that were available with previous versions of picocli. *

* Exit Code *

* This method returns an exit code that applications can use to call {@code System.exit}. * (The return value of the {@code Callable} or {@code Method} can still be obtained via {@link #getExecutionResult() getExecutionResult}.) * If the user object {@code Callable} or {@code Method} returns an {@code int} or {@code Integer}, * this will be used as the exit code. Additionally, if the user object implements {@link CommandLine.IExitCodeGenerator IExitCodeGenerator}, * an exit code is obtained by calling its {@code getExitCode()} method (after invoking the user object). *

* In the case of multiple exit codes the highest value will be used (or if all values are negative, the lowest value will be used). *

* Exception Handling *

* This method never throws an exception. *

* If the user specified invalid input, the {@linkplain #getParameterExceptionHandler() parameter exception handler} is invoked. * By default this prints an error message and the usage help message, and returns an exit code. *

* If an exception occurred while the user object {@code Runnable}, {@code Callable}, or {@code Method} * was invoked, this exception is caught and passed to the {@linkplain #getExecutionExceptionHandler() execution exception handler}. * The default {@code IExecutionExceptionHandler} will rethrow this Exception. *

* Any exception thrown from the {@code IParameterExceptionHandler} or {@code IExecutionExceptionHandler} is caught, * it stacktrace is printed and is mapped to an exit code, using the following logic: *

* If an {@link CommandLine.IExitCodeExceptionMapper IExitCodeExceptionMapper} is {@linkplain #setExitCodeExceptionMapper(IExitCodeExceptionMapper) configured}, * this mapper is used to determine the exit code based on the exception. *

* If an {@code IExitCodeExceptionMapper} is not set, by default this method will return the {@code @Command} annotation's * {@link Command#exitCodeOnInvalidInput() exitCodeOnInvalidInput} or {@link Command#exitCodeOnExecutionException() exitCodeOnExecutionException} value, respectively. *

Example Usage:

*
     * @Command
     * class MyCommand implements Callable<Integer> {
     *     public Integer call() { return 123; }
     * }
     * CommandLine cmd = new CommandLine(new MyCommand());
     * int exitCode = cmd.execute(args);
     * assert exitCode == 123;
     * System.exit(exitCode);
     * 
*

Since {@code execute} is an instance method, not a static method, applications can do configuration before invoking the command. For example:

*
{@code
     * CommandLine cmd = new CommandLine(new MyCallable())
     *         .setCaseInsensitiveEnumValuesAllowed(true) // configure a non-default parser option
     *         .setOut(myOutWriter()) // configure an alternative to System.out
     *         .setErr(myErrWriter()) // configure an alternative to System.err
     *         .setColorScheme(myColorScheme()); // configure a custom color scheme
     * int exitCode = cmd.execute(args);
     * System.exit(exitCode);
     * }
*

* If the specified command has subcommands, the {@linkplain RunLast last} subcommand specified on the * command line is executed. This can be configured by setting the {@linkplain #setExecutionStrategy(IExecutionStrategy) execution strategy}. * Built-in alternatives are executing the {@linkplain RunFirst first} subcommand, or executing {@linkplain RunAll all} specified subcommands. *

* @param args the command line arguments to parse * @return the exit code * @see ExitCode * @see IExitCodeGenerator * @see #getExecutionResult() * @see #getExecutionStrategy() * @see #getParameterExceptionHandler() * @see #getExecutionExceptionHandler() * @see #getExitCodeExceptionMapper() * @since 4.0 */ public int execute(String... args) { ParseResult[] parseResult = new ParseResult[1]; clearExecutionResults(); try { parseResult[0] = parseArgs(args); return enrichForBackwardsCompatibility(getExecutionStrategy()).execute(parseResult[0]); } catch (ParameterException ex) { try { return getParameterExceptionHandler().handleParseException(ex, args); } catch (Exception ex2) { return handleUnhandled(ex2, ex.getCommandLine(), ex.getCommandLine().getCommandSpec().exitCodeOnInvalidInput()); } } catch (ExecutionException ex) { try { Exception cause = ex.getCause() instanceof Exception ? (Exception) ex.getCause() : ex; return getExecutionExceptionHandler().handleExecutionException(cause, ex.getCommandLine(), parseResult[0]); } catch (Exception ex2) { return handleUnhandled(ex2, ex.getCommandLine(), ex.getCommandLine().getCommandSpec().exitCodeOnExecutionException()); } } catch (Exception ex) { return handleUnhandled(ex, this, getCommandSpec().exitCodeOnExecutionException()); } } private static int handleUnhandled(Exception ex, CommandLine cmd, int defaultExitCode) { cmd.getErr().print(throwableToColorString(ex, cmd.getColorScheme())); cmd.getErr().flush(); return mappedExitCode(ex, cmd.getExitCodeExceptionMapper(), defaultExitCode); } /** * Convert a {@code Throwable} to a {@code String} , with message and stack traces extracted and colored * according to {@code ColorScheme}. * @param t the {@code Throwable} to be converted * @param existingColorScheme the {@code ColorScheme} to use * @return converted and colored {@code String} */ private static String throwableToColorString(Throwable t, Help.ColorScheme existingColorScheme) { Help.ColorScheme colorScheme = new Help.ColorScheme.Builder(existingColorScheme).applySystemProperties().build(); StringWriter stringWriter = new ColoredStackTraceWriter(colorScheme); t.printStackTrace(new PrintWriter(stringWriter)); return stringWriter.toString(); } /** * Extends StringWriter to use ColorScheme. Allows separating * exception messages from stack traces by intercepting write method. */ static class ColoredStackTraceWriter extends StringWriter { Help.ColorScheme colorScheme; public ColoredStackTraceWriter(Help.ColorScheme colorScheme) { this.colorScheme = colorScheme; } @Override public void write(String str, int off, int len) { List styles = str.startsWith("\t") ? colorScheme.stackTraceStyles() : colorScheme.errorStyles(); super.write(colorScheme.apply(str.substring(off, len), styles).toString()); } } private T enrichForBackwardsCompatibility(T obj) { // in case the IExecutionStrategy is a built-in like RunLast, // and the application called #useOut, #useErr or #useAnsi on it if (obj instanceof AbstractHandler) { AbstractHandler handler = (AbstractHandler) obj; if (handler.out() != System.out) { setOut(newPrintWriter(handler.out(), getStdoutEncoding())); } if (handler.err() != System.err) { setErr(newPrintWriter(handler.err(), getStderrEncoding())); } if (handler.ansi() != Help.Ansi.AUTO) { setColorScheme(handler.colorScheme()); } } return obj; } /** Command line parse result handler that returns a value. This handler prints help if requested, and otherwise calls * {@link #handle(CommandLine.ParseResult)} with the parse result. Facilitates implementation of the {@link IParseResultHandler2} interface. *

Note that {@code AbstractParseResultHandler} is a generic type. This, along with the abstract {@code self} method, * allows method chaining to work properly in subclasses, without the need for casts. An example subclass can look like this:

*
{@code
     * class MyResultHandler extends AbstractParseResultHandler {
     *
     *     protected MyReturnType handle(ParseResult parseResult) throws ExecutionException { ... }
     *
     *     protected MyResultHandler self() { return this; }
     * }
     * }
* @deprecated see {@link #execute(String...)}, {@link #getExecutionStrategy()}, {@link #getParameterExceptionHandler()}, {@link #getExecutionExceptionHandler()} * @since 3.0 */ @Deprecated public abstract static class AbstractParseResultHandler extends AbstractHandler> implements IParseResultHandler2, IExecutionStrategy { /** Prints help if requested, and otherwise calls {@link #handle(CommandLine.ParseResult)}. * Finally, either a list of result objects is returned, or the JVM is terminated if an exit code {@linkplain #andExit(int) was set}. * * @param parseResult the {@code ParseResult} that resulted from successfully parsing the command line arguments * @return the result of {@link #handle(CommandLine.ParseResult) processing parse results} * @throws ParameterException if the {@link HelpCommand HelpCommand} was invoked for an unknown subcommand. Any {@code ParameterExceptions} * thrown from this method are treated as if this exception was thrown during parsing and passed to the {@link IExceptionHandler2} * @throws ExecutionException if a problem occurred while processing the parse results; client code can use * {@link ExecutionException#getCommandLine()} to get the command or subcommand where processing failed */ public R handleParseResult(ParseResult parseResult) throws ExecutionException { if (printHelpIfRequested(parseResult.asCommandLineList(), out(), err(), colorScheme())) { return returnResultOrExit(null); } return returnResultOrExit(handle(parseResult)); } public int execute(ParseResult parseResult) throws ExecutionException { Integer helpExitCode = executeHelpRequest(parseResult); if (helpExitCode != null) { return helpExitCode; } Tracer t = CommandLine.tracer(); t.debug("%s: handling ParseResult...", getClass().getSimpleName()); R executionResult = handle(parseResult); List exitCodeGenerators = extractExitCodeGenerators(parseResult); t.debug("%s: ParseResult has %s exit code generators", getClass().getSimpleName(), exitCodeGenerators.size()); return resolveExitCode(parseResult.commandSpec().exitCodeOnSuccess(), executionResult, exitCodeGenerators); } // Use the highest value (or if all values are negative, use the lowest value). private int resolveExitCode(int exitCodeOnSuccess, R executionResult, List exitCodeGenerators) { int result = 0; for (IExitCodeGenerator generator : exitCodeGenerators) { try { int exitCode = generator.getExitCode(); if ((exitCode > 0 && exitCode > result) || (exitCode < result && result <= 0)) { result = exitCode; } } catch (Exception ex) { result = (result == 0) ? 1 : result; ex.printStackTrace(); } } Tracer t = CommandLine.tracer(); t.debug("resolveExitCode: exit code generators resulted in exit code=%d", result); if (executionResult instanceof List) { List resultList = (List) executionResult; for (Object obj : resultList) { if (obj instanceof Integer) { int exitCode = (Integer) obj; if ((exitCode > 0 && exitCode > result) || (exitCode < result && result <= 0)) { result = exitCode; } } } } t.debug("resolveExitCode: execution results resulted in exit code=%d", result); t.debug("resolveExitCode: returning exit code=%d", result == 0 ? exitCodeOnSuccess : result); return result == 0 ? exitCodeOnSuccess : result; } /** Processes the specified {@code ParseResult} and returns the result as a list of objects. * Implementations are responsible for catching any exceptions thrown in the {@code handle} method, and * rethrowing an {@code ExecutionException} that details the problem and captures the offending {@code CommandLine} object. * * @param parseResult the {@code ParseResult} that resulted from successfully parsing the command line arguments * @return the result of processing parse results * @throws ExecutionException if a problem occurred while processing the parse results; client code can use * {@link ExecutionException#getCommandLine()} to get the command or subcommand where processing failed */ protected abstract R handle(ParseResult parseResult) throws ExecutionException; protected List extractExitCodeGenerators(ParseResult parseResult) { return Collections.emptyList(); } } /** * Command line {@linkplain IExecutionStrategy execution strategy} that prints help if requested, and otherwise executes the top-level * {@code Runnable} or {@code Callable} command. * For use by the {@link #execute(String...) execute} method. * @since 2.0 */ public static class RunFirst extends AbstractParseResultHandler> implements IParseResultHandler { /** {@inheritDoc} */ public int execute(ParseResult parseResult) throws ExecutionException { return super.execute(parseResult); } /** Prints help if requested, and otherwise executes the top-level {@code Runnable} or {@code Callable} command. * Finally, either a list of result objects is returned, or the JVM is terminated if an exit code {@linkplain #andExit(int) was set}. * If the top-level command does not implement either {@code Runnable} or {@code Callable}, an {@code ExecutionException} * is thrown detailing the problem and capturing the offending {@code CommandLine} object. * * @param parsedCommands the {@code CommandLine} objects that resulted from successfully parsing the command line arguments * @param out the {@code PrintStream} to print help to if requested * @param ansi for printing help messages using ANSI styles and colors * @return an empty list if help was requested, or a list containing a single element: the result of calling the * {@code Callable}, or a {@code null} element if the top-level command was a {@code Runnable} * @throws ParameterException if the {@link HelpCommand HelpCommand} was invoked for an unknown subcommand. Any {@code ParameterExceptions} * thrown from this method are treated as if this exception was thrown during parsing and passed to the {@link IExceptionHandler} * @throws ExecutionException if a problem occurred while processing the parse results; use * {@link ExecutionException#getCommandLine()} to get the command or subcommand where processing failed */ public List handleParseResult(List parsedCommands, PrintStream out, Help.Ansi ansi) { if (printHelpIfRequested(parsedCommands, out, err(), ansi)) { return returnResultOrExit(Collections.emptyList()); } return returnResultOrExit(executeUserObject(parsedCommands.get(0), new ArrayList())); } /** Executes the top-level {@code Runnable} or {@code Callable} subcommand. * If the top-level command does not implement either {@code Runnable} or {@code Callable} and is not a {@code Method}, an {@code ExecutionException} * is thrown detailing the problem and capturing the offending {@code CommandLine} object. * * @param parseResult the {@code ParseResult} that resulted from successfully parsing the command line arguments * @return an empty list if help was requested, or a list containing a single element: the result of calling the * {@code Callable}, or a {@code null} element if the last (sub)command was a {@code Runnable} * @throws ExecutionException if a problem occurred while processing the parse results; use * {@link ExecutionException#getCommandLine()} to get the command or subcommand where processing failed * @since 3.0 */ protected List handle(ParseResult parseResult) throws ExecutionException { Tracer t = CommandLine.tracer(); t.debug("RunFirst: executing user object for '%s'...", parseResult.commandSpec().qualifiedName()); return executeUserObject(parseResult.commandSpec().commandLine(), new ArrayList()); // first } protected List extractExitCodeGenerators(ParseResult parseResult) { if (parseResult.commandSpec().userObject() instanceof IExitCodeGenerator) { return Collections.singletonList((IExitCodeGenerator) parseResult.commandSpec().userObject()); } return Collections.emptyList(); } @Override protected RunFirst self() { return this; } } /** * Command line {@linkplain IExecutionStrategy execution strategy} that prints help if requested, and otherwise executes the most specific * {@code Runnable} or {@code Callable} subcommand. * For use by the {@link #execute(String...) execute} method. *

* Something like this:

*
{@code
     *     // RunLast implementation: print help if requested, otherwise execute the most specific subcommand
     *     List parsedCommands = parseResult.asCommandLineList();
     *     if (CommandLine.printHelpIfRequested(parsedCommands, out(), err(), ansi())) {
     *         return emptyList();
     *     }
     *     CommandLine last = parsedCommands.get(parsedCommands.size() - 1);
     *     Object command = last.getCommand();
     *     Object result = null;
     *     if (command instanceof Runnable) {
     *         try {
     *             ((Runnable) command).run();
     *         } catch (Exception ex) {
     *             throw new ExecutionException(last, "Error in runnable " + command, ex);
     *         }
     *     } else if (command instanceof Callable) {
     *         try {
     *             result = ((Callable) command).call();
     *         } catch (Exception ex) {
     *             throw new ExecutionException(last, "Error in callable " + command, ex);
     *         }
     *     } else {
     *         throw new ExecutionException(last, "Parsed command (" + command + ") is not Runnable or Callable");
     *     }
     *     last.setExecutionResult(result);
     *     return Arrays.asList(result);
     * }
*

* From picocli v2.0, {@code RunLast} is used to implement the {@link #run(Runnable, PrintStream, PrintStream, Help.Ansi, String...) run} * and {@link #call(Callable, PrintStream, PrintStream, Help.Ansi, String...) call} convenience methods. *

* @since 2.0 */ public static class RunLast extends AbstractParseResultHandler> implements IParseResultHandler { /** {@inheritDoc} */ public int execute(ParseResult parseResult) throws ExecutionException { return super.execute(parseResult); } /** Prints help if requested, and otherwise executes the most specific {@code Runnable} or {@code Callable} subcommand. *

For {@linkplain Command#subcommandsRepeatable() repeatable subcommands}, this method * may execute multiple subcommands: the most deeply nested subcommands that have the same parent command.

*

Finally, either a list of result objects is returned, or the JVM is terminated if an exit code {@linkplain #andExit(int) was set}.

*

If the last (sub)command does not implement either {@code Runnable} or {@code Callable}, an {@code ExecutionException} * is thrown detailing the problem and capturing the offending {@code CommandLine} object.

* * @param parsedCommands the {@code CommandLine} objects that resulted from successfully parsing the command line arguments * @param out the {@code PrintStream} to print help to if requested * @param ansi for printing help messages using ANSI styles and colors * @return an empty list if help was requested, or a list containing a single element: the result of calling the * {@code Callable}, or a {@code null} element if the last (sub)command was a {@code Runnable} * @throws ParameterException if the {@link HelpCommand HelpCommand} was invoked for an unknown subcommand. Any {@code ParameterExceptions} * thrown from this method are treated as if this exception was thrown during parsing and passed to the {@link IExceptionHandler} * @throws ExecutionException if a problem occurred while processing the parse results; use * {@link ExecutionException#getCommandLine()} to get the command or subcommand where processing failed */ public List handleParseResult(List parsedCommands, PrintStream out, Help.Ansi ansi) { if (printHelpIfRequested(parsedCommands, out, err(), ansi)) { return returnResultOrExit(Collections.emptyList()); } return returnResultOrExit(executeUserObjectOfLastSubcommandWithSameParent(parsedCommands)); } /** Executes the most specific {@code Runnable} or {@code Callable} subcommand. *

For {@linkplain Command#subcommandsRepeatable() repeatable subcommands}, this method * may execute multiple subcommands: the most deeply nested subcommands that have the same parent command.

*

If the user object of the executed (sub)command does not implement either {@code Runnable} or {@code Callable} and is not a {@code Method}, an {@code ExecutionException} * is thrown detailing the problem and capturing the offending {@code CommandLine} object.

* * @param parseResult the {@code ParseResult} that resulted from successfully parsing the command line arguments * @return an empty list if help was requested, or a list containing a single element: the result of calling the * {@code Callable}, or a {@code null} element if the last (sub)command was a {@code Runnable} * @throws ExecutionException if a problem occurred while processing the parse results; use * {@link ExecutionException#getCommandLine()} to get the command or subcommand where processing failed * @since 3.0 */ protected List handle(ParseResult parseResult) throws ExecutionException { return executeUserObjectOfLastSubcommandWithSameParent(parseResult.asCommandLineList()); } private static List executeUserObjectOfLastSubcommandWithSameParent(List parsedCommands) { Tracer t = CommandLine.tracer(); int start = indexOfLastSubcommandWithSameParent(parsedCommands); List result = new ArrayList(); for (int i = start; i < parsedCommands.size(); i++) { t.debug("RunLast: executing user object for '%s'...", parsedCommands.get(i).commandSpec.qualifiedName()); executeUserObject(parsedCommands.get(i), result); } return result; } // find list of most deeply nested sub-(sub*)-commands private static int indexOfLastSubcommandWithSameParent(List parsedCommands) { int start = parsedCommands.size() - 1; for (int i = parsedCommands.size() - 2; i >= 0; i--) { if (parsedCommands.get(i).getParent() != parsedCommands.get(i + 1).getParent()) { break; } start = i; } return start; } protected List extractExitCodeGenerators(ParseResult parseResult) { List parsedCommands = parseResult.asCommandLineList(); int start = indexOfLastSubcommandWithSameParent(parsedCommands); List result = new ArrayList(); for (int i = start; i < parsedCommands.size(); i++) { Object userObject = parsedCommands.get(i).getCommandSpec().userObject(); if (userObject instanceof IExitCodeGenerator) { result.add((IExitCodeGenerator) userObject); } } return result; } @Override protected RunLast self() { return this; } } /** * Command line {@linkplain IExecutionStrategy execution strategy} that prints help if requested, and otherwise executes the top-level command and * all subcommands as {@code Runnable}, {@code Callable} or {@code Method}. * For use by the {@link #execute(String...) execute} method. * @since 2.0 */ public static class RunAll extends AbstractParseResultHandler> implements IParseResultHandler { /** {@inheritDoc} */ public int execute(ParseResult parseResult) throws ExecutionException { return super.execute(parseResult); } /** Prints help if requested, and otherwise executes the top-level command and all subcommands as {@code Runnable}, * {@code Callable} or {@code Method}. Finally, either a list of result objects is returned, or the JVM is terminated if an exit * code {@linkplain #andExit(int) was set}. If any of the {@code CommandLine} commands does not implement either * {@code Runnable} or {@code Callable}, an {@code ExecutionException} * is thrown detailing the problem and capturing the offending {@code CommandLine} object. * * @param parsedCommands the {@code CommandLine} objects that resulted from successfully parsing the command line arguments * @param out the {@code PrintStream} to print help to if requested * @param ansi for printing help messages using ANSI styles and colors * @return an empty list if help was requested, or a list containing the result of executing all commands: * the return values from calling the {@code Callable} commands, {@code null} elements for commands that implement {@code Runnable} * @throws ParameterException if the {@link HelpCommand HelpCommand} was invoked for an unknown subcommand. Any {@code ParameterExceptions} * thrown from this method are treated as if this exception was thrown during parsing and passed to the {@link IExceptionHandler} * @throws ExecutionException if a problem occurred while processing the parse results; use * {@link ExecutionException#getCommandLine()} to get the command or subcommand where processing failed */ public List handleParseResult(List parsedCommands, PrintStream out, Help.Ansi ansi) { if (printHelpIfRequested(parsedCommands, out, err(), ansi)) { return returnResultOrExit(Collections.emptyList()); } List result = new ArrayList(); for (CommandLine parsed : parsedCommands) { executeUserObject(parsed, result); } return returnResultOrExit(result); } /** Executes the top-level command and all subcommands as {@code Runnable} or {@code Callable}. * If any of the {@code CommandLine} commands does not implement either {@code Runnable} or {@code Callable} and is not a {@code Method}, an {@code ExecutionException} * is thrown detailing the problem and capturing the offending {@code CommandLine} object. * * @param parseResult the {@code ParseResult} that resulted from successfully parsing the command line arguments * @return an empty list if help was requested, or a list containing the result of executing all commands: * the return values from calling the {@code Callable} commands, {@code null} elements for commands that implement {@code Runnable} * @throws ExecutionException if a problem occurred while processing the parse results; use * {@link ExecutionException#getCommandLine()} to get the command or subcommand where processing failed * @since 3.0 */ protected List handle(ParseResult parseResult) throws ExecutionException { Tracer t = CommandLine.tracer(); return returnResultOrExit(recursivelyExecuteUserObject(parseResult, new ArrayList(), t)); } private List recursivelyExecuteUserObject(ParseResult parseResult, List result, Tracer t) throws ExecutionException { t.debug("%s: executing user object for '%s'...", getClass().getSimpleName(), parseResult.commandSpec.qualifiedName()); executeUserObject(parseResult.commandSpec().commandLine(), result); for (ParseResult pr : parseResult.subcommands()) { recursivelyExecuteUserObject(pr, result, t); } return result; } protected List extractExitCodeGenerators(ParseResult parseResult) { return recursivelyExtractExitCodeGenerators(parseResult, new ArrayList()); } private List recursivelyExtractExitCodeGenerators(ParseResult parseResult, List result) throws ExecutionException { if (parseResult.commandSpec().userObject() instanceof IExitCodeGenerator) { result.add((IExitCodeGenerator) parseResult.commandSpec().userObject()); } for (ParseResult pr : parseResult.subcommands()) { recursivelyExtractExitCodeGenerators(pr, result); } return result; } @Override protected RunAll self() { return this; } } /** * @deprecated use {@link #execute(String...)} and {@link #getExecutionResult()} instead * @since 2.0 */ @Deprecated public List parseWithHandler(IParseResultHandler handler, PrintStream out, String... args) { return parseWithHandlers(handler, out, Help.Ansi.AUTO, defaultExceptionHandler(), args); } /** * Returns the result of calling {@link #parseWithHandlers(IParseResultHandler2, IExceptionHandler2, String...)} with * a new {@link DefaultExceptionHandler} in addition to the specified parse result handler and the specified command line arguments. *

* This is a convenience method intended to offer the same ease of use as the {@link #run(Runnable, PrintStream, PrintStream, Help.Ansi, String...) run} * and {@link #call(Callable, PrintStream, PrintStream, Help.Ansi, String...) call} methods, but with more flexibility and better * support for nested subcommands. *

*

Calling this method roughly expands to:

*
{@code
     * try {
     *     ParseResult parseResult = parseArgs(args);
     *     return handler.handleParseResult(parseResult);
     * } catch (ParameterException ex) {
     *     return new DefaultExceptionHandler().handleParseException(ex, args);
     * }
     * }
*

* Picocli provides some default handlers that allow you to accomplish some common tasks with very little code. * The following handlers are available:

*
    *
  • {@link RunLast} handler prints help if requested, and otherwise gets the last specified command or subcommand * and tries to execute it as a {@code Runnable} or {@code Callable}.
  • *
  • {@link RunFirst} handler prints help if requested, and otherwise executes the top-level command as a {@code Runnable} or {@code Callable}.
  • *
  • {@link RunAll} handler prints help if requested, and otherwise executes all recognized commands and subcommands as {@code Runnable} or {@code Callable} tasks.
  • *
  • {@link DefaultExceptionHandler} prints the error message followed by usage help
  • *
* @param the return type of this handler * @param handler the function that will handle the result of successfully parsing the command line arguments * @param args the command line arguments * @return an object resulting from handling the parse result or the exception that occurred while parsing the input * @throws ExecutionException if the command line arguments were parsed successfully but a problem occurred while processing the * parse results; use {@link ExecutionException#getCommandLine()} to get the command or subcommand where processing failed * @see RunLast * @see RunAll * @deprecated use {@link #execute(String...)} and {@link #getExecutionResult()} instead * @since 3.0 */ @Deprecated public R parseWithHandler(IParseResultHandler2 handler, String[] args) { return parseWithHandlers(handler, new DefaultExceptionHandler(), args); } /** * @deprecated use {@link #execute(String...)} and {@link #getExecutionResult()} instead * @since 2.0 */ @Deprecated public List parseWithHandlers(IParseResultHandler handler, PrintStream out, Help.Ansi ansi, IExceptionHandler exceptionHandler, String... args) { clearExecutionResults(); try { List result = parse(args); return handler.handleParseResult(result, out, ansi); } catch (ParameterException ex) { return exceptionHandler.handleException(ex, out, ansi, args); } } /** * Tries to {@linkplain #parseArgs(String...) parse} the specified command line arguments, and if successful, delegates * the processing of the resulting {@code ParseResult} object to the specified {@linkplain IParseResultHandler2 handler}. * If the command line arguments were invalid, the {@code ParameterException} thrown from the {@code parse} method * is caught and passed to the specified {@link IExceptionHandler2}. *

* This is a convenience method intended to offer the same ease of use as the {@link #run(Runnable, PrintStream, PrintStream, Help.Ansi, String...) run} * and {@link #call(Callable, PrintStream, PrintStream, Help.Ansi, String...) call} methods, but with more flexibility and better * support for nested subcommands. *

*

Calling this method roughly expands to:

*
     * ParseResult parseResult = null;
     * try {
     *     parseResult = parseArgs(args);
     *     return handler.handleParseResult(parseResult);
     * } catch (ParameterException ex) {
     *     return exceptionHandler.handleParseException(ex, (String[]) args);
     * } catch (ExecutionException ex) {
     *     return exceptionHandler.handleExecutionException(ex, parseResult);
     * }
     * 
*

* Picocli provides some default handlers that allow you to accomplish some common tasks with very little code. * The following handlers are available:

*
    *
  • {@link RunLast} handler prints help if requested, and otherwise gets the last specified command or subcommand * and tries to execute it as a {@code Runnable} or {@code Callable}.
  • *
  • {@link RunFirst} handler prints help if requested, and otherwise executes the top-level command as a {@code Runnable} or {@code Callable}.
  • *
  • {@link RunAll} handler prints help if requested, and otherwise executes all recognized commands and subcommands as {@code Runnable} or {@code Callable} tasks.
  • *
  • {@link DefaultExceptionHandler} prints the error message followed by usage help
  • *
* * @param handler the function that will handle the result of successfully parsing the command line arguments * @param exceptionHandler the function that can handle the {@code ParameterException} thrown when the command line arguments are invalid * @param args the command line arguments * @return an object resulting from handling the parse result or the exception that occurred while parsing the input * @throws ExecutionException if the command line arguments were parsed successfully but a problem occurred while processing the parse * result {@code ParseResult} object; use {@link ExecutionException#getCommandLine()} to get the command or subcommand where processing failed * @param the return type of the result handler and exception handler * @see RunLast * @see RunAll * @see DefaultExceptionHandler * @deprecated use {@link #execute(String...)} and {@link #getExecutionResult()} instead * @since 3.0 */ @Deprecated public R parseWithHandlers(IParseResultHandler2 handler, IExceptionHandler2 exceptionHandler, String... args) { clearExecutionResults(); ParseResult parseResult = null; try { parseResult = parseArgs(args); return handler.handleParseResult(parseResult); } catch (ParameterException ex) { return exceptionHandler.handleParseException(ex, args); } catch (ExecutionException ex) { return exceptionHandler.handleExecutionException(ex, parseResult); } } static String versionString() { return String.format("%s, JVM: %s (%s %s %s), OS: %s %s %s", VERSION, System.getProperty("java.version"), System.getProperty("java.vendor"), System.getProperty("java.vm.name"), System.getProperty("java.vm.version"), System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch")); } /** * Equivalent to {@code new CommandLine(command).usage(out)}. See {@link #usage(PrintStream)} for details. * @param command the object annotated with {@link Command}, {@link Option} and {@link Parameters} * @param out the print stream to print the help message to * @throws IllegalArgumentException if the specified command object does not have a {@link Command}, {@link Option} or {@link Parameters} annotation */ public static void usage(Object command, PrintStream out) { toCommandLine(command, new DefaultFactory()).usage(out); } /** * Equivalent to {@code new CommandLine(command).usage(out, ansi)}. * See {@link #usage(PrintStream, Help.Ansi)} for details. * @param command the object annotated with {@link Command}, {@link Option} and {@link Parameters} * @param out the print stream to print the help message to * @param ansi whether the usage message should contain ANSI escape codes or not * @throws IllegalArgumentException if the specified command object does not have a {@link Command}, {@link Option} or {@link Parameters} annotation */ public static void usage(Object command, PrintStream out, Help.Ansi ansi) { toCommandLine(command, new DefaultFactory()).usage(out, ansi); } /** * Equivalent to {@code new CommandLine(command).usage(out, colorScheme)}. * See {@link #usage(PrintStream, Help.ColorScheme)} for details. * @param command the object annotated with {@link Command}, {@link Option} and {@link Parameters} * @param out the print stream to print the help message to * @param colorScheme the {@code ColorScheme} defining the styles for options, parameters and commands when ANSI is enabled * @throws IllegalArgumentException if the specified command object does not have a {@link Command}, {@link Option} or {@link Parameters} annotation */ public static void usage(Object command, PrintStream out, Help.ColorScheme colorScheme) { toCommandLine(command, new DefaultFactory()).usage(out, colorScheme); } /** * Delegates to {@link #usage(PrintStream, Help.ColorScheme)} with the {@linkplain #getColorScheme() configured} color scheme. * @param out the printStream to print to * @see #usage(PrintStream, Help.ColorScheme) */ public void usage(PrintStream out) { usage(out, getColorScheme()); } /** * Delegates to {@link #usage(PrintWriter, Help.ColorScheme)} with the {@linkplain #getColorScheme() configured} color scheme. * @param writer the PrintWriter to print to * @see #usage(PrintWriter, Help.ColorScheme) * @since 3.0 */ public void usage(PrintWriter writer) { usage(writer, getColorScheme()); } /** * Delegates to {@link #usage(PrintStream, Help.ColorScheme)} with the {@linkplain Help#defaultColorScheme(CommandLine.Help.Ansi) default color scheme}. * @param out the printStream to print to * @param ansi whether the usage message should include ANSI escape codes or not * @see #usage(PrintStream, Help.ColorScheme) */ public void usage(PrintStream out, Help.Ansi ansi) { usage(out, Help.defaultColorScheme(ansi)); } /** Similar to {@link #usage(PrintStream, Help.Ansi)} but with the specified {@code PrintWriter} instead of a {@code PrintStream}. * @since 3.0 */ public void usage(PrintWriter writer, Help.Ansi ansi) { usage(writer, Help.defaultColorScheme(ansi)); } /** * Prints a usage help message for the annotated command class to the specified {@code PrintStream}. * Delegates construction of the usage help message to the {@link Help} inner class and is equivalent to: *
     * Help.ColorScheme colorScheme = Help.defaultColorScheme(Help.Ansi.AUTO);
     * Help help = getHelpFactory().create(getCommandSpec(), colorScheme)
     * StringBuilder sb = new StringBuilder();
     * for (String key : getHelpSectionKeys()) {
     *     IHelpSectionRenderer renderer = getHelpSectionMap().get(key);
     *     if (renderer != null) { sb.append(renderer.render(help)); }
     * }
     * out.print(sb);
     * 
*

Annotate your class with {@link Command} to control many aspects of the usage help message, including * the program name, text of section headings and section contents, and some aspects of the auto-generated sections * of the usage help message. *

To customize the auto-generated sections of the usage help message, like how option details are displayed, * instantiate a {@link Help} object and use a {@link Help.TextTable} with more of fewer columns, a custom * {@linkplain Help.Layout layout}, and/or a custom option {@linkplain Help.IOptionRenderer renderer} * for ultimate control over which aspects of an Option or Field are displayed where.

* @param out the {@code PrintStream} to print the usage help message to * @param colorScheme the {@code ColorScheme} defining the styles for options, parameters and commands when ANSI is enabled * @see UsageMessageSpec */ public void usage(PrintStream out, Help.ColorScheme colorScheme) { out.print(usage(new StringBuilder(), getHelpFactory().create(getCommandSpec(), colorScheme))); out.flush(); } /** Similar to {@link #usage(PrintStream, Help.ColorScheme)}, but with the specified {@code PrintWriter} instead of a {@code PrintStream}. * @since 3.0 */ public void usage(PrintWriter writer, Help.ColorScheme colorScheme) { writer.print(usage(new StringBuilder(), getHelpFactory().create(getCommandSpec(), colorScheme))); writer.flush(); } /** Similar to {@link #usage(PrintStream)}, but returns the usage help message as a String instead of printing it to the {@code PrintStream}. * @since 3.2 */ public String getUsageMessage() { return usage(new StringBuilder(), getHelp()).toString(); } /** Similar to {@link #usage(PrintStream, Help.Ansi)}, but returns the usage help message as a String instead of printing it to the {@code PrintStream}. * @since 3.2 */ public String getUsageMessage(Help.Ansi ansi) { return usage(new StringBuilder(), getHelpFactory().create(getCommandSpec(), Help.defaultColorScheme(ansi))).toString(); } /** Similar to {@link #usage(PrintStream, Help.ColorScheme)}, but returns the usage help message as a String instead of printing it to the {@code PrintStream}. * @since 3.2 */ public String getUsageMessage(Help.ColorScheme colorScheme) { return usage(new StringBuilder(), getHelpFactory().create(getCommandSpec(), colorScheme)).toString(); } private StringBuilder usage(StringBuilder sb, Help help) { for (String key : getHelpSectionKeys()) { IHelpSectionRenderer renderer = getHelpSectionMap().get(key); if (renderer != null) { sb.append(renderer.render(help)); } } return sb; } /** * Delegates to {@link #printVersionHelp(PrintStream, Help.Ansi)} with the ANSI setting of the {@linkplain #getColorScheme() configured} color scheme. * @param out the printStream to print to * @see #printVersionHelp(PrintStream, Help.Ansi) * @since 0.9.8 */ public void printVersionHelp(PrintStream out) { printVersionHelp(out, getColorScheme().ansi()); } /** * Prints version information from the {@link Command#version()} annotation to the specified {@code PrintStream}. * Each element of the array of version strings is printed on a separate line. Version strings may contain * markup for colors and style. * @param out the printStream to print to * @param ansi whether the usage message should include ANSI escape codes or not * @see Command#version() * @see Option#versionHelp() * @see #isVersionHelpRequested() * @since 0.9.8 */ public void printVersionHelp(PrintStream out, Help.Ansi ansi) { for (String versionInfo : getCommandSpec().version()) { out.println(ansi.new Text(versionInfo, getColorScheme())); } out.flush(); } /** * Prints version information from the {@link Command#version()} annotation to the specified {@code PrintStream}. * Each element of the array of version strings is {@linkplain String#format(String, Object...) formatted} with the * specified parameters, and printed on a separate line. Both version strings and parameters may contain * markup for colors and style. * @param out the printStream to print to * @param ansi whether the usage message should include ANSI escape codes or not * @param params Arguments referenced by the format specifiers in the version strings * @see Command#version() * @see Option#versionHelp() * @see #isVersionHelpRequested() * @since 1.0.0 */ public void printVersionHelp(PrintStream out, Help.Ansi ansi, Object... params) { for (String versionInfo : getCommandSpec().version()) { out.println(ansi.new Text(format(versionInfo, params), getColorScheme())); } out.flush(); } /** * Delegates to {@link #printVersionHelp(PrintWriter, Help.Ansi, Object...)} with the ANSI setting of the {@linkplain #getColorScheme() configured} color scheme. * @param out the PrintWriter to print to * @since 4.0 */ public void printVersionHelp(PrintWriter out) { printVersionHelp(out, getColorScheme().ansi()); } /** * Prints version information from the {@link Command#version()} annotation to the specified {@code PrintWriter}. * Each element of the array of version strings is {@linkplain String#format(String, Object...) formatted} with the * specified parameters, and printed on a separate line. Both version strings and parameters may contain * markup for colors and style. * @param out the PrintWriter to print to * @param ansi whether the usage message should include ANSI escape codes or not * @param params Arguments referenced by the format specifiers in the version strings * @see Command#version() * @see Option#versionHelp() * @see #isVersionHelpRequested() * @since 4.0 */ public void printVersionHelp(PrintWriter out, Help.Ansi ansi, Object... params) { for (String versionInfo : getCommandSpec().version()) { out.println(ansi.new Text(format(versionInfo, params), getColorScheme())); } out.flush(); } /** * Equivalent to {@code new CommandLine(callable).execute(args)}, except for the return value. * @param callable the command to call when {@linkplain #parseArgs(String...) parsing} succeeds. * @param args the command line arguments to parse * @param the annotated object must implement Callable * @param the return type of the most specific command (must implement {@code Callable}) * @throws InitializationException if the specified command object does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @throws ExecutionException if the Callable throws an exception * @return {@code null} if an error occurred while parsing the command line options, or if help was requested and printed. Otherwise returns the result of calling the Callable * @see #execute(String...) * @since 3.0 * @deprecated use {@link #execute(String...)} and {@link #getExecutionResult()} instead */ @Deprecated public static , T> T call(C callable, String... args) { CommandLine cmd = new CommandLine(callable); List results = cmd.parseWithHandler(new RunLast(), args); return CommandLine.firstElement(results); } /** * Delegates to {@link #call(Callable, PrintStream, PrintStream, Help.Ansi, String...)} with {@code System.err} for * diagnostic error messages and {@link Help.Ansi#AUTO}. * @param callable the command to call when {@linkplain #parseArgs(String...) parsing} succeeds. * @param out the printStream to print the usage help message to when the user requested help * @param args the command line arguments to parse * @param the annotated object must implement Callable * @param the return type of the most specific command (must implement {@code Callable}) * @throws InitializationException if the specified command object does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @throws ExecutionException if the Callable throws an exception * @return {@code null} if an error occurred while parsing the command line options, or if help was requested and printed. Otherwise returns the result of calling the Callable * @deprecated use {@link #execute(String...)} and {@link #getExecutionResult()} instead * @see RunLast */ @Deprecated public static , T> T call(C callable, PrintStream out, String... args) { return call(callable, out, System.err, Help.Ansi.AUTO, args); } /** * Delegates to {@link #call(Callable, PrintStream, PrintStream, Help.Ansi, String...)} with {@code System.err} for diagnostic error messages. * @param callable the command to call when {@linkplain #parseArgs(String...) parsing} succeeds. * @param out the printStream to print the usage help message to when the user requested help * @param ansi the ANSI style to use * @param args the command line arguments to parse * @param the annotated object must implement Callable * @param the return type of the most specific command (must implement {@code Callable}) * @throws InitializationException if the specified command object does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @throws ExecutionException if the Callable throws an exception * @return {@code null} if an error occurred while parsing the command line options, or if help was requested and printed. Otherwise returns the result of calling the Callable * @deprecated use {@link #execute(String...)} and {@link #getExecutionResult()} instead * @see RunLast */ @Deprecated public static , T> T call(C callable, PrintStream out, Help.Ansi ansi, String... args) { return call(callable, out, System.err, ansi, args); } /** * Convenience method to allow command line application authors to avoid some boilerplate code in their application. * The annotated object needs to implement {@link Callable}. *

Consider using the {@link #execute(String...)} method instead:

*
{@code
     * CommandLine cmd = new CommandLine(callable)
     *         .setOut(myOutWriter()) // System.out by default
     *         .setErr(myErrWriter()) // System.err by default
     *         .setColorScheme(myColorScheme()); // default color scheme, Ansi.AUTO by default
     * int exitCode = cmd.execute(args);
     * //System.exit(exitCode);
     * }
*

* If the specified Callable command has subcommands, the {@linkplain RunLast last} subcommand specified on the * command line is executed. *

* @param callable the command to call when {@linkplain #parse(String...) parsing} succeeds. * @param out the printStream to print the usage help message to when the user requested help * @param err the printStream to print diagnostic messages to * @param ansi including whether the usage message should include ANSI escape codes or not * @param args the command line arguments to parse * @param the annotated object must implement Callable * @param the return type of the specified {@code Callable} * @throws InitializationException if the specified command object does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @throws ExecutionException if the Callable throws an exception * @return {@code null} if an error occurred while parsing the command line options, or if help was requested and printed. Otherwise returns the result of calling the Callable * @deprecated use {@link #execute(String...)} and {@link #getExecutionResult()} instead * @since 3.0 */ @Deprecated public static , T> T call(C callable, PrintStream out, PrintStream err, Help.Ansi ansi, String... args) { CommandLine cmd = new CommandLine(callable); List results = cmd.parseWithHandlers(new RunLast().useOut(out).useAnsi(ansi), new DefaultExceptionHandler>().useErr(err).useAnsi(ansi), args); return CommandLine.firstElement(results); } /** * Equivalent to {@code new CommandLine(callableClass, factory).execute(args)}, except for the return value. * @param callableClass class of the command to call when {@linkplain #parseArgs(String...) parsing} succeeds. * @param factory the factory responsible for instantiating the specified callable class and potentially inject other components * @param args the command line arguments to parse * @param the annotated class must implement Callable * @param the return type of the most specific command (must implement {@code Callable}) * @throws InitializationException if the specified class cannot be instantiated by the factory, or does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @throws ExecutionException if the Callable throws an exception * @return {@code null} if an error occurred while parsing the command line options, or if help was requested and printed. Otherwise returns the result of calling the Callable * @see #execute(String...) * @since 3.2 * @deprecated use {@link #execute(String...)} and {@link #getExecutionResult()} instead */ @Deprecated public static , T> T call(Class callableClass, IFactory factory, String... args) { CommandLine cmd = new CommandLine(callableClass, factory); List results = cmd.parseWithHandler(new RunLast(), args); return CommandLine.firstElement(results); } /** * Delegates to {@link #call(Class, IFactory, PrintStream, PrintStream, Help.Ansi, String...)} with * {@code System.err} for diagnostic error messages, and {@link Help.Ansi#AUTO}. * @param callableClass class of the command to call when {@linkplain #parseArgs(String...) parsing} succeeds. * @param factory the factory responsible for instantiating the specified callable class and potentially injecting other components * @param out the printStream to print the usage help message to when the user requested help * @param args the command line arguments to parse * @param the annotated class must implement Callable * @param the return type of the most specific command (must implement {@code Callable}) * @throws InitializationException if the specified class cannot be instantiated by the factory, or does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @throws ExecutionException if the Callable throws an exception * @return {@code null} if an error occurred while parsing the command line options, or if help was requested and printed. Otherwise returns the result of calling the Callable * @deprecated use {@link #execute(String...)} and {@link #getExecutionResult()} instead * @since 3.2 */ @Deprecated public static , T> T call(Class callableClass, IFactory factory, PrintStream out, String... args) { return call(callableClass, factory, out, System.err, Help.Ansi.AUTO, args); } /** * Delegates to {@link #call(Class, IFactory, PrintStream, PrintStream, Help.Ansi, String...)} with * {@code System.err} for diagnostic error messages. * @param callableClass class of the command to call when {@linkplain #parseArgs(String...) parsing} succeeds. * @param factory the factory responsible for instantiating the specified callable class and potentially injecting other components * @param out the printStream to print the usage help message to when the user requested help * @param ansi the ANSI style to use * @param args the command line arguments to parse * @param the annotated class must implement Callable * @param the return type of the most specific command (must implement {@code Callable}) * @throws InitializationException if the specified class cannot be instantiated by the factory, or does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @throws ExecutionException if the Callable throws an exception * @return {@code null} if an error occurred while parsing the command line options, or if help was requested and printed. Otherwise returns the result of calling the Callable * @deprecated use {@link #execute(String...)} and {@link #getExecutionResult()} instead * @since 3.2 */ @Deprecated public static , T> T call(Class callableClass, IFactory factory, PrintStream out, Help.Ansi ansi, String... args) { return call(callableClass, factory, out, System.err, ansi, args); } /** * Convenience method to allow command line application authors to avoid some boilerplate code in their application. * The specified {@linkplain IFactory factory} will create an instance of the specified {@code callableClass}; * use this method instead of {@link #call(Callable, PrintStream, PrintStream, Help.Ansi, String...) call(Callable, ...)} * if you want to use a factory that performs Dependency Injection. * The annotated class needs to implement {@link Callable}. *

Consider using the {@link #execute(String...)} method instead:

*
{@code
     * CommandLine cmd = new CommandLine(callableClass, factory)
     *         .setOut(myOutWriter()) // System.out by default
     *         .setErr(myErrWriter()) // System.err by default
     *         .setColorScheme(myColorScheme()); // default color scheme, Ansi.AUTO by default
     * int exitCode = cmd.execute(args);
     * //System.exit(exitCode);
     * }
*

* If the specified Callable command has subcommands, the {@linkplain RunLast last} subcommand specified on the * command line is executed. *

* @param callableClass class of the command to call when {@linkplain #parseArgs(String...) parsing} succeeds. * @param factory the factory responsible for instantiating the specified callable class and potentially injecting other components * @param out the printStream to print the usage help message to when the user requested help * @param err the printStream to print diagnostic messages to * @param ansi the ANSI style to use * @param args the command line arguments to parse * @param the annotated class must implement Callable * @param the return type of the most specific command (must implement {@code Callable}) * @throws InitializationException if the specified class cannot be instantiated by the factory, or does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @throws ExecutionException if the Callable throws an exception * @return {@code null} if an error occurred while parsing the command line options, or if help was requested and printed. Otherwise returns the result of calling the Callable * @deprecated use {@link #execute(String...)} and {@link #getExecutionResult()} instead * @since 3.2 */ @Deprecated public static , T> T call(Class callableClass, IFactory factory, PrintStream out, PrintStream err, Help.Ansi ansi, String... args) { CommandLine cmd = new CommandLine(callableClass, factory); List results = cmd.parseWithHandlers(new RunLast().useOut(out).useAnsi(ansi), new DefaultExceptionHandler>().useErr(err).useAnsi(ansi), args); return CommandLine.firstElement(results); } @SuppressWarnings("unchecked") private static T firstElement(List results) { return (results == null || results.isEmpty()) ? null : (T) results.get(0); } /** * Equivalent to {@code new CommandLine(runnable).execute(args)}. * @param runnable the command to run when {@linkplain #parseArgs(String...) parsing} succeeds. * @param args the command line arguments to parse * @param the annotated object must implement Runnable * @throws InitializationException if the specified command object does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @throws ExecutionException if the Runnable throws an exception * @see #execute(String...) * @since 3.0 * @deprecated use {@link #execute(String...)} instead */ @Deprecated public static void run(R runnable, String... args) { run(runnable, System.out, System.err, Help.Ansi.AUTO, args); } /** * Delegates to {@link #run(Runnable, PrintStream, PrintStream, Help.Ansi, String...)} with {@code System.err} for diagnostic error messages and {@link Help.Ansi#AUTO}. * @param runnable the command to run when {@linkplain #parseArgs(String...) parsing} succeeds. * @param out the printStream to print the usage help message to when the user requested help * @param args the command line arguments to parse * @param the annotated object must implement Runnable * @throws InitializationException if the specified command object does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @throws ExecutionException if the Runnable throws an exception * @deprecated use {@link #execute(String...)} instead * @see RunLast */ @Deprecated public static void run(R runnable, PrintStream out, String... args) { run(runnable, out, System.err, Help.Ansi.AUTO, args); } /** * Delegates to {@link #run(Runnable, PrintStream, PrintStream, Help.Ansi, String...)} with {@code System.err} for diagnostic error messages. * @param runnable the command to run when {@linkplain #parseArgs(String...) parsing} succeeds. * @param out the printStream to print the usage help message to when the user requested help * @param ansi whether the usage message should include ANSI escape codes or not * @param args the command line arguments to parse * @param the annotated object must implement Runnable * @throws InitializationException if the specified command object does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @throws ExecutionException if the Runnable throws an exception * @deprecated use {@link #execute(String...)} instead * @see RunLast */ @Deprecated public static void run(R runnable, PrintStream out, Help.Ansi ansi, String... args) { run(runnable, out, System.err, ansi, args); } /** * Convenience method to allow command line application authors to avoid some boilerplate code in their application. * The annotated object needs to implement {@link Runnable}. *

Consider using the {@link #execute(String...)} method instead:

*
{@code
     * CommandLine cmd = new CommandLine(runnable)
     *         .setOut(myOutWriter()) // System.out by default
     *         .setErr(myErrWriter()) // System.err by default
     *         .setColorScheme(myColorScheme()); // default color scheme, Ansi.AUTO by default
     * int exitCode = cmd.execute(args);
     * //System.exit(exitCode);
     * }
*

* If the specified Runnable command has subcommands, the {@linkplain RunLast last} subcommand specified on the * command line is executed. *

* From picocli v2.0, this method prints usage help or version help if {@linkplain #printHelpIfRequested(List, PrintStream, PrintStream, Help.Ansi) requested}, * and any exceptions thrown by the {@code Runnable} are caught and rethrown wrapped in an {@code ExecutionException}. *

* @param runnable the command to run when {@linkplain #parse(String...) parsing} succeeds. * @param out the printStream to print the usage help message to when the user requested help * @param err the printStream to print diagnostic messages to * @param ansi whether the usage message should include ANSI escape codes or not * @param args the command line arguments to parse * @param the annotated object must implement Runnable * @throws InitializationException if the specified command object does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @throws ExecutionException if the Runnable throws an exception * @deprecated use {@link #execute(String...)} instead * @since 3.0 */ @Deprecated public static void run(R runnable, PrintStream out, PrintStream err, Help.Ansi ansi, String... args) { CommandLine cmd = new CommandLine(runnable); cmd.parseWithHandlers(new RunLast().useOut(out).useAnsi(ansi), new DefaultExceptionHandler>().useErr(err).useAnsi(ansi), args); } /** * Equivalent to {@code new CommandLine(runnableClass, factory).execute(args)}. * @param runnableClass class of the command to run when {@linkplain #parseArgs(String...) parsing} succeeds. * @param factory the factory responsible for instantiating the specified Runnable class and potentially injecting other components * @param args the command line arguments to parse * @param the annotated class must implement Runnable * @throws InitializationException if the specified class cannot be instantiated by the factory, or does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @throws ExecutionException if the Runnable throws an exception * @see #execute(String...) * @since 3.2 * @deprecated use {@link #execute(String...)} instead */ @Deprecated public static void run(Class runnableClass, IFactory factory, String... args) { run(runnableClass, factory, System.out, System.err, Help.Ansi.AUTO, args); } /** * Delegates to {@link #run(Class, IFactory, PrintStream, PrintStream, Help.Ansi, String...)} with * {@code System.err} for diagnostic error messages, and {@link Help.Ansi#AUTO}. * @param runnableClass class of the command to run when {@linkplain #parseArgs(String...) parsing} succeeds. * @param factory the factory responsible for instantiating the specified Runnable class and potentially injecting other components * @param out the printStream to print the usage help message to when the user requested help * @param args the command line arguments to parse * @param the annotated class must implement Runnable * @see #run(Class, IFactory, PrintStream, PrintStream, Help.Ansi, String...) * @throws InitializationException if the specified class cannot be instantiated by the factory, or does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @throws ExecutionException if the Runnable throws an exception * @see #parseWithHandlers(IParseResultHandler2, IExceptionHandler2, String...) * @see RunLast * @deprecated use {@link #execute(String...)} instead * @since 3.2 */ @Deprecated public static void run(Class runnableClass, IFactory factory, PrintStream out, String... args) { run(runnableClass, factory, out, System.err, Help.Ansi.AUTO, args); } /** * Delegates to {@link #run(Class, IFactory, PrintStream, PrintStream, Help.Ansi, String...)} with * {@code System.err} for diagnostic error messages. * @param runnableClass class of the command to run when {@linkplain #parseArgs(String...) parsing} succeeds. * @param factory the factory responsible for instantiating the specified Runnable class and potentially injecting other components * @param out the printStream to print the usage help message to when the user requested help * @param ansi whether the usage message should include ANSI escape codes or not * @param args the command line arguments to parse * @param the annotated class must implement Runnable * @see #run(Class, IFactory, PrintStream, PrintStream, Help.Ansi, String...) * @throws InitializationException if the specified class cannot be instantiated by the factory, or does not have a {@link Command}, {@link Option} or {@link Parameters} annotation * @throws ExecutionException if the Runnable throws an exception * @see #parseWithHandlers(IParseResultHandler2, IExceptionHandler2, String...) * @see RunLast * @deprecated use {@link #execute(String...)} instead * @since 3.2 */ @Deprecated public static void run(Class runnableClass, IFactory factory, PrintStream out, Help.Ansi ansi, String... args) { run(runnableClass, factory, out, System.err, ansi, args); } /** * Convenience method to allow command line application authors to avoid some boilerplate code in their application. * The specified {@linkplain IFactory factory} will create an instance of the specified {@code runnableClass}; * use this method instead of {@link #run(Runnable, PrintStream, PrintStream, Help.Ansi, String...) run(Runnable, ...)} * if you want to use a factory that performs Dependency Injection. * The annotated class needs to implement {@link Runnable}. *

Consider using the {@link #execute(String...)} method instead:

*
{@code
     * CommandLine cmd = new CommandLine(runnableClass, factory)
     *         .setOut(myOutWriter()) // System.out by default
     *         .setErr(myErrWriter()) // System.err by default
     *         .setColorScheme(myColorScheme()); // default color scheme, Ansi.AUTO by default
     * int exitCode = cmd.execute(args);
     * //System.exit(exitCode);
     * }
*

* If the specified Runnable command has subcommands, the {@linkplain RunLast last} subcommand specified on the * command line is executed. *

* This method prints usage help or version help if {@linkplain #printHelpIfRequested(List, PrintStream, PrintStream, Help.Ansi) requested}, * and any exceptions thrown by the {@code Runnable} are caught and rethrown wrapped in an {@code ExecutionException}. *

* @param runnableClass class of the command to run when {@linkplain #parseArgs(String...) parsing} succeeds. * @param factory the factory responsible for instantiating the specified Runnable class and potentially injecting other components * @param out the printStream to print the usage help message to when the user requested help * @param err the printStream to print diagnostic messages to * @param ansi whether the usage message should include ANSI escape codes or not * @param args the command line arguments to parse * @param the annotated class must implement Runnable * @deprecated use {@link #execute(String...)} instead * @since 3.2 */ @Deprecated public static void run(Class runnableClass, IFactory factory, PrintStream out, PrintStream err, Help.Ansi ansi, String... args) { CommandLine cmd = new CommandLine(runnableClass, factory); cmd.parseWithHandlers(new RunLast().useOut(out).useAnsi(ansi), new DefaultExceptionHandler>().useErr(err).useAnsi(ansi), args); } /** * Delegates to {@link #invoke(String, Class, PrintStream, PrintStream, Help.Ansi, String...)} with {@code System.out} for * requested usage help messages, {@code System.err} for diagnostic error messages, and {@link Help.Ansi#AUTO}. * @param methodName the {@code @Command}-annotated method to build a {@link CommandSpec} model from, * and run when {@linkplain #parseArgs(String...) parsing} succeeds. * @param cls the class where the {@code @Command}-annotated method is declared, or a subclass * @param args the command line arguments to parse * @see #invoke(String, Class, PrintStream, PrintStream, Help.Ansi, String...) * @throws InitializationException if the specified method does not have a {@link Command} annotation, * or if the specified class contains multiple {@code @Command}-annotated methods with the specified name * @throws ExecutionException if the Runnable throws an exception * @see #parseWithHandlers(IParseResultHandler2, IExceptionHandler2, String...) * @since 3.6 * @deprecated use {@link #execute(String...)} and {@link #getExecutionResult()} instead */ @Deprecated public static Object invoke(String methodName, Class cls, String... args) { return invoke(methodName, cls, System.out, System.err, Help.Ansi.AUTO, args); } /** * Delegates to {@link #invoke(String, Class, PrintStream, PrintStream, Help.Ansi, String...)} with the specified stream for * requested usage help messages, {@code System.err} for diagnostic error messages, and {@link Help.Ansi#AUTO}. * @param methodName the {@code @Command}-annotated method to build a {@link CommandSpec} model from, * and run when {@linkplain #parseArgs(String...) parsing} succeeds. * @param cls the class where the {@code @Command}-annotated method is declared, or a subclass * @param out the printstream to print requested help message to * @param args the command line arguments to parse * @see #invoke(String, Class, PrintStream, PrintStream, Help.Ansi, String...) * @throws InitializationException if the specified method does not have a {@link Command} annotation, * or if the specified class contains multiple {@code @Command}-annotated methods with the specified name * @throws ExecutionException if the Runnable throws an exception * @see #parseWithHandlers(IParseResultHandler2, IExceptionHandler2, String...) * @deprecated use {@link #execute(String...)} and {@link #getExecutionResult()} instead * @since 3.6 */ @Deprecated public static Object invoke(String methodName, Class cls, PrintStream out, String... args) { return invoke(methodName, cls, out, System.err, Help.Ansi.AUTO, args); } /** * Delegates to {@link #invoke(String, Class, PrintStream, PrintStream, Help.Ansi, String...)} with the specified stream for * requested usage help messages, {@code System.err} for diagnostic error messages, and the specified Ansi mode. * @param methodName the {@code @Command}-annotated method to build a {@link CommandSpec} model from, * and run when {@linkplain #parseArgs(String...) parsing} succeeds. * @param cls the class where the {@code @Command}-annotated method is declared, or a subclass * @param out the printstream to print requested help message to * @param ansi whether the usage message should include ANSI escape codes or not * @param args the command line arguments to parse * @see #invoke(String, Class, PrintStream, PrintStream, Help.Ansi, String...) * @throws InitializationException if the specified method does not have a {@link Command} annotation, * or if the specified class contains multiple {@code @Command}-annotated methods with the specified name * @throws ExecutionException if the Runnable throws an exception * @see #parseWithHandlers(IParseResultHandler2, IExceptionHandler2, String...) * @deprecated use {@link #execute(String...)} and {@link #getExecutionResult()} instead * @since 3.6 */ @Deprecated public static Object invoke(String methodName, Class cls, PrintStream out, Help.Ansi ansi, String... args) { return invoke(methodName, cls, out, System.err, ansi, args); } /** * Convenience method to allow command line application authors to avoid some boilerplate code in their application. * Constructs a {@link CommandSpec} model from the {@code @Option} and {@code @Parameters}-annotated method parameters * of the {@code @Command}-annotated method, parses the specified command line arguments and invokes the specified method. *

Consider using the {@link #execute(String...)} method instead:

*
{@code
     * Method commandMethod = getCommandMethods(cls, methodName).get(0);
     * CommandLine cmd = new CommandLine(commandMethod)
     *         .setOut(myOutWriter()) // System.out by default
     *         .setErr(myErrWriter()) // System.err by default
     *         .setColorScheme(myColorScheme()); // default color scheme, Ansi.AUTO by default
     * int exitCode = cmd.execute(args);
     * //System.exit(exitCode);
     * }
* @param methodName the {@code @Command}-annotated method to build a {@link CommandSpec} model from, * and run when {@linkplain #parseArgs(String...) parsing} succeeds. * @param cls the class where the {@code @Command}-annotated method is declared, or a subclass * @param out the printStream to print the usage help message to when the user requested help * @param err the printStream to print diagnostic messages to * @param ansi whether the usage message should include ANSI escape codes or not * @param args the command line arguments to parse * @throws InitializationException if the specified method does not have a {@link Command} annotation, * or if the specified class contains multiple {@code @Command}-annotated methods with the specified name * @throws ExecutionException if the method throws an exception * @deprecated use {@link #execute(String...)} and {@link #getExecutionResult()} instead * @since 3.6 */ @Deprecated public static Object invoke(String methodName, Class cls, PrintStream out, PrintStream err, Help.Ansi ansi, String... args) { List candidates = getCommandMethods(cls, methodName); if (candidates.size() != 1) { throw new InitializationException("Expected exactly one @Command-annotated method for " + cls.getName() + "::" + methodName + "(...), but got: " + candidates); } Method method = candidates.get(0); CommandLine cmd = new CommandLine(method); List list = cmd.parseWithHandlers(new RunLast().useOut(out).useAnsi(ansi), new DefaultExceptionHandler>().useErr(err).useAnsi(ansi), args); return list == null ? null : list.get(0); } /** * Helper to get methods of a class annotated with {@link Command @Command} via reflection, optionally filtered by method name (not {@link Command#name() @Command.name}). * Methods have to be either public (inherited) members or be declared by {@code cls}, that is "inherited" static or protected methods will not be picked up. * * @param cls the class to search for methods annotated with {@code @Command} * @param methodName if not {@code null}, return only methods whose method name (not {@link Command#name() @Command.name}) equals this string. Ignored if {@code null}. * @return the matching command methods, or an empty list * @see #invoke(String, Class, String...) * @since 3.6.0 */ public static List getCommandMethods(Class cls, String methodName) { return getCommandMethods(cls, methodName, true); } private static List getCommandMethods(Class cls, String methodName, boolean includeInherited) { Set candidates = new HashSet(); if (includeInherited) { // traverse public member methods (excludes static/non-public, includes inherited) candidates.addAll(Arrays.asList(Assert.notNull(cls, "class").getMethods())); } // traverse directly declared methods (includes static/non-public, excludes inherited) candidates.addAll(Arrays.asList(Assert.notNull(cls, "class").getDeclaredMethods())); List result = new ArrayList(); for (Method method : candidates) { if (method.isAnnotationPresent(Command.class)) { if (methodName == null || methodName.equals(method.getName())) { result.add(method); } } } Collections.sort(result, new Comparator() { public int compare(Method o1, Method o2) { return o1.getName().compareTo(o2.getName()); } }); return result; } /** * Registers the specified type converter for the specified class. When initializing fields annotated with * {@link Option}, the field's type is used as a lookup key to find the associated type converter, and this * type converter converts the original command line argument string value to the correct type. *

* Java 8 lambdas make it easy to register custom type converters: *

*
     * commandLine.registerConverter(java.nio.file.Path.class, s -> java.nio.file.Paths.get(s));
     * commandLine.registerConverter(java.time.Duration.class, s -> java.time.Duration.parse(s));
*

* Built-in type converters are pre-registered for the following java 1.5 types: *

*
    *
  • all primitive types
  • *
  • all primitive wrapper types: Boolean, Byte, Character, Double, Float, Integer, Long, Short
  • *
  • any enum
  • *
  • java.io.File
  • *
  • java.math.BigDecimal
  • *
  • java.math.BigInteger
  • *
  • java.net.InetAddress
  • *
  • java.net.URI
  • *
  • java.net.URL
  • *
  • java.nio.charset.Charset
  • *
  • java.sql.Time
  • *
  • java.util.Date
  • *
  • java.util.UUID
  • *
  • java.util.regex.Pattern
  • *
  • StringBuilder
  • *
  • CharSequence
  • *
  • String
  • *
*

The specified converter will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment the converter is registered. Subcommands added * later will not have this converter added automatically. To ensure a custom type converter is available to all * subcommands, register the type converter last, after adding subcommands.

* * @param cls the target class to convert parameter string values to * @param converter the class capable of converting string values to the specified target type * @param the target type * @return this CommandLine object, to allow method chaining * @see #addSubcommand(String, Object) */ public CommandLine registerConverter(Class cls, ITypeConverter converter) { interpreter.converterRegistry.put(Assert.notNull(cls, "class"), Assert.notNull(converter, "converter")); for (CommandLine command : getCommandSpec().commands.values()) { command.registerConverter(cls, converter); } return this; } /** Returns the String that separates option names from option values when parsing command line options. * @return the String the parser uses to separate option names from option values * @see ParserSpec#separator() */ public String getSeparator() { return getCommandSpec().parser().separator(); } /** Sets the String the parser uses to separate option names from option values to the specified value. * The separator may also be set declaratively with the {@link CommandLine.Command#separator()} annotation attribute. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param separator the String that separates option names from option values * @see ParserSpec#separator(String) * @return this {@code CommandLine} object, to allow method chaining */ public CommandLine setSeparator(String separator) { getCommandSpec().parser().separator(Assert.notNull(separator, "separator")); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setSeparator(separator); } return this; } /** Returns the ResourceBundle of this command or {@code null} if no resource bundle is set. * @see Command#resourceBundle() * @see CommandSpec#resourceBundle() * @since 3.6 */ public ResourceBundle getResourceBundle() { return getCommandSpec().resourceBundle(); } /** Sets the ResourceBundle containing usage help message strings. *

The specified bundle will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will not be impacted. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param bundle the ResourceBundle containing usage help message strings * @return this {@code CommandLine} object, to allow method chaining * @see Command#resourceBundle() * @see CommandSpec#resourceBundle(ResourceBundle) * @since 3.6 */ public CommandLine setResourceBundle(ResourceBundle bundle) { getCommandSpec().resourceBundle(bundle); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setResourceBundle(bundle); } return this; } /** Returns the maximum width of the usage help message. The default is 80. * @see UsageMessageSpec#width() */ public int getUsageHelpWidth() { return getCommandSpec().usageMessage().width(); } /** Sets the maximum width of the usage help message. Longer lines are wrapped. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param width the maximum width of the usage help message * @see UsageMessageSpec#width(int) * @return this {@code CommandLine} object, to allow method chaining */ public CommandLine setUsageHelpWidth(int width) { getCommandSpec().usageMessage().width(width); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setUsageHelpWidth(width); } return this; } /** Returns the maximum usage help long options column max width to the specified value. * This value controls the maximum width of the long options column: any positional parameter * labels or long options that are longer than the specified value will overflow into * the description column, and cause the description to be displayed on the next line. * @see UsageMessageSpec#longOptionsMaxWidth() * @since 4.2*/ public int getUsageHelpLongOptionsMaxWidth() { return getCommandSpec().usageMessage().longOptionsMaxWidth(); } /** Returns the maximum usage help long options column max width to the specified value. * This value controls the maximum width of the long options column: any positional parameter * labels or long options that are longer than the specified value will overflow into * the description column, and cause the description to be displayed on the next line. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param columnWidth the new maximum usage help long options column max width. Must be 20 or greater. * @see UsageMessageSpec#longOptionsMaxWidth(int) * @return this {@code CommandLine} object, to allow method chaining * @since 4.2 */ public CommandLine setUsageHelpLongOptionsMaxWidth(int columnWidth) { getCommandSpec().usageMessage().longOptionsMaxWidth(columnWidth); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setUsageHelpLongOptionsMaxWidth(columnWidth); } return this; } /** Returns whether picocli should attempt to detect the terminal size and adjust the usage help message width * to take the full terminal width. End users may enable this by setting system property {@code "picocli.usage.width"} to {@code AUTO}, * and may disable this by setting this system property to a {@linkplain UsageMessageSpec#width() numeric value}. * This feature requires Java 7 or greater. The default is {@code false}. * @see UsageMessageSpec#autoWidth() * @since 4.0 */ public boolean isUsageHelpAutoWidth() { return getCommandSpec().usageMessage().autoWidth(); } /** Sets whether picocli should attempt to detect the terminal size and adjust the usage help message width * to take the full terminal width. The default is {@code false}. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* @param detectTerminalSize whether picocli should attempt to detect the terminal size * @see UsageMessageSpec#autoWidth(boolean) * @return this {@code CommandLine} object, to allow method chaining * @since 4.0 */ public CommandLine setUsageHelpAutoWidth(boolean detectTerminalSize) { getCommandSpec().usageMessage().autoWidth(detectTerminalSize); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setUsageHelpAutoWidth(detectTerminalSize); } return this; } /** Returns the command name (also called program name) displayed in the usage help synopsis. * @return the command name (also called program name) displayed in the usage * @see CommandSpec#name() * @since 2.0 */ public String getCommandName() { return getCommandSpec().name(); } /** Sets the command name (also called program name) displayed in the usage help synopsis to the specified value. * Note that this method only modifies the usage help message, it does not impact parsing behaviour. * The command name may also be set declaratively with the {@link CommandLine.Command#name()} annotation attribute. * @param commandName command name (also called program name) displayed in the usage help synopsis * @return this {@code CommandLine} object, to allow method chaining * @see CommandSpec#name(String) * @since 2.0 */ public CommandLine setCommandName(String commandName) { getCommandSpec().name(Assert.notNull(commandName, "commandName")); return this; } /** Returns whether arguments starting with {@code '@'} should be treated as the path to an argument file and its * contents should be expanded into separate arguments for each line in the specified file. * This property is {@code true} by default. * @return whether "argument files" or {@code @files} should be expanded into their content * @see ParserSpec#expandAtFiles() * @since 2.1 */ public boolean isExpandAtFiles() { return getCommandSpec().parser().expandAtFiles(); } /** Sets whether arguments starting with {@code '@'} should be treated as the path to an argument file and its * contents should be expanded into separate arguments for each line in the specified file. ({@code true} by default.) * @param expandAtFiles whether "argument files" or {@code @files} should be expanded into their content * @return this {@code CommandLine} object, to allow method chaining * @see ParserSpec#expandAtFiles(boolean) * @since 2.1 */ public CommandLine setExpandAtFiles(boolean expandAtFiles) { getCommandSpec().parser().expandAtFiles(expandAtFiles); return this; } /** Returns the character that starts a single-line comment or {@code null} if all content of argument files should * be interpreted as arguments (without comments). * If specified, all characters from the comment character to the end of the line are ignored. * @return the character that starts a single-line comment or {@code null}. The default is {@code '#'}. * @see ParserSpec#atFileCommentChar() * @since 3.5 */ public Character getAtFileCommentChar() { return getCommandSpec().parser().atFileCommentChar(); } /** Sets the character that starts a single-line comment or {@code null} if all content of argument files should * be interpreted as arguments (without comments). * If specified, all characters from the comment character to the end of the line are ignored. * @param atFileCommentChar the character that starts a single-line comment or {@code null}. The default is {@code '#'}. * @return this {@code CommandLine} object, to allow method chaining * @see ParserSpec#atFileCommentChar(Character) * @since 3.5 */ public CommandLine setAtFileCommentChar(Character atFileCommentChar) { getCommandSpec().parser().atFileCommentChar(atFileCommentChar); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setAtFileCommentChar(atFileCommentChar); } return this; } /** Returns whether to use a simplified argument file format that is compatible with JCommander. * In this format, every line (except empty lines and comment lines) * is interpreted as a single argument. Arguments containing whitespace do not need to be quoted. * When system property {@code "picocli.useSimplifiedAtFiles"} is defined, the system property value overrides the programmatically set value. * @return whether to use a simplified argument file format. The default is {@code false}. * @see ParserSpec#useSimplifiedAtFiles() * @since 3.9 */ public boolean isUseSimplifiedAtFiles() { return getCommandSpec().parser().useSimplifiedAtFiles(); } /** Sets whether to use a simplified argument file format that is compatible with JCommander. * In this format, every line (except empty lines and comment lines) * is interpreted as a single argument. Arguments containing whitespace do not need to be quoted. * When system property {@code "picocli.useSimplifiedAtFiles"} is defined, the system property value overrides the programmatically set value. * @param simplifiedAtFiles whether to use a simplified argument file format. The default is {@code false}. * @return this {@code CommandLine} object, to allow method chaining * @see ParserSpec#useSimplifiedAtFiles(boolean) * @since 3.9 */ public CommandLine setUseSimplifiedAtFiles(boolean simplifiedAtFiles) { getCommandSpec().parser().useSimplifiedAtFiles(simplifiedAtFiles); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setUseSimplifiedAtFiles(simplifiedAtFiles); } return this; } /** Returns the {@code INegatableOptionTransformer} used to create the negative form of {@linkplain Option#negatable() negatable} options. * By default this returns the result of {@link RegexTransformer#createDefault()}. * @return the {@code INegatableOptionTransformer} used to create negative option names. * @see Option#negatable() * @see CommandSpec#negatableOptionTransformer() * @since 4.0 */ public INegatableOptionTransformer getNegatableOptionTransformer() { return getCommandSpec().negatableOptionTransformer(); } /** Sets the {@code INegatableOptionTransformer} used to create the negative form of {@linkplain Option#negatable() negatable} options. *

The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.

* Note that {@link CommandLine#setOptionsCaseInsensitive} will also change the case sensitivity of {@linkplain Option#negatable() negatable} options: * any custom {@link INegatableOptionTransformer} that was previously installed will be replaced by the case-insensitive * version of the default transformer. To ensure your custom transformer is used, install it last, after changing case sensitivity. * @param transformer the {@code INegatableOptionTransformer} used to create negative option names. * @return this {@code CommandLine} object, to allow method chaining * @see Option#negatable() * @see CommandSpec#negatableOptionTransformer(CommandLine.INegatableOptionTransformer) * @since 4.0 */ public CommandLine setNegatableOptionTransformer(INegatableOptionTransformer transformer) { getCommandSpec().negatableOptionTransformer(transformer); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setNegatableOptionTransformer(transformer); } return this; } private static boolean empty(String str) { return str == null || str.trim().length() == 0; } private static boolean empty(Object[] array) { return array == null || array.length == 0; } private static String str(String[] arr, int i) { return (arr == null || arr.length <= i) ? "" : arr[i]; } private static boolean isBoolean(Class[] types) { return isBoolean(types[0]) || (isOptional(types[0]) && isBoolean(types[1])); } private static boolean isBoolean(Class type) { return type == Boolean.class || type == Boolean.TYPE; } private static CommandLine toCommandLine(Object obj, IFactory factory) { return obj instanceof CommandLine ? (CommandLine) obj : new CommandLine(obj, factory, false);} private static boolean isMultiValue(Class cls) { return (cls.isArray() && cls != char[].class) || Collection.class.isAssignableFrom(cls) || Map.class.isAssignableFrom(cls); } private static boolean isOptional(Class cls) { return cls != null && "java.util.Optional".equals(cls.getName()); } // #1108 private static Object getOptionalEmpty() throws Exception { return Class.forName("java.util.Optional").getMethod("empty").invoke(null); } private static Object getOptionalOfNullable(Object newValue) throws Exception { return Class.forName("java.util.Optional").getMethod("ofNullable", Object.class).invoke(null, newValue); } private static String format(String formatString, Object... params) { try { return formatString == null ? "" : String.format(formatString, params); } catch (IllegalFormatException ex) { CommandLine.tracer().warn("Could not format '%s' (Underlying error: %s). " + "Using raw String: '%%n' format strings have not been replaced with newlines. " + "Please ensure to escape '%%' characters with another '%%'.", formatString, ex.getMessage()); return formatString; } } private static Map mapOf(String key, Object value, Object... other) { LinkedHashMap result = new LinkedHashMap(); result.put(key, value); for (int i = 0; i < other.length - 1; i += 2) { result.put(String.valueOf(other[i]), other[i + 1]); } return result; } private static class NoCompletionCandidates implements Iterable { public Iterator iterator() { throw new UnsupportedOperationException(); } } /** Specifies the scope of the element. * @since 4.3 */ public enum ScopeType { /** The element only exists in the current command. */ LOCAL, /** The element exists in the command where the element is defined and all descendants (subcommands, sub-subcommands, etc.). */ INHERIT, } /** *

* Annotate fields in your class with {@code @Option} and picocli will initialize these fields when matching * arguments are specified on the command line. In the case of command methods (annotated with {@code @Command}), * command options can be defined by annotating method parameters with {@code @Option}. *

* Command class example: *

*
     * import static picocli.CommandLine.*;
     *
     * public class MyClass {
     *     @Parameters(description = "Any number of input files")
     *     private List<File> files = new ArrayList<File>();
     *
     *     @Option(names = { "-o", "--out" }, description = "Output file (default: print to console)")
     *     private File outputFile;
     *
     *     @Option(names = { "-v", "--verbose"}, description = "Verbose mode. Helpful for troubleshooting. Multiple -v options increase the verbosity.")
     *     private boolean[] verbose;
     *
     *     @Option(names = { "-h", "--help", "-?", "-help"}, usageHelp = true, description = "Display this help and exit")
     *     private boolean help;
     * }
     * 
*

* A field cannot be annotated with both {@code @Parameters} and {@code @Option} or a * {@code ParameterException} is thrown. *

*/ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) public @interface Option { /** Special value that can be used in some annotation attributes to designate {@code null}. * @see Option#defaultValue() * @see Option#fallbackValue() * @see Option#mapFallbackValue() * @since 4.6 */ public static final String NULL_VALUE = ArgSpec.NULL_VALUE; /** * One or more option names. At least one option name is required. *

* Different environments have different conventions for naming options, but usually options have a prefix * that sets them apart from parameters. * Picocli supports all of the below styles. The default separator is {@code '='}, but this can be configured. *

* *nix *

* In Unix and Linux, options have a short (single-character) name, a long name or both. * Short options * (POSIX * style are single-character and are preceded by the {@code '-'} character, e.g., {@code `-v'}. * GNU-style long * (or mnemonic) options start with two dashes in a row, e.g., {@code `--file'}. *

Picocli supports the POSIX convention that short options can be grouped, with the last option * optionally taking a parameter, which may be attached to the option name or separated by a space or * a {@code '='} character. The below examples are all equivalent: *

         * -xvfFILE
         * -xvf FILE
         * -xvf=FILE
         * -xv --file FILE
         * -xv --file=FILE
         * -x -v --file FILE
         * -x -v --file=FILE
         * 

* DOS *

* DOS options mostly have upper case single-character names and start with a single slash {@code '/'} character. * Option parameters are separated by a {@code ':'} character. Options cannot be grouped together but * must be specified separately. For example: *

         * DIR /S /A:D /T:C
         * 

* PowerShell *

* Windows PowerShell options generally are a word preceded by a single {@code '-'} character, e.g., {@code `-Help'}. * Option parameters are separated by a space or by a {@code ':'} character. *

* @return one or more option names */ String[] names(); /** * Indicates whether this option is required. By default this is false. *

If an option is required, but a user invokes the program without specifying the required option, * a {@link MissingParameterException} is thrown from the {@link #parse(String...)} method.

*

Required options that are part of a {@linkplain ArgGroup group} are required within the group, not required within the command: * the group's {@linkplain ArgGroup#multiplicity() multiplicity} determines whether the group itself is required or optional.

* @return whether this option is required */ boolean required() default false; /** *

This should rarely be used: the recommended attributes are {@link #usageHelp() usageHelp} and {@link #versionHelp() versionHelp}. *

* Only set {@code help=true} when this option should disable validation of the remaining * arguments, and no error message should be generated for missing required options. *

* This is useful for custom help options that are in addition to the standard help and * version options. For example if your application has many hidden options or * subcommands, and there is a custom help option like {@code --detailed-help} that prints * the usage help message for these hidden options and subcommands. *

*

Note:

*

* Use the {@link #usageHelp() usageHelp} for "normal" help options (like {@code -h} and {@code --help} on unix, * {@code -?} and {@code -Help} on Windows) * and use {@link #versionHelp() versionHelp} for "normal" version help ({@code -V} and {@code --version} on unix, * {@code -Version} on Windows): * picocli has built-in logic so that options with {@code usageHelp=true} or {@code versionHelp=true} * will automatically cause the requested help message to be printed in applications * that use the {@link #execute(String...)} method, without any code in the application. *

* Note that there is no such automatic help printing for options with {@code help=true}; * applications need to check whether the end user specified this option and take appropriate action * in the business logic of the application. *

* @return whether this option disables validation of the other arguments */ boolean help() default false; /** * Set {@code usageHelp=true} for the {@code --help} option that triggers display of the usage help message. * The convenience methods {@code Commandline.call}, * {@code Commandline.run}, and {@code Commandline.parseWithHandler(s)} will automatically print usage help * when an option with {@code usageHelp=true} was specified on the command line. *

* By default, all options and positional parameters are included in the usage help message * except when explicitly marked {@linkplain #hidden() hidden}. *

* If this option is specified on the command line, picocli will not validate the remaining arguments (so no "missing required * option" errors) and the {@link CommandLine#isUsageHelpRequested()} method will return {@code true}. *

* Alternatively, consider annotating your command with {@linkplain Command#mixinStandardHelpOptions() @Command(mixinStandardHelpOptions = true)}. *

* @return whether this option allows the user to request usage help * @since 0.9.8 * @see #hidden() * @see #run(Runnable, String...) * @see #call(Callable, String...) * @see #parseWithHandler(IParseResultHandler2, String[]) * @see #printHelpIfRequested(List, PrintStream, PrintStream, Help.Ansi) */ boolean usageHelp() default false; /** * Set {@code versionHelp=true} for the {@code --version} option that triggers display of the version information. * The convenience methods {@code Commandline.call}, * {@code Commandline.run}, and {@code Commandline.parseWithHandler(s)} will automatically print version information * when an option with {@code versionHelp=true} was specified on the command line. *

* The version information string is obtained from the command's {@linkplain Command#version() version} annotation * or from the {@linkplain Command#versionProvider() version provider}. *

* If this option is specified on the command line, picocli will not validate the remaining arguments (so no "missing required * option" errors) and the {@link CommandLine#isUsageHelpRequested()} method will return {@code true}. *

* Alternatively, consider annotating your command with {@linkplain Command#mixinStandardHelpOptions() @Command(mixinStandardHelpOptions = true)}. *

* @return whether this option allows the user to request version information * @since 0.9.8 * @see #hidden() * @see #run(Runnable, String...) * @see #call(Callable, String...) * @see #parseWithHandler(IParseResultHandler2, String[]) * @see #printHelpIfRequested(List, PrintStream, PrintStream, Help.Ansi) */ boolean versionHelp() default false; /** * Description of this option, used when generating the usage documentation. Each element of the array is rendered on a separate line. *

May contain embedded {@linkplain java.util.Formatter format specifiers} like {@code %n} line separators. Literal percent {@code '%'} characters must be escaped with another {@code %}. *

* The description may contain variables that are rendered when help is requested. * The string {@code ${DEFAULT-VALUE}} is replaced with the default value of the option. This is regardless of * the command's {@link Command#showDefaultValues() showDefaultValues} setting or the option's {@link #showDefaultValue() showDefaultValue} setting. * The string {@code ${COMPLETION-CANDIDATES}} is replaced with the completion candidates generated by * {@link #completionCandidates()} in the description for this option. * Also, embedded {@code %n} newline markers are converted to actual newlines. *

* @return the description of this option * @see Variable Interpolation section of the user manual */ String[] description() default {}; /** * Specifies the minimum number of required parameters and the maximum number of accepted parameters. * If an option declares a positive arity, and the user specifies an insufficient number of parameters on the * command line, a {@link MissingParameterException} is thrown by the {@link #parse(String...)} method. *

* In many cases picocli can deduce the number of required parameters from the field's type. * By default, flags (boolean options) have arity "0..1", * and single-valued type fields (String, int, Integer, double, Double, File, Date, etc) have arity one. * Generally, fields with types that cannot hold multiple values can omit the {@code arity} attribute. *

* Fields used to capture options with arity two or higher should have a type that can hold multiple values, * like arrays or Collections. See {@link #type()} for strongly-typed Collection fields. *

* For example, if an option has 2 required parameters and any number of optional parameters, * specify {@code @Option(names = "-example", arity = "2..*")}. *

* A note on boolean options *

* By default picocli allows boolean options (also called "flags" or "switches") to have an optional parameter, * which must be either "true" or "false" (lowercase, other values are rejected). * You can make a boolean option take a required parameter by annotating your field with {@code arity="1"}. * For example:

*
@Option(names = "-v", arity = "1") boolean verbose;
*

* Because this boolean field is defined with arity 1, the user must specify either {@code -v false} * or {@code -v true} * on the command line, or a {@link MissingParameterException} is thrown by the {@link #parse(String...)} * method. *

* To remove the optional parameter, define the field with {@code arity = "0"}. * For example:

*
@Option(names="-v", arity="0") boolean verbose;
*

This will reject any of the below:

*
         * -v true
         * -v false
         * 
* @return how many arguments this option requires */ String arity() default ""; /** * Specify a {@code paramLabel} for the option parameter to be used in the usage help message. If omitted, * picocli uses the field name in fish brackets ({@code '<'} and {@code '>'}) by default. Example: *
class Example {
         *     @Option(names = {"-o", "--output"}, paramLabel="FILE", description="path of the output file")
         *     private File out;
         *     @Option(names = {"-j", "--jobs"}, arity="0..1", description="Allow N jobs at once; infinite jobs with no arg.")
         *     private int maxJobs = -1;
         * }
*

By default, the above gives a usage help message like the following:

         * Usage: <main class> [OPTIONS]
         * -o, --output FILE       path of the output file
         * -j, --jobs [<maxJobs>]  Allow N jobs at once; infinite jobs with no arg.
         * 
* @return name of the option parameter used in the usage help message */ String paramLabel() default ""; /** Returns whether usage syntax decorations around the {@linkplain #paramLabel() paramLabel} should be suppressed. * The default is {@code false}: by default, the paramLabel is surrounded with {@code '['} and {@code ']'} characters * if the value is optional and followed by ellipses ("...") when multiple values can be specified. * @since 3.6.0 */ boolean hideParamSyntax() default false; /**

* Optionally specify a {@code type} to control exactly what Class the option parameter should be converted * to. This may be useful when the field type is an interface or an abstract class. For example, a field can * be declared to have type {@code java.lang.Number}, and annotating {@code @Option(type=Short.class)} * ensures that the option parameter value is converted to a {@code Short} before setting the field value. *

* For array fields whose component type is an interface or abstract class, specify the concrete component type. * For example, a field with type {@code Number[]} may be annotated with {@code @Option(type=Short.class)} * to ensure that option parameter values are converted to {@code Short} before adding an element to the array. *

* Picocli will use the {@link ITypeConverter} that is * {@linkplain #registerConverter(Class, ITypeConverter) registered} for the specified type to convert * the raw String values before modifying the field value. *

* Prior to 2.0, the {@code type} attribute was necessary for {@code Collection} and {@code Map} fields, * but starting from 2.0 picocli will infer the component type from the generic type's type arguments. * For example, for a field of type {@code Map} picocli will know the option parameter * should be split up in key=value pairs, where the key should be converted to a {@code java.util.concurrent.TimeUnit} * enum value, and the value should be converted to a {@code Long}. No {@code @Option(type=...)} type attribute * is required for this. For generic types with wildcards, picocli will take the specified upper or lower bound * as the Class to convert to, unless the {@code @Option} annotation specifies an explicit {@code type} attribute. *

* If the field type is a raw collection or a raw map, and you want it to contain other values than Strings, * or if the generic type's type arguments are interfaces or abstract classes, you may * specify a {@code type} attribute to control the Class that the option parameter should be converted to. * @return the type(s) to convert the raw String values */ Class[] type() default {}; /** * Optionally specify one or more {@link ITypeConverter} classes to use to convert the command line argument into * a strongly typed value (or key-value pair for map fields). This is useful when a particular field should * use a custom conversion that is different from the normal conversion for the field's type. *

For example, for a specific field you may want to use a converter that maps the constant names defined * in {@link java.sql.Types java.sql.Types} to the {@code int} value of these constants, but any other {@code int} fields should * not be affected by this and should continue to use the standard int converter that parses numeric values.

* @return the type converter(s) to use to convert String values to strongly typed values for this field * @see CommandLine#registerConverter(Class, ITypeConverter) */ Class>[] converter() default {}; /** * Specify a regular expression to use to split option parameter values before applying them to the field. * All elements resulting from the split are added to the array or Collection. Previously ignored for single-value fields, * from picocli 4.0 a {@code split} regex can only be specified on multi-value options and positional parameters. * @return a regular expression to split option parameter values or {@code ""} if the value should not be split * @see String#split(String) */ String split() default ""; /** * Specify the string to display for the {@link #split split} regular expression in the usage help synopsis. * @since 4.3 */ String splitSynopsisLabel() default ""; /** * Set {@code hidden=true} if this option should not be included in the usage help message. * @return whether this option should be excluded from the usage documentation */ boolean hidden() default false; /** Returns the default value of this option, before splitting and type conversion. *

To get a {@code null} default value, omit specifying a default value or use the special value {@link Option#NULL_VALUE} - * for options of type {@code Optional} that will result in the {@code Optional.empty()} * value being assigned when the option is not specified on the command line.

* @return a String that (after type conversion) will be used as the value for this option if the option was not specified on the command line * @see #fallbackValue() * @since 3.2 */ String defaultValue() default "__no_default_value__"; /** Use this attribute to control for a specific option whether its default value should be shown in the usage * help message. If not specified, the default value is only shown when the {@link Command#showDefaultValues()} * is set {@code true} on the command. Use this attribute to specify whether the default value * for this specific option should always be shown or never be shown, regardless of the command setting. *

Note that picocli 3.2 allows {@linkplain #description() embedding default values} by specifying the variable * {@code ${DEFAULT-VALUE}} anywhere in the description that ignores this setting.

* @return whether this option's default value should be shown in the usage help message */ Help.Visibility showDefaultValue() default Help.Visibility.ON_DEMAND; /** Use this attribute to specify an {@code Iterable} class that generates completion candidates for this option. * For map fields, completion candidates should be in {@code key=value} form. *

* Completion candidates are used in bash completion scripts generated by the {@code picocli.AutoComplete} class. * Bash has special completion options to generate file names and host names, and the bash completion scripts * generated by {@code AutoComplete} delegate to these bash built-ins for {@code @Options} whose {@code type} is * {@code java.io.File}, {@code java.nio.file.Path} or {@code java.net.InetAddress}. *

* For {@code @Options} whose {@code type} is a Java {@code enum}, {@code AutoComplete} can generate completion * candidates from the type. For other types, use this attribute to specify completion candidates. *

* * @return a class whose instances can iterate over the completion candidates for this option * @see picocli.CommandLine.IFactory * @since 3.2 */ Class> completionCandidates() default NoCompletionCandidates.class; /** * Set {@code interactive=true} to make this option prompt the end user for a value (like a password). * Only supported for single-value options and {@code char[]} arrays (no collections, maps or other array types). * When running on Java 6 or greater and {@link Option#echo() echo = false} (the default), * this will use the {@link Console#readPassword()} API to get a value without echoing input to the console, * otherwise it will simply read a value from {@code System.in}. *

* For passwords, best security practice is to use type {@code char[]} instead of {@code String}, and to to null out the array after use. *

* When defined with {@code arity = "0..1"}, the option can also take a value from the command line. * (The user will still be prompted if no option parameter was specified on the command line.) * This is useful for commands that need to be run interactively as well as in batch mode. *

* @return whether this option prompts the end user for a value to be entered on the command line * @since 3.5 */ boolean interactive() default false; /** Use this attribute to control whether user input for an interactive option is echoed to the console or not. * If {@code echo = true}, the user input is echoed to the console. * This attribute is ignored when {@code interactive = false} (the default). * @return whether the user input for an interactive option should be echoed to the console or not * @see OptionSpec#echo() * @since 4.6 */ boolean echo() default false; /** Use this attribute to customize the text displayed to the end user for an interactive option when asking for user input. * When omitted, the displayed text is derived from the option name and the first description line. * This attribute is ignored when {@code interactive = false} (the default). * @return the text to display to the end user for an interactive option when asking for user input * @see OptionSpec#prompt() * @since 4.6 */ String prompt() default ""; /** ResourceBundle key for this option. If not specified, (and a ResourceBundle {@linkplain Command#resourceBundle() exists for this command}) an attempt * is made to find the option description using any of the option names (without leading hyphens) as key. * @see OptionSpec#description() * @since 3.6 */ String descriptionKey() default ""; /** * When {@link Command#sortOptions() @Command(sortOptions = false)} is specified, this attribute can be used to control the order in which options are listed in the usage help message. * When {@link Command#sortSynopsis() @Command(sortSynopsis = false)} is specified, this attribute controls the order in which options appear in the synopsis of the usage help message. * @return the position in the options list at which this option should be shown. Options with a lower number are shown before options with a higher number. Gaps are allowed. * @since 3.9 */ int order() default -1; /** (Only for boolean options): set this to automatically add a negative version for this boolean option. * For example, for a {@code --force} option the negative version would be {@code --no-force}, * and for a {@code -XX:+PrintGCDetails} option, the negative version would be {@code -XX:-PrintGCDetails}. * The synopsis would show {@code --[no-]force} and {@code -XX:(+|-)PrintGCDetails}, respectively. *

The form of the negative name can be customized by modifying the regular expressions * used by {@linkplain RegexTransformer#createDefault() default}, or by replacing the default * {@link INegatableOptionTransformer} with a custom implementation entirely.

*

Negative option names used to parse the command line are collected when the command is constructed * (so any variables in the option names will be resolved at that time). * Documentation strings for negatable options are generated on demand when the usage help message is shown.

* @see CommandLine#getNegatableOptionTransformer() * @see CommandLine#setNegatableOptionTransformer(INegatableOptionTransformer) * @since 4.0 */ boolean negatable() default false; /** Determines on which command(s) this option exists: on this command only (the default), or * whether this is a "global" option that is applied to this command and all subcommands, sub-subcommands, etc. * @since 4.3 */ ScopeType scope() default ScopeType.LOCAL; /** * For options with an optional parameter (for example, {@code arity = "0..1"}), this value is assigned to the annotated element * if the option is specified on the command line without an option parameter. *

* This is different from the {@link #defaultValue()}, which is assigned if the option is not specified at all on the command line. *

* Using a {@code fallbackValue} allows applications to distinguish between

*
    *
  • option was not specified on the command line (default value assigned)
  • *
  • option was specified without parameter on the command line (fallback value assigned)
  • *
  • option was specified with parameter on the command line (command line argument value assigned)
  • *
*

This is useful to define options that can function as a boolean "switch" * and optionally allow users to provide a (strongly typed) extra parameter value. *

*

Use the special value {@link Option#NULL_VALUE} to specify {@code null} - * for options of type {@code Optional} that will result in the {@code Optional.empty()} * value being assigned when the option name is specified without a parameter on the command line.

* @see OptionSpec#fallbackValue() * @since 4.0 */ String fallbackValue() default ""; /** For options of type Map, setting the {@code mapFallbackValue} to any value allows end user * to specify key-only parameters for this option. For example, {@code -Dkey} instead of {@code -Dkey=value}. *

The value specified in this annotation is the value that is put into the Map for the user-specified key. * Use the special value {@link Option#NULL_VALUE} to specify {@code null} - * for maps of type {@code Map>} that will result in {@code Optional.empty()} * values in the map when only the key is specified.

*

If no {@code mapFallbackValue} is set, key-only Map parameters like {@code -Dkey} * are considered invalid user input and cause a {@link ParameterException} to be thrown.

* @see ArgSpec#mapFallbackValue() * @since 4.6 */ String mapFallbackValue() default ArgSpec.UNSPECIFIED; /** * Optionally specify a custom {@code IParameterConsumer} to temporarily suspend picocli's parsing logic * and process one or more command line arguments in a custom manner. * This may be useful when passing arguments through to another program. * @since 4.0 */ Class parameterConsumer() default NullParameterConsumer.class; /** Returns the preprocessor for this option. * @see IParameterPreprocessor * @since 4.6 */ Class preprocessor() default NoOpParameterPreprocessor.class; } /** *

* Fields annotated with {@code @Parameters} will be initialized with positional parameters. By specifying the * {@link #index()} attribute you can pick the exact position or a range of positional parameters to apply. If no * index is specified, the field will get all positional parameters (and so it should be an array or a collection). *

* In the case of command methods (annotated with {@code @Command}), method parameters may be annotated with {@code @Parameters}, * but are are considered positional parameters by default, unless they are annotated with {@code @Option}. *

* Command class example: *

*
     * import static picocli.CommandLine.*;
     *
     * public class MyCalcParameters {
     *     @Parameters(description = "Any number of input numbers")
     *     private List<BigDecimal> files = new ArrayList<BigDecimal>();
     *
     *     @Option(names = { "-h", "--help" }, usageHelp = true, description = "Display this help and exit")
     *     private boolean help;
     * }
     * 

* A field cannot be annotated with both {@code @Parameters} and {@code @Option} or a {@code ParameterException} * is thrown.

*/ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) public @interface Parameters { /** Special value that can be used in some annotation attributes to designate {@code null}. * @see Parameters#defaultValue() * @see Parameters#mapFallbackValue() * @since 4.6 */ public static final String NULL_VALUE = ArgSpec.NULL_VALUE; /** Specify an index ("0", or "1", etc.) to pick which of the command line arguments should be assigned to this * field. For array or Collection fields, you can also specify an index range ("0..3", or "2..*", etc.) to assign * a subset of the command line arguments to this field. The default is "*", meaning all command line arguments. * @return an index or range specifying which of the command line arguments should be assigned to this field */ String index() default ""; /** Description of the parameter(s), used when generating the usage documentation. Each element of the array is rendered on a separate line. *

May contain embedded {@linkplain java.util.Formatter format specifiers} like {@code %n} line separators. Literal percent {@code '%'} characters must be escaped with another {@code %}. *

* The description may contain variables that are rendered when help is requested. * The string {@code ${DEFAULT-VALUE}} is replaced with the default value of the positional parameter. This is regardless of * the command's {@link Command#showDefaultValues() showDefaultValues} setting or the positional parameter's {@link #showDefaultValue() showDefaultValue} setting. * The string {@code ${COMPLETION-CANDIDATES}} is replaced with the completion candidates generated by * {@link #completionCandidates()} in the description for this positional parameter. * Also, embedded {@code %n} newline markers are converted to actual newlines. *

* @return the description of the parameter(s) * @see Variable Interpolation section of the user manual */ String[] description() default {}; /** * Specifies the minimum number of required parameters and the maximum number of accepted parameters. If a * positive arity is declared, and the user specifies an insufficient number of parameters on the command line, * {@link MissingParameterException} is thrown by the {@link #parse(String...)} method. *

The default depends on the type of the parameter: booleans require no parameters, arrays and Collections * accept zero to any number of parameters, and any other type accepts one parameter.

*

For single-value parameters, setting {@code arity = "0..1"} makes a positional parameter optional, while setting {@code arity = "1"} makes it required.

*

Required parameters that are part of a {@linkplain ArgGroup group} are required within the group, not required within the command: * the group's {@linkplain ArgGroup#multiplicity() multiplicity} determines whether the group itself is required or optional.

* @return the range of minimum and maximum parameters accepted by this command */ String arity() default ""; /** * Specify a {@code paramLabel} for the parameter to be used in the usage help message. If omitted, * picocli uses the field name in fish brackets ({@code '<'} and {@code '>'}) by default. Example: *
class Example {
         *     @Parameters(paramLabel="FILE", description="path of the input FILE(s)")
         *     private File[] inputFiles;
         * }
*

By default, the above gives a usage help message like the following:

         * Usage: <main class> [FILE...]
         * [FILE...]       path of the input FILE(s)
         * 
* @return name of the positional parameter used in the usage help message */ String paramLabel() default ""; /** Returns whether usage syntax decorations around the {@linkplain #paramLabel() paramLabel} should be suppressed. * The default is {@code false}: by default, the paramLabel is surrounded with {@code '['} and {@code ']'} characters * if the value is optional and followed by ellipses ("...") when multiple values can be specified. * @since 3.6.0 */ boolean hideParamSyntax() default false; /** *

* Optionally specify a {@code type} to control exactly what Class the positional parameter should be converted * to. This may be useful when the field type is an interface or an abstract class. For example, a field can * be declared to have type {@code java.lang.Number}, and annotating {@code @Parameters(type=Short.class)} * ensures that the positional parameter value is converted to a {@code Short} before setting the field value. *

* For array fields whose component type is an interface or abstract class, specify the concrete component type. * For example, a field with type {@code Number[]} may be annotated with {@code @Parameters(type=Short.class)} * to ensure that positional parameter values are converted to {@code Short} before adding an element to the array. *

* Picocli will use the {@link ITypeConverter} that is * {@linkplain #registerConverter(Class, ITypeConverter) registered} for the specified type to convert * the raw String values before modifying the field value. *

* Prior to 2.0, the {@code type} attribute was necessary for {@code Collection} and {@code Map} fields, * but starting from 2.0 picocli will infer the component type from the generic type's type arguments. * For example, for a field of type {@code Map} picocli will know the positional parameter * should be split up in key=value pairs, where the key should be converted to a {@code java.util.concurrent.TimeUnit} * enum value, and the value should be converted to a {@code Long}. No {@code @Parameters(type=...)} type attribute * is required for this. For generic types with wildcards, picocli will take the specified upper or lower bound * as the Class to convert to, unless the {@code @Parameters} annotation specifies an explicit {@code type} attribute. *

* If the field type is a raw collection or a raw map, and you want it to contain other values than Strings, * or if the generic type's type arguments are interfaces or abstract classes, you may * specify a {@code type} attribute to control the Class that the positional parameter should be converted to. * @return the type(s) to convert the raw String values */ Class[] type() default {}; /** * Optionally specify one or more {@link ITypeConverter} classes to use to convert the command line argument into * a strongly typed value (or key-value pair for map fields). This is useful when a particular field should * use a custom conversion that is different from the normal conversion for the field's type. *

For example, for a specific field you may want to use a converter that maps the constant names defined * in {@link java.sql.Types java.sql.Types} to the {@code int} value of these constants, but any other {@code int} fields should * not be affected by this and should continue to use the standard int converter that parses numeric values.

* @return the type converter(s) to use to convert String values to strongly typed values for this field * @see CommandLine#registerConverter(Class, ITypeConverter) */ Class>[] converter() default {}; /** * Specify a regular expression to use to split positional parameter values before applying them to the field. * All elements resulting from the split are added to the array or Collection. Previously ignored for single-value fields, * from picocli 4.0 a {@code split} regex can only be specified on multi-value options and positional parameters. * @return a regular expression to split operand values or {@code ""} if the value should not be split * @see String#split(String) */ String split() default ""; /** * Specify a string to show the split option parameter values in usage * @since 4.3 */ String splitSynopsisLabel() default ""; /** * Set {@code hidden=true} if this parameter should not be included in the usage message. * @return whether this parameter should be excluded from the usage message */ boolean hidden() default false; /** Returns the default value of this positional parameter, before splitting and type conversion. *

To get a {@code null} default value, omit specifying a default value or use the special value {@link Parameters#NULL_VALUE} - * for positional parameters of type {@code Optional} that will result in the {@code Optional.empty()} * value being assigned when the positional parameters is not specified on the command line.

* @return a String that (after type conversion) will be used as the value for this positional parameter if no value was specified on the command line * @since 3.2 */ String defaultValue() default "__no_default_value__"; /** Use this attribute to control for a specific positional parameter whether its default value should be shown in the usage * help message. If not specified, the default value is only shown when the {@link Command#showDefaultValues()} * is set {@code true} on the command. Use this attribute to specify whether the default value * for this specific positional parameter should always be shown or never be shown, regardless of the command setting. *

Note that picocli 3.2 allows {@linkplain #description() embedding default values} by specifying the variable * {@code ${DEFAULT-VALUE}} anywhere in the description that ignores this setting.

* @return whether this positional parameter's default value should be shown in the usage help message */ Help.Visibility showDefaultValue() default Help.Visibility.ON_DEMAND; /** Use this attribute to specify an {@code Iterable} class that generates completion candidates for * this positional parameter. For map fields, completion candidates should be in {@code key=value} form. *

* Completion candidates are used in bash completion scripts generated by the {@code picocli.AutoComplete} class. * Unfortunately, {@code picocli.AutoComplete} is not very good yet at generating completions for positional parameters. *

* * @return a class whose instances can iterate over the completion candidates for this positional parameter * @see picocli.CommandLine.IFactory * @since 3.2 */ Class> completionCandidates() default NoCompletionCandidates.class; /** * Set {@code interactive=true} if this positional parameter will prompt the end user for a value (like a password). * Only supported for single-value positional parameters (not arrays, collections or maps). * When running on Java 6 or greater and {@link Option#echo() echo = false} (the default), * this will use the {@link Console#readPassword()} API to get a value without echoing input to the console, * otherwise it will simply read a value from {@code System.in}. * @return whether this positional parameter prompts the end user for a value to be entered on the command line * @since 3.5 */ boolean interactive() default false; /** Use this attribute to control whether user input for an interactive positional parameter is echoed to the console or not. * If {@code echo = true}, the user input is echoed to the console. * This attribute is ignored when {@code interactive = false} (the default). * @return whether the user input for an interactive positional parameter should be echoed to the console or not * @see PositionalParamSpec#echo() * @since 4.6 */ boolean echo() default false; /** Use this attribute to customize the text displayed to the end user for an interactive positional parameter when asking for user input. * When omitted, the displayed text is derived from the positional parameter's * position (index) and the first description line. * This attribute is ignored when {@code interactive = false} (the default). * @return the text to display to the end user for an interactive positional parameter when asking for user input * @see PositionalParamSpec#prompt() * @since 4.6 */ String prompt() default ""; /** ResourceBundle key for this option. If not specified, (and a ResourceBundle {@linkplain Command#resourceBundle() exists for this command}) an attempt * is made to find the positional parameter description using {@code paramLabel() + "[" + index() + "]"} as key. * * @see PositionalParamSpec#description() * @since 3.6 */ String descriptionKey() default ""; /** Determines on which command(s) this positional parameter exists: on this command only (the default), or * whether this is a "global" parameter that is applied to this command and all subcommands, sub-subcommands, etc. * @since 4.3 */ ScopeType scope() default ScopeType.LOCAL; /** * Optionally specify a custom {@code IParameterConsumer} to temporarily suspend picocli's parsing logic * and process one or more command line arguments in a custom manner. * @since 4.0 */ Class parameterConsumer() default NullParameterConsumer.class; /** For positional parameters of type Map, setting the {@code mapFallbackValue} to any value allows end user * to specify key-only parameters for this parameter. For example, {@code key} instead of {@code key=value}. *

The value specified in this annotation is the value that is put into the Map for the user-specified key. * Use the special value {@link Parameters#NULL_VALUE} to specify {@code null} - * for maps of type {@code Map>} that will result in {@code Optional.empty()} * values in the map when only the key is specified.

*

If no {@code mapFallbackValue} is set, key-only Map parameters like {@code -Dkey} * are considered invalid user input and cause a {@link ParameterException} to be thrown.

* @see ArgSpec#mapFallbackValue() * @since 4.6 */ String mapFallbackValue() default ArgSpec.UNSPECIFIED; /** Returns the preprocessor for this positional parameter. * @see IParameterPreprocessor * @since 4.6 */ Class preprocessor() default NoOpParameterPreprocessor.class; } /** *

* Fields annotated with {@code @ParentCommand} will be initialized with the parent command of the current subcommand. * If the current command does not have a parent command, this annotation has no effect. *

* Parent commands often define options that apply to all the subcommands. * This annotation offers a convenient way to inject a reference to the parent command into a subcommand, so the * subcommand can access its parent options. For example: *

     * @Command(name = "top", subcommands = Sub.class)
     * class Top implements Runnable {
     *
     *     @Option(names = {"-d", "--directory"}, description = "this option applies to all subcommands")
     *     File baseDirectory;
     *
     *     public void run() { System.out.println("Hello from top"); }
     * }
     *
     * @Command(name = "sub")
     * class Sub implements Runnable {
     *
     *     @ParentCommand
     *     private Top parent;
     *
     *     public void run() {
     *         System.out.println("Subcommand: parent command 'directory' is " + parent.baseDirectory);
     *     }
     * }
     * 
* @since 2.2 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface ParentCommand { } /** * Fields annotated with {@code @Unmatched} will be initialized with the list of unmatched command line arguments, if any. * If this annotation is found, picocli automatically sets {@linkplain CommandLine#setUnmatchedArgumentsAllowed(boolean) unmatchedArgumentsAllowed} to {@code true}. * @see CommandLine#isUnmatchedArgumentsAllowed() * @since 3.0 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Unmatched { } /** *

* Fields annotated with {@code @Mixin} are "expanded" into the current command: {@link Option @Option} and * {@link Parameters @Parameters} in the mixin class are added to the options and positional parameters of this command. * A {@link DuplicateOptionAnnotationsException} is thrown if any of the options in the mixin has the same name as * an option in this command. *

* The {@code Mixin} annotation provides a way to reuse common options and parameters without subclassing. For example: *

     * @Command(name="HelloWorld")
     * class HelloWorld implements Runnable {
     *
     *     // adds the --help and --version options to this command
     *     @Mixin
     *     private HelpOptions options = new HelpOptions();
     *
     *     @Option(names = {"-u", "--userName"}, required = true, description = "The user name")
     *     String userName;
     *
     *     public void run() { System.out.println("Hello, " + userName); }
     * }
     *
     * // Common reusable help options.
     * class HelpOptions {
     *
     *     @Option(names = { "-h", "--help"}, usageHelp = true, description = "Display this help and exit")
     *     private boolean help;
     *
     *     @Option(names = { "-V", "--version"}, versionHelp = true, description = "Display version info and exit")
     *     private boolean versionHelp;
     * }
     * 
* @since 3.0 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.PARAMETER}) public @interface Mixin { /** Optionally specify a name that the mixin object can be retrieved with from the {@code CommandSpec}. * If not specified the name of the annotated field is used. * @return a String to register the mixin object with, or an empty String if the name of the annotated field should be used */ String name() default ""; } /** * Fields annotated with {@code @Spec} will be initialized with the {@code CommandSpec} for the command the field is part of. Example usage: *
     * class InjectSpecExample implements Runnable {
     *     @Spec CommandSpec commandSpec;
     *     //...
     *     public void run() {
     *         // do something with the injected objects
     *     }
     * }
     * 
* @since 3.2 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD}) public @interface Spec { /** Identifies what kind of {@code CommandSpec} should be injected. * @since 4.3.0 */ enum Target { /** Injects the {@code CommandSpec} of the command where this {@code @Spec}-annotated program element is declared. */ SELF, /** Injects the {@code CommandSpec} of the "mixee" command that receives the options and other command elements defined here, * or {@code null} if this commands is not {@linkplain Mixin mixed into} another command. * The "mixee" command has a {@code @Mixin}-annotated program element with the type of the class where this {@code @Spec}-annotated program element is declared. */ MIXEE} /** Whether to inject the {@code CommandSpec} of this command (the default) or the {@code CommandSpec} * of the "mixee" command that receives the options and other command elements defined here. * @see Mixin * @since 4.3.0 */ Target value() default Target.SELF; } /** *

Annotate your class with {@code @Command} when you want more control over the format of the generated help * message. From 3.6, methods can also be annotated with {@code @Command}, where the method parameters define the * command options and positional parameters. *

     * @Command(name              = "Encrypt", mixinStandardHelpOptions = true,
     *        description         = "Encrypt FILE(s), or standard input, to standard output or to the output file.",
     *        version             = "Encrypt version 1.0",
     *        footer              = "Copyright (c) 2017",
     *        exitCodeListHeading = "Exit Codes:%n",
     *        exitCodeList        = { " 0:Successful program execution.",
     *                                "64:Invalid input: an unknown option or invalid parameter was specified.",
     *                                "70:Execution exception: an exception occurred while executing the business logic."}
     *        )
     * public class Encrypt {
     *     @Parameters(paramLabel = "FILE", description = "Any number of input files")
     *     private List<File> files = new ArrayList<File>();
     *
     *     @Option(names = { "-o", "--out" }, description = "Output file (default: print to console)")
     *     private File outputFile;
     *
     *     @Option(names = { "-v", "--verbose"}, description = "Verbose mode. Helpful for troubleshooting. Multiple -v options increase the verbosity.")
     *     private boolean[] verbose;
     * }
*

* The structure of a help message looks like this: *

    *
  • [header]
  • *
  • [synopsis]: {@code Usage: [OPTIONS] [FILE...]}
  • *
  • [description]
  • *
  • [parameter list]: {@code [FILE...] Any number of input files}
  • *
  • [option list]: {@code -h, --help prints this help message and exits}
  • *
  • [exit code list]
  • *
  • [footer]
  • *
*/ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.LOCAL_VARIABLE, ElementType.FIELD, ElementType.PACKAGE, ElementType.METHOD}) public @interface Command { /** Program name to show in the synopsis. If omitted, {@code "
"} is used. * For {@linkplain #subcommands() declaratively added} subcommands, this attribute is also used * by the parser to recognize subcommands in the command line arguments. * @return the program name to show in the synopsis * @see CommandSpec#name() * @see Help#commandName() */ String name() default CommandSpec.DEFAULT_COMMAND_NAME; /** Alternative command names by which this subcommand is recognized on the command line. * @return one or more alternative command names * @since 3.1 */ String[] aliases() default {}; /** A list of classes to instantiate and register as subcommands. When registering subcommands declaratively * like this, you don't need to call the {@link CommandLine#addSubcommand(String, Object)} method. For example, this: *
         * @Command(subcommands = {
         *         GitStatus.class,
         *         GitCommit.class,
         *         GitBranch.class })
         * public class Git { ... }
         *
         * CommandLine commandLine = new CommandLine(new Git());
         * 
is equivalent to this: *
         * // alternative: programmatically add subcommands.
         * // NOTE: in this case there should be no `subcommands` attribute on the @Command annotation.
         * @Command public class Git { ... }
         *
         * CommandLine commandLine = new CommandLine(new Git())
         *         .addSubcommand("status",   new GitStatus())
         *         .addSubcommand("commit",   new GitCommit())
         *         .addSubcommand("branch",   new GitBranch());
         * 
* Applications may be interested in the following built-in commands in picocli * that can be used as subcommands: *
    *
  • {@link HelpCommand} - a {@code help} subcommand that prints help on the following or preceding command
  • *
  • {@link AutoComplete.GenerateCompletion} - a {@code generate-completion} subcommand that prints a Bash/ZSH completion script for its parent command, so that clients can install autocompletion in one line by running {@code source <(parent-command generate-completion)} in the shell
  • *
* @return the declaratively registered subcommands of this command, or an empty array if none * @see CommandLine#addSubcommand(String, Object) * @see HelpCommand * @since 0.9.8 */ Class[] subcommands() default {}; /** Returns whether the subcommands of this command are repeatable, that is, whether such subcommands can * occur multiple times and may be followed by sibling commands instead of only by child commands of the subcommand. * @since 4.2 */ boolean subcommandsRepeatable() default false; /** Specify whether methods annotated with {@code @Command} should be registered as subcommands of their * enclosing {@code @Command} class. * The default is {@code true}. For example: *
         * @Command
         * public class Git {
         *     @Command
         *     void status() { ... }
         * }
         *
         * CommandLine git = new CommandLine(new Git());
         * 
is equivalent to this: *
         * // don't add command methods as subcommands automatically
         * @Command(addMethodSubcommands = false)
         * public class Git {
         *     @Command
         *     void status() { ... }
         * }
         *
         * // add command methods as subcommands programmatically
         * CommandLine git = new CommandLine(new Git());
         * CommandLine status = new CommandLine(CommandLine.getCommandMethods(Git.class, "status").get(0));
         * git.addSubcommand("status", status);
         * 
* @return whether methods annotated with {@code @Command} should be registered as subcommands * @see CommandLine#addSubcommand(String, Object) * @see CommandLine#getCommandMethods(Class, String) * @see CommandSpec#addMethodSubcommands() * @since 3.6.0 */ boolean addMethodSubcommands() default true; /** String that separates options from option parameters. Default is {@code "="}. Spaces are also accepted. * @return the string that separates options from option parameters, used both when parsing and when generating usage help * @see CommandLine#setSeparator(String) */ String separator() default "="; /** Version information for this command, to print to the console when the user specifies an * {@linkplain Option#versionHelp() option} to request version help. Each element of the array is rendered on a separate line. *

May contain embedded {@linkplain java.util.Formatter format specifiers} like {@code %n} line separators. Literal percent {@code '%'} characters must be escaped with another {@code %}.

*

This is not part of the usage help message.

* * @return a string or an array of strings with version information about this command (each string in the array is displayed on a separate line). * @since 0.9.8 * @see CommandLine#printVersionHelp(PrintStream) */ String[] version() default {}; /** Class that can provide version information dynamically at runtime. An implementation may return version * information obtained from the JAR manifest, a properties file or some other source. * @return a Class that can provide version information dynamically at runtime * @since 2.2 */ Class versionProvider() default NoVersionProvider.class; /** * Adds the standard {@code -h} and {@code --help} {@linkplain Option#usageHelp() usageHelp} options and {@code -V} * and {@code --version} {@linkplain Option#versionHelp() versionHelp} options to the options of this command. *

* Note that if no {@link #version()} or {@link #versionProvider()} is specified, the {@code --version} option will not print anything. *

* For {@linkplain #resourceBundle() internationalization}: the help option has {@code descriptionKey = "mixinStandardHelpOptions.help"}, * and the version option has {@code descriptionKey = "mixinStandardHelpOptions.version"}. *

* @return whether the auto-help mixin should be added to this command * @since 3.0 */ boolean mixinStandardHelpOptions() default false; /** Set this attribute to {@code true} if this subcommand is a help command, and required options and positional * parameters of the parent command should not be validated. If a subcommand marked as {@code helpCommand} is * specified on the command line, picocli will not validate the parent arguments (so no "missing required * option" errors) and the {@link CommandLine#printHelpIfRequested(List, PrintStream, PrintStream, Help.Ansi)} method will return {@code true}. * @return {@code true} if this subcommand is a help command and picocli should not check for missing required * options and positional parameters on the parent command * @since 3.0 */ boolean helpCommand() default false; /** Set the heading preceding the header section. *

May contain embedded {@linkplain java.util.Formatter format specifiers} like {@code %n} line separators. Literal percent {@code '%'} characters must be escaped with another {@code %}.

* @return the heading preceding the header section * @see UsageMessageSpec#headerHeading() * @see Help#headerHeading(Object...) */ String headerHeading() default ""; /** Optional summary description of the command, shown before the synopsis. Each element of the array is rendered on a separate line. *

May contain embedded {@linkplain java.util.Formatter format specifiers} like {@code %n} line separators. Literal percent {@code '%'} characters must be escaped with another {@code %}.

* @return summary description of the command * @see UsageMessageSpec#header() * @see Help#header(Object...) */ String[] header() default {}; /** Set the heading preceding the synopsis text. The default heading is {@code "Usage: "} (without a line break between the heading and the synopsis text). *

May contain embedded {@linkplain java.util.Formatter format specifiers} like {@code %n} line separators. Literal percent {@code '%'} characters must be escaped with another {@code %}.

* @return the heading preceding the synopsis text * @see Help#synopsisHeading(Object...) */ String synopsisHeading() default "Usage: "; /** Specify {@code true} to generate an abbreviated synopsis like {@code "
[OPTIONS] [PARAMETERS...] [COMMAND]"}. * By default, a detailed synopsis with individual option names and parameters is generated. * @return whether the synopsis should be abbreviated * @see Help#abbreviatedSynopsis() * @see Help#detailedSynopsis(int, Comparator, boolean) */ boolean abbreviateSynopsis() default false; /** Specify one or more custom synopsis lines to display instead of an auto-generated synopsis. Each element of the array is rendered on a separate line. *

May contain embedded {@linkplain java.util.Formatter format specifiers} like {@code %n} line separators. Literal percent {@code '%'} characters must be escaped with another {@code %}.

* @return custom synopsis text to replace the auto-generated synopsis * @see Help#customSynopsis(Object...) */ String[] customSynopsis() default {}; /** * Specify the String to show in the synopsis for the subcommands of this command. The default is * {@code "[COMMAND]"}. Ignored if this command has no {@linkplain #subcommands() subcommands}. * @since 4.0 */ String synopsisSubcommandLabel() default "[COMMAND]"; /** Set the heading preceding the description section. *

May contain embedded {@linkplain java.util.Formatter format specifiers} like {@code %n} line separators. Literal percent {@code '%'} characters must be escaped with another {@code %}.

* @return the heading preceding the description section * @see Help#descriptionHeading(Object...) */ String descriptionHeading() default ""; /** Optional text to display between the synopsis line(s) and the list of options. Each element of the array is rendered on a separate line. *

May contain embedded {@linkplain java.util.Formatter format specifiers} like {@code %n} line separators. Literal percent {@code '%'} characters must be escaped with another {@code %}.

* @return description of this command * @see Help#description(Object...) */ String[] description() default {}; /** Set the heading preceding the parameters list. *

May contain embedded {@linkplain java.util.Formatter format specifiers} like {@code %n} line separators. Literal percent {@code '%'} characters must be escaped with another {@code %}.

* @return the heading preceding the parameters list * @see Help#parameterListHeading(Object...) */ String parameterListHeading() default ""; /** Set the heading preceding the options list. *

May contain embedded {@linkplain java.util.Formatter format specifiers} like {@code %n} line separators. Literal percent {@code '%'} characters must be escaped with another {@code %}.

* @return the heading preceding the options list * @see Help#optionListHeading(Object...) */ String optionListHeading() default ""; /** Specify {@code false} to show Options in declaration order in the option list of the usage help message (or to sort options by their {@linkplain Option#order() order index} if set). * Note that picocli cannot reliably detect declaration order in commands that have both {@code @Option}-annotated methods and {@code @Option}-annotated fields. * The default ({@code true}) is to sort alphabetically. * @return whether options should be shown in alphabetic order. */ boolean sortOptions() default true; /** Specify {@code false} to show options in declaration order in the synopsis of the usage help message (or to sort options by their {@linkplain Option#order() order index} if set). * Note that picocli cannot reliably detect declaration order in commands that have both {@code @Option}-annotated methods and {@code @Option}-annotated fields. * The default ({@code true}) is to sort alphabetically. * @return whether options in the synopsis should be shown in alphabetic order. * @since 4.7.6-SNAPSHOT */ boolean sortSynopsis() default true; /** Prefix required options with this character in the options list. The default is no marker: the synopsis * indicates which options and parameters are required. * @return the character to show in the options list to mark required options */ char requiredOptionMarker() default ' '; /** Class that can provide default values dynamically at runtime. An implementation may return default * value obtained from a configuration file like a properties file or some other source. *

* Applications may be interested in the {@link PropertiesDefaultProvider} built-in default provider * that allows end users to maintain their own default values for options and positional parameters, * which may override the defaults that are hard-coded in the application. *

* @return a Class that can provide default values dynamically at runtime * @since 3.6 */ Class defaultValueProvider() default NoDefaultProvider.class; /** Specify {@code true} to show default values in the description column of the options list (except for * boolean options). False by default. *

Note that picocli 3.2 allows {@linkplain Option#description() embedding default values} anywhere in the * option or positional parameter description that ignores this setting.

* @return whether the default values for options and parameters should be shown in the description column */ boolean showDefaultValues() default false; /** Specify {@code true} to show a {@code [@...]} entry * in the synopsis and parameter list of the usage help message. * (The entry is not shown if {@linkplain CommandLine#isExpandAtFiles() expanding parameter files} is disabled.) * @since 4.2 */ boolean showAtFileInUsageHelp() default false; /** Specify {@code true} to show a {@code [--]} "End of options" entry * in the synopsis and option list of the usage help message. * @since 4.3 */ boolean showEndOfOptionsDelimiterInUsageHelp() default false; /** Set the heading preceding the subcommands list. The default heading is {@code "Commands:%n"} (with a line break at the end). *

May contain embedded {@linkplain java.util.Formatter format specifiers} like {@code %n} line separators. Literal percent {@code '%'} characters must be escaped with another {@code %}.

* @return the heading preceding the subcommands list * @see Help#commandListHeading(Object...) */ String commandListHeading() default "Commands:%n"; /** Set the heading preceding the footer section. *

May contain embedded {@linkplain java.util.Formatter format specifiers} like {@code %n} line separators. Literal percent {@code '%'} characters must be escaped with another {@code %}.

* @return the heading preceding the footer section * @see Help#footerHeading(Object...) */ String footerHeading() default ""; /** Optional text to display after the list of options. Each element of the array is rendered on a separate line. *

May contain embedded {@linkplain java.util.Formatter format specifiers} like {@code %n} line separators. Literal percent {@code '%'} characters must be escaped with another {@code %}.

* @return text to display after the list of options * @see Help#footer(Object...) */ String[] footer() default {}; /** * Set {@code hidden=true} if this command should not be included in the list of commands in the usage help of the parent command. * @return whether this command should be excluded from the usage message * @since 3.0 */ boolean hidden() default false; /** Set the base name of the ResourceBundle to find option and positional parameters descriptions, as well as * usage help message sections and section headings.

See {@link Messages} for more details and an example.

* @return the base name of the ResourceBundle for usage help strings * @see ArgSpec#messages() * @see UsageMessageSpec#messages() * @see CommandSpec#resourceBundle() * @see CommandLine#setResourceBundle(ResourceBundle) * @since 3.6 */ String resourceBundle() default ""; /** Set the {@link UsageMessageSpec#width(int) usage help message width}. The default is 80. * @see UsageMessageSpec#width() * @since 3.7 */ int usageHelpWidth() default 80; /** If {@code true}, picocli will attempt to detect the terminal width and adjust the usage help message accordingly. * End users may enable this by setting system property {@code "picocli.usage.width"} to {@code AUTO}, * and may disable this by setting this system property to a {@linkplain UsageMessageSpec#width() numeric value}. * This feature requires Java 7 or greater. The default is {@code false} * @see UsageMessageSpec#autoWidth() * @since 4.0 */ boolean usageHelpAutoWidth() default false; /** Exit code for successful termination. {@value picocli.CommandLine.ExitCode#OK} by default. * @see #execute(String...) * @since 4.0 */ int exitCodeOnSuccess() default ExitCode.OK; /** Exit code for successful termination after printing usage help on user request. {@value picocli.CommandLine.ExitCode#OK} by default. * @see #execute(String...) * @since 4.0 */ int exitCodeOnUsageHelp() default ExitCode.OK; /** Exit code for successful termination after printing version help on user request. {@value picocli.CommandLine.ExitCode#OK} by default. * @see #execute(String...) * @since 4.0 */ int exitCodeOnVersionHelp() default ExitCode.OK; /** Exit code for command line usage error. {@value picocli.CommandLine.ExitCode#USAGE} by default. * @see #execute(String...) * @since 4.0 */ int exitCodeOnInvalidInput() default ExitCode.USAGE; /** Exit code signifying that an exception occurred when invoking the Runnable, Callable or Method user object of a command. * {@value picocli.CommandLine.ExitCode#SOFTWARE} by default. * @see #execute(String...) * @since 4.0 */ int exitCodeOnExecutionException() default ExitCode.SOFTWARE; /** Set the heading preceding the exit codes section, may contain {@code "%n"} line separators. {@code ""} (empty string) by default. * @see Help#exitCodeListHeading(Object...) * @since 4.0 */ String exitCodeListHeading() default ""; /** Set the values to be displayed in the exit codes section as a list of {@code "key:value"} pairs: * keys are exit codes, values are descriptions. Descriptions may contain {@code "%n"} line separators. *

For example:

*
         * @Command(exitCodeListHeading = "Exit Codes:%n",
         *          exitCodeList = { " 0:Successful program execution.",
         *                           "64:Invalid input: an unknown option or invalid parameter was specified.",
         *                           "70:Execution exception: an exception occurred while executing the business logic."})
         * 
* @since 4.0 */ String[] exitCodeList() default {}; /** Returns whether subcommands inherit their attributes from this parent command. * @since 4.6 */ ScopeType scope() default ScopeType.LOCAL; /** Returns the model transformer for this command. * @since 4.6 */ Class modelTransformer() default NoOpModelTransformer.class; /** Returns the preprocessor for this command. * @see IParameterPreprocessor * @since 4.6 */ Class preprocessor() default NoOpParameterPreprocessor.class; } /** A {@code Command} may define one or more {@code ArgGroups}: a group of options, positional parameters or a mixture of the two. * Groups can be used to: *
    *
  • define mutually exclusive arguments. By default, options and positional parameters * in a group are mutually exclusive. This can be controlled with the {@link #exclusive() exclusive} attribute. * Picocli will throw a {@link MutuallyExclusiveArgsException} if the command line contains multiple arguments that are mutually exclusive.
  • *
  • define a set of arguments that must co-occur. Set {@link #exclusive() exclusive = false} * to define a group of options and positional parameters that must always be specified together. * Picocli will throw a {@link MissingParameterException MissingParameterException} if not all the options and positional parameters in a co-occurring group are specified together.
  • *
  • create an option section in the usage help message. * To be shown in the usage help message, a group needs to have a {@link #heading() heading} (which may come from a {@linkplain #headingKey() resource bundle}). * Groups without a heading are only used for validation. * Set {@link #validate() validate = false} for groups whose purpose is only to customize the usage help message.
  • *
  • define composite repeating argument groups. Groups may contain other groups to create composite groups.
  • *
*

Groups may be optional ({@code multiplicity = "0..1"}), required ({@code multiplicity = "1"}), or repeating groups ({@code multiplicity = "0..*"} or {@code multiplicity = "1..*"}). * For a group of mutually exclusive arguments, making the group required means that one of the arguments in the group must appear on the command line, or a {@link MissingParameterException MissingParameterException} is thrown. * For a group of co-occurring arguments, all arguments in the group must appear on the command line. *

*

Groups can be composed for validation purposes:

*
    *
  • When the parent group is mutually exclusive, only one of the subgroups may be present.
  • *
  • When the parent group is a co-occurring group, all subgroups must be present.
  • *
  • When the parent group is required, at least one subgroup must be present.
  • *
*

* Below is an example of an {@code ArgGroup} defining a set of dependent options that must occur together. * All options are required within the group, while the group itself is optional:

*
     * public class DependentOptions {
     *     @ArgGroup(exclusive = false, multiplicity = "0..1")
     *     Dependent group;
     *
     *     static class Dependent {
     *         @Option(names = "-a", required = true) int a;
     *         @Option(names = "-b", required = true) int b;
     *         @Option(names = "-c", required = true) int c;
     *     }
     * }
* @see ArgGroupSpec * @since 4.0 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) public @interface ArgGroup { /** The heading of this group, used when generating the usage documentation. * When neither a {@link #heading() heading} nor a {@link #headingKey() headingKey} are specified, * this group is used for validation only and does not change the usage help message. */ String heading() default "__no_heading__"; /** ResourceBundle key for this group's usage help message section heading. * When neither a {@link #heading() heading} nor a {@link #headingKey() headingKey} are specified, * this group is used for validation only and does not change the usage help message. */ String headingKey() default "__no_heading_key__"; /** Determines whether this is a mutually exclusive group; {@code true} by default. * If {@code false}, this is a co-occurring group. Ignored if {@link #validate()} is {@code false}. */ boolean exclusive() default true; /** Determines how often this group can be specified on the command line; {@code "0..1"} (optional) by default. * For a group of mutually exclusive arguments, making the group required {@code multiplicity = "1"} means that * one of the arguments in the group must appear on the command line, or a MissingParameterException is thrown. * For a group of co-occurring arguments, making the group required means that all arguments in the group must appear on the command line. * Ignored if {@link #validate()} is {@code false}. */ String multiplicity() default "0..1"; /** Determines whether picocli should validate the rules of this group ({@code true} by default). * For a mutually exclusive group validation means verifying that no more than one elements of the group is specified on the command line; * for a co-occurring group validation means verifying that all elements of the group are specified on the command line. * Set {@link #validate() validate = false} for groups whose purpose is only to customize the usage help message. * @see #multiplicity() * @see #heading() */ boolean validate() default true; /** Determines the position in the options list in the usage help message at which this group should be shown. * Groups with a lower number are shown before groups with a higher number. * This attribute is only honored for groups that have a {@link #heading() heading} (or a {@link #headingKey() headingKey} with a non-{@code null} resource bundle value).*/ int order() default -1; } /** *

* When parsing command line arguments and initializing * fields annotated with {@link Option @Option} or {@link Parameters @Parameters}, * String values can be converted to any type for which a {@code ITypeConverter} is registered. *

* This interface defines the contract for classes that know how to convert a String into some domain object. * Custom converters can be registered with the {@link #registerConverter(Class, ITypeConverter)} method. *

* Java 8 lambdas make it easy to register custom type converters: *

*
     * commandLine.registerConverter(java.nio.file.Path.class, s -> java.nio.file.Paths.get(s));
     * commandLine.registerConverter(java.time.Duration.class, s -> java.time.Duration.parse(s));
*

* Built-in type converters are pre-registered for the following java 1.5 types: *

*
    *
  • all primitive types
  • *
  • all primitive wrapper types: Boolean, Byte, Character, Double, Float, Integer, Long, Short
  • *
  • any enum
  • *
  • java.io.File
  • *
  • java.math.BigDecimal
  • *
  • java.math.BigInteger
  • *
  • java.net.InetAddress
  • *
  • java.net.URI
  • *
  • java.net.URL
  • *
  • java.nio.charset.Charset
  • *
  • java.sql.Time
  • *
  • java.util.Date
  • *
  • java.util.UUID
  • *
  • java.util.regex.Pattern
  • *
  • StringBuilder
  • *
  • CharSequence
  • *
  • String
  • *
* @param the type of the object that is the result of the conversion */ public interface ITypeConverter { /** * Converts the specified command line argument value to some domain object. * @param value the command line argument String value * @return the resulting domain object * @throws Exception an exception detailing what went wrong during the conversion. * Any exception thrown from this method will be caught and shown to the end user. * An example error message shown to the end user could look something like this: * {@code Invalid value for option '--some-option': cannot convert 'xxxinvalidinput' to SomeType (java.lang.IllegalArgumentException: Invalid format: must be 'x:y:z' but was 'xxxinvalidinput')} * @throws TypeConversionException throw this exception to have more control over the error * message that is shown to the end user when type conversion fails. * An example message shown to the user could look like this: * {@code Invalid value for option '--some-option': Invalid format: must be 'x:y:z' but was 'xxxinvalidinput'} */ K convert(String value) throws Exception; } /** * Provides version information for a command. Commands may configure a provider with the * {@link Command#versionProvider()} annotation attribute. * @since 2.2 */ public interface IVersionProvider { /** * Returns version information for a command. * @return version information (each string in the array is displayed on a separate line) * @throws Exception an exception detailing what went wrong when obtaining version information */ String[] getVersion() throws Exception; } /** * Converter that can be used to signal to picocli that it should use the default converter. * This can be useful with maps: *
     *   class App {
     *       @Option(names = "-D", converter = {UseDefaultConverter.class, GenericValueConverter.class})
     *       Map<String, GenericValue<?>> values;
     *  }
     * 
* * The {@link #convert(String)} method of this class always throws an UnsupportedOperationException. * @since 4.7.6-SNAPSHOT */ public static final class UseDefaultConverter implements ITypeConverter { /** Always throws UnsupportedOperationException. * @throws UnsupportedOperationException always */ public Object convert(String value) throws Exception { throw new UnsupportedOperationException("This method should never be called."); } } private static class NoVersionProvider implements IVersionProvider { public String[] getVersion() throws Exception { throw new UnsupportedOperationException(); } } /** * Provides a way to modify how the command model is built. * This is useful for applications that need to modify the model dynamically depending on the runtime environment. *

* Commands may configure a model transformer using the * {@link Command#modelTransformer()} annotation attribute, or via the * {@link CommandSpec#modelTransformer(IModelTransformer)} programmatic API. *

* Model transformers are invoked only once, after the full command hierarchy is constructed. * @since 4.6 */ public interface IModelTransformer { /** * Given an original CommandSpec, return the object that should be used * instead. Implementors may modify the specified CommandSpec and return it, * or create a full or partial copy of the specified CommandSpec, and return * that, or even return a completely new CommandSpec. *

* Implementors are free to add or remove options, positional parameters, * subcommands or modify the command in any other way. *

* This method is called once, after the full command hierarchy is * constructed, and before any command line arguments are parsed. *

* @return the CommandSpec to use instead of the specified one */ CommandSpec transform(CommandSpec commandSpec); } private static class NoOpModelTransformer implements IModelTransformer { public CommandSpec transform(CommandSpec commandSpec) { return commandSpec; } } /** * Provides default value for a command. Commands may configure a provider with the * {@link Command#defaultValueProvider()} annotation attribute. * @since 3.6 */ public interface IDefaultValueProvider { /** Returns the default value for an option or positional parameter or {@code null}. * The returned value is converted to the type of the option/positional parameter * via the same type converter used when populating this option/positional * parameter from a command line argument. * @param argSpec the option or positional parameter, never {@code null} * @return the default value for the option or positional parameter, or {@code null} if * this provider has no default value for the specified option or positional parameter * @throws Exception when there was a problem obtaining the default value */ String defaultValue(ArgSpec argSpec) throws Exception; } private static class NoDefaultProvider implements IDefaultValueProvider { public String defaultValue(ArgSpec argSpec) { throw new UnsupportedOperationException(); } } /** * Options or positional parameters can be assigned a {@code IParameterConsumer} that implements * custom logic to process the parameters for this option or this position. * When an option or positional parameter with a custom {@code IParameterConsumer} is matched on the * command line, picocli's internal parser is temporarily suspended, and this object becomes * responsible for consuming and processing as many command line arguments as needed. *

This may be useful when passing through parameters to another command.

*

Example usage:

*
     * @Command(name = "find")
     * class Find {
     *     @Option(names = "-exec", parameterConsumer = Find.ExecParameterConsumer.class)
     *     List<String> list = new ArrayList<String>();
     *
     *     static class ExecParameterConsumer implements IParameterConsumer {
     *         public void consumeParameters(Stack<String> args, ArgSpec argSpec, CommandSpec commandSpec) {
     *             List<String> list = argSpec.getValue();
     *             while (!args.isEmpty()) {
     *                 String arg = args.pop();
     *                 list.add(arg);
     *
     *                 // `find -exec` semantics: stop processing after a ';' or '+' argument
     *                 if (";".equals(arg) || "+".equals(arg)) {
     *                     break;
     *                 }
     *             }
     *         }
     *     }
     * }
*

If this interface does not meet your requirements, you may have a look at the more powerful * and flexible {@link IParameterPreprocessor} interface introduced with picocli 4.6.

* @see Option#parameterConsumer() * @see Parameters#parameterConsumer() * @since 4.0 */ public interface IParameterConsumer { /** * Consumes as many of the specified command line arguments as needed by popping them off * the specified Stack. Implementors are free to ignore the {@linkplain ArgSpec#arity() arity} * of the option or positional parameter, they are free to consume arguments that would * normally be matched as other options of the command, and they are free to consume * arguments that would normally be matched as an end-of-options delimiter. *

Implementors are responsible for saving the consumed values; * if the user object of the option or positional parameter is a Collection * or a Map, a common approach would be to obtain the current instance via the * {@link ArgSpec#getValue()}, and add to this instance. If the user object is an * array, the implementation would need to create a new array that contains the * old values as well as the newly consumed values, and store this array in the * user object via the {@link ArgSpec#setValue(Object)}. *

* If the user input is invalid, implementations should throw a {@link ParameterException} * with a message to display to the user. *

* When this method returns, the picocli parser will process the remaining arguments on the Stack. *

* @param args the command line arguments * @param argSpec the option or positional parameter for which to consume command line arguments * @param commandSpec the command that the option or positional parameter belongs to * @throws ParameterException if the user input is invalid */ void consumeParameters(Stack args, ArgSpec argSpec, CommandSpec commandSpec); } private static class NullParameterConsumer implements IParameterConsumer { public void consumeParameters(Stack args, ArgSpec argSpec, CommandSpec commandSpec) { throw new UnsupportedOperationException(); } } /** * Options, positional parameters and commands can be assigned a {@code IParameterPreprocessor} that * implements custom logic to preprocess the parameters for this option, position or command. * When an option, positional parameter or command with a custom {@code IParameterPreprocessor} is matched * on the command line, picocli's internal parser is temporarily suspended, and this custom logic is invoked. *

* This custom logic may completely replace picocli's internal parsing for this option, positional parameter * or command, or it may do some preprocessing before picocli's internal parsing is resumed for this option, * positional parameter or command. *

* The "preprocessing" can include modifying the stack of command line parameters, or modifying the model. *

*

This may be useful when disambiguating input for commands that have both a positional parameter and an * option with an optional parameter.

*

Example usage:

*
     * @Command(name = "edit")
     * class Edit {
     *     @Parameters(index = "0", description = "The file to edit.")
     *     File file;
     *
     *     enum Editor { defaultEditor, eclipse, idea, netbeans }
     *
     *     @Option(names = "--open", arity = "0..1", preprocessor = Edit.MyPreprocessor.class,
     *         description = {
     *             "Optionally specify the editor to use; if omitted the default editor is used. ",
     *             "Example: edit --open=idea FILE opens IntelliJ IDEA (notice the '=' separator)",
     *             "         edit --open FILE opens the specified file in the default editor"
     *         })
     *     Editor editor = Editor.defaultEditor;
     *
     *     static class MyPreprocessor implements IParameterPreprocessor {
     *         public boolean preprocess(Stack<String> args, CommandSpec commandSpec, ArgSpec argSpec, Map<String, Object> info) {
     *             // we need to decide whether the next arg is the file to edit or the name of the editor to use...
     *             if (" ".equals(info.get("separator"))) { // parameter was not attached to option
     *                 args.push(Editor.defaultEditor.name()); // act as if the user specified --open=defaultEditor
     *             }
     *             return false; // picocli's internal parsing is resumed for this option
     *         }
     *     }
     * }
* @see Option#preprocessor() * @see Parameters#preprocessor() * @since 4.6 */ public interface IParameterPreprocessor { /** * Called when either the command, option or positional parameter that has this preprocessor configured was * recognized by the picocli parser. *

Implementors are free to modify one or more of the specified command line arguments before they are * processed by the picocli parser (or by the option's {@link IParameterConsumer parameter consumer}, if one is specified). *

* Implementors may optionally consume one or more of the specified command line arguments: * a return value of {@code true} signals that the preprocessor consumed the parameter: * picocli should skip further processing of this option or positional parameter, * and the preprocessor implementation takes responsibility for assigning the * option or positional parameter a value. A return value of {@code false} means that picocli should * process the stack as usual for this option or positional parameter, and picocli is responsible for * assigning this option or positional parameter a value. *

* For a command, returning {@code true} signals that the preprocessor takes responsibility for parsing all * options and positional parameters for this command, and takes responsibility for validating constraints like * whether all required options and positional parameters were specified. * A return value of {@code false} means that picocli should * process the stack as usual for this command, and picocli is responsible for validation. * Command preprocessors can signal back to the picocli parser when they detect that the user requested version * information or usage help by putting a value of {@code true} in the specified * {@code info} map for keys {@code versionHelpRequested} or {@code usageHelpRequested}, respectively. *

* If the user input is invalid, implementations should throw a {@link ParameterException} * with a message to display to the user. *

* @param args the remaining command line arguments that follow the matched argument * (the matched argument is not on the stack anymore) * @param commandSpec the command or subcommand that was matched (if the specified {@code argSpec} is * {@code null}), or the command that the matched option or positional parameter belongs to * @param argSpec the option or positional parameter for which to pre-process command line arguments * (may be {@code null} when this method is called for a subcommand that was matched) * @param info a map containing additional information on the current parser state, * including whether the option parameter was attached to the option name with * a `=` separator, whether quotes have already been stripped off the option, etc. * Implementations may modify this map to communicate back to the picocli parser. * Supported values: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Supported values in the info Map
keyvalid valuestype
separator'' (empty string): attached without separator, ' ' (space): not attached, (any other string): option name was attached to option param with specified separatorjava.lang.String
negated{@code true}: the option or positional parameter is a {@linkplain Option#negatable() negated} option/parameter, {@code false}: the option or positional parameter is not a negated option/parameterjava.lang.Boolean
unquoted{@code true}: quotes surrounding the value have already been stripped off, {@code false}: quotes surrounding the value have not yet been stripped offjava.lang.Boolean
versionHelpRequested{@code true}: version help was requested, {@code false}: version help was not requestedjava.lang.Boolean
usageHelpRequested{@code true}: usage help was requested, {@code false}: usage help was not requestedjava.lang.Boolean
* @return true if the preprocessor consumed the parameter * and picocli should skip further processing of the stack for this option or positional parameter; * false if picocli should continue processing the stack for this option or positional parameter * @throws ParameterException if the user input is invalid */ boolean preprocess(Stack args, CommandSpec commandSpec, ArgSpec argSpec, Map info); } private static class NoOpParameterPreprocessor implements IParameterPreprocessor { public boolean preprocess(Stack args, CommandSpec commandSpec, ArgSpec argSpec, Map info) { return false; } public boolean equals(Object obj) { return obj instanceof NoOpParameterPreprocessor; } public int hashCode() { return NoOpParameterPreprocessor.class.hashCode() + 7; } } /** Determines the option name transformation of {@linkplain Option#negatable() negatable} boolean options. * Making an option negatable has two aspects: *
    *
  • the negative form recognized by the parser while parsing the command line
  • *
  • the documentation string showing both the positive and the negative form in the usage help message
  • *

* Additionally, this transformer controls which names of a negatable option are actually negatable: * for example, by default short options like {@code -v} do not have a negative form, even if the same option's * long form, {@code --verbose}, may have a negative form, {@code --no-verbose}. *

* @see RegexTransformer * @since 4.0 */ public interface INegatableOptionTransformer { /** Returns the negative form of the specified option name for the parser to recognize when parsing command line arguments. * @param optionName the option name to create a negative form for, for example {@code --force} * @param cmd the command that the option is part of * @return the negative form of the specified option name, for example {@code --no-force} */ String makeNegative(String optionName, CommandSpec cmd); /** Returns the documentation string to show in the synopsis and usage help message for the specified option. * The returned value should be concise and clearly suggest that both the positive and the negative form are valid option names * @param optionName the option name to create a documentation string for, for example {@code --force}, or {@code -XX:+