All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dev.jeka.core.tool.CommandLine Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2014-2024  the original author or authors.
 *
 * 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
 *
 *       https://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 dev.jeka.core.tool;

import dev.jeka.core.tool.CommandLine.Help.Ansi.IStyle;
import dev.jeka.core.tool.CommandLine.Help.Ansi.Style;
import dev.jeka.core.tool.CommandLine.Help.Ansi.Text;
import dev.jeka.core.tool.CommandLine.Model.*;
import dev.jeka.core.tool.CommandLine.ParseResult.GroupMatchContainer;

import java.io.*;
import java.lang.annotation.*;
import java.lang.reflect.Proxy;
import java.lang.reflect.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.*;
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 static dev.jeka.core.tool.CommandLine.Help.Column.Overflow.*;
import static java.util.Locale.ENGLISH;

/**
 * 

* 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 *

*/ 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 dev.jeka.core.tool.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 dev.jeka.core.tool.AutoComplete} class. * Unfortunately, {@code dev.jeka.core.tool.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:+