diff --git a/NGCC/.gitignore b/NGCC/.gitignore
new file mode 100644
index 0000000..ae3c172
--- /dev/null
+++ b/NGCC/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/NGCC/src/Exec.java b/NGCC/src/Exec.java
new file mode 100644
index 0000000..76dd5c4
--- /dev/null
+++ b/NGCC/src/Exec.java
@@ -0,0 +1,51 @@
+
+import commands.*;
+import picocli.CommandLine;
+
+public class Exec {
+
+ public static void main(String[] args) {
+
+ try {
+
+ if (args[0].contentEquals("-b") || args[0].contentEquals("--build")) {
+ CommandLine cmd = new CommandLine(new Build());
+ cmd.execute(args);
+
+ } else if (args[0].contentEquals("-r") || args[0].contentEquals("--read")) {
+ CommandLine cmd = new CommandLine(new Read());
+ cmd.execute(args);
+
+ } else if (args[0].contentEquals("-g") || args[0].contentEquals("--generate")) {
+ CommandLine cmd = new CommandLine(new Generate());
+ cmd.execute(args);
+
+ } else if (args[0].contentEquals("-p") || args[0].contentEquals("--produce")) {
+ CommandLine cmd = new CommandLine(new Produce());
+ cmd.execute(args);
+
+ } else if (args[0].contentEquals("-a") || args[0].contentEquals("--analyse")) {
+ CommandLine cmd = new CommandLine(new Analyse());
+ cmd.execute(args);
+
+ } else if (args[0].contentEquals("-e") || args[0].contentEquals("--evaluate")) {
+ CommandLine cmd = new CommandLine(new Evaluate());
+ cmd.execute(args);
+
+ } else if (args[0].contentEquals("--help")) {
+ CommandLine cmd = new CommandLine(new Help());
+ cmd.execute(args);
+
+ } else {
+ System.out.println(args[0] + " : command not found");
+ }
+
+
+ } catch (ArrayIndexOutOfBoundsException e) {
+ CommandLine cmd = new CommandLine(new Help());
+ System.out.println(cmd.execute(args));
+ }
+
+ }
+
+}
diff --git a/NGCC/src/commands/Analyse.java b/NGCC/src/commands/Analyse.java
new file mode 100644
index 0000000..f0382f7
--- /dev/null
+++ b/NGCC/src/commands/Analyse.java
@@ -0,0 +1,52 @@
+package commands;
+import java.util.concurrent.Callable;
+
+//import picocli.CommandLine;
+import picocli.CommandLine.*;
+
+
+@Command(
+ name = "analyse",
+ version = "Version 1.0",
+ sortOptions = false,
+ usageHelpWidth = 60,
+ header = " -- Nicely Generated and Corrected Copies -- \n",
+ footer = "\n Provided by IUT Info Nice S3T-G4",
+ description = "description"
+)
+
+
+public class Analyse implements Callable {
+
+ @Option(names= {"-a","--analyse"}, arity = "0", order = 1, description = "analyse mode")
+ boolean analyse;
+
+ @Option(names= {"-u"}, arity = "1", order = 2, description = "update mode")
+ int step;
+
+ @Option(names= {"-v"}, arity = "0..*", order = 3, defaultValue = "1", description ="verbose mode")
+ int vb_level;
+
+ @Option(names= {"-d"}, arity = "1", order = 4, defaultValue = "copies", description ="directory")
+ String directory;
+
+ @Parameters(arity = "0..1", defaultValue = "./source.txt", description ="source path")
+ String source_path;
+
+
+
+
+ @Override
+ public Void call() throws Exception {
+ if(analyse) {
+ System.out.println("Analyse mode activated ...");
+ System.out.println("Update : "+step);
+ System.out.println("Verbose : "+vb_level);
+ System.out.println("Directory : "+directory);
+ System.out.println("Source : "+source_path);
+ }
+
+ return null;
+
+ }
+}
diff --git a/NGCC/src/commands/Build.java b/NGCC/src/commands/Build.java
new file mode 100644
index 0000000..057fded
--- /dev/null
+++ b/NGCC/src/commands/Build.java
@@ -0,0 +1,51 @@
+package commands;
+import java.util.concurrent.Callable;
+
+//import picocli.CommandLine;
+import picocli.CommandLine.*;
+
+
+@Command(
+ name = "ngcc",
+ version = "Version 1.0",
+ sortOptions = false,
+ usageHelpWidth = 60,
+ header = " -- Nicely Generated and Corrected Copies -- \n",
+ footer = "\n Provided by IUT Info Nice S3T-G4",
+ description = "description"
+)
+
+
+public class Build implements Callable {
+
+ @Option(names= {"-b","--build"}, arity = "0", order = 1, description = "build mode")
+ boolean build;
+
+ @Option(names= {"-u"}, arity = "1", order = 2, description = "update mode")
+ int step;
+
+ @Option(names= {"-v"}, arity = "0..1", defaultValue = "1", order = 3, description ="verbose mode")
+ int vb_level;
+
+ @Option(names= {"-a"}, arity = "1", order = 4, defaultValue = "answer-sheet.pdf", description ="answer")
+ String answer_name;
+
+ @Parameters(arity = "0..1", defaultValue = "./source.txt", description ="source path")
+ String source_path;
+
+
+
+ @Override
+ public Void call() throws Exception {
+ if(build) {
+ System.out.println("Build mode activated ...");
+ System.out.println("Update : "+step);
+ System.out.println("Verbose : "+vb_level);
+ System.out.println("Answer : "+answer_name);
+ System.out.println("Source : "+source_path);
+ }
+
+ return null;
+
+ }
+}
diff --git a/NGCC/src/commands/Evaluate.java b/NGCC/src/commands/Evaluate.java
new file mode 100644
index 0000000..762268b
--- /dev/null
+++ b/NGCC/src/commands/Evaluate.java
@@ -0,0 +1,63 @@
+package commands;
+import java.util.concurrent.Callable;
+
+//import picocli.CommandLine;
+import picocli.CommandLine.*;
+
+
+@Command(
+ name = "evaluate",
+ version = "Version 1.0",
+ sortOptions = false,
+ usageHelpWidth = 60,
+ header = " -- Nicely Generated and Corrected Copies -- \n",
+ footer = "\n Provided by IUT Info Nice S3T-G4",
+ description = "description"
+)
+
+
+public class Evaluate implements Callable {
+
+ @Option(names= {"-e","--evaluate"}, arity = "0", order = 1, description = "evaluate mode")
+ boolean evaluate;
+
+ @Option(names= {"-u"}, arity = "1", order = 2, description = "update mode")
+ int step;
+
+ @Option(names= {"-v"}, arity = "0..*", order = 3, defaultValue = "1", description ="verbose mode")
+ int vb_level;
+
+ @Option(names= {"-o"}, arity = "1", order = 4, defaultValue = "result.csv", description ="result")
+ String result_name;
+
+ @Parameters(arity = "0..1", defaultValue = "./source.txt", description ="source path")
+ String source_path;
+
+
+ public boolean isCsv(String file) {
+ return file.endsWith(".csv");
+
+ }
+
+ @Override
+ public Void call() throws Exception {
+ if(evaluate) {
+ System.out.println("Generate mode activated ...");
+ System.out.println("Update : "+step);
+ System.out.println("Verbose : "+vb_level);
+
+ if (isCsv(result_name)) {
+ System.out.println("Result : "+result_name);
+ }
+ else {
+ System.out.println("The specified name for the result file is invalid");
+ //System.out.println("Result : "+result_name+".csv");
+ }
+
+ System.out.println("Source : "+source_path);
+ }
+
+ return null;
+
+ }
+}
diff --git a/NGCC/src/commands/Generate.java b/NGCC/src/commands/Generate.java
new file mode 100644
index 0000000..ffecb2b
--- /dev/null
+++ b/NGCC/src/commands/Generate.java
@@ -0,0 +1,67 @@
+package commands;
+import java.util.concurrent.Callable;
+
+//import picocli.CommandLine;
+import picocli.CommandLine.*;
+
+
+@Command(
+ name = "generate",
+ version = "Version 1.0",
+ sortOptions = false,
+ usageHelpWidth = 60,
+ header = " -- Nicely Generated and Corrected Copies -- \n",
+ footer = "\n Provided by IUT Info Nice S3T-G4",
+ description = "description"
+)
+
+
+public class Generate implements Callable {
+
+ @Option(names= {"-g","--generate"}, arity = "0", order = 1, description = "generate mode")
+ boolean generate;
+
+ @Option(names= {"-u"}, arity = "1", order = 2, description = "update mode")
+ int step;
+
+ @Option(names= {"-v"}, arity = "0..*", order = 3, defaultValue = "1", description ="verbose mode")
+ int vb_level;
+
+ @Option(names= {"-t"}, arity = "1", order = 4, defaultValue = "topic-sheet.pdf", description ="topic")
+ String topic_name;
+
+ @Option(names= {"-a"}, arity = "1", order = 5, defaultValue = "answer-sheet.pdf", description ="answer")
+ String answer_name;
+
+ @Parameters(arity = "0..1", defaultValue = "./source.txt", description ="source path")
+ String source_path;
+
+
+ public boolean isPdf(String file) {
+ return file.endsWith(".pdf");
+
+ }
+
+ @Override
+ public Void call() throws Exception {
+ if(generate) {
+ System.out.println("Generate mode activated ...");
+ System.out.println("Update : "+step);
+ System.out.println("Verbose : "+vb_level);
+ System.out.println("Topic : "+topic_name); //isPdf ...
+
+ if (isPdf(answer_name)) {
+ System.out.println("Answer : "+answer_name);
+ }
+ else {
+ System.out.println("The specified name for the result file is invalid");
+ //System.out.println("Answer : "+answer_name+".pdf");
+ }
+
+ System.out.println("Source : "+source_path);
+ }
+
+ return null;
+
+ }
+}
diff --git a/NGCC/src/commands/Help.java b/NGCC/src/commands/Help.java
new file mode 100644
index 0000000..0b7d962
--- /dev/null
+++ b/NGCC/src/commands/Help.java
@@ -0,0 +1,43 @@
+package commands;
+import java.util.concurrent.Callable;
+
+//import picocli.CommandLine;
+import picocli.CommandLine.*;
+
+
+@Command(
+ name = "help",
+ version = "Version 1.0",
+ sortOptions = false,
+ usageHelpWidth = 60,
+ header = " ---- Nicely Generated and Corrected Copies ---- \n" +
+ " _______ _________________ ________ \n" +
+ " \\ \\ / _____/\\_ ___ \\\\_ ___ \\ \n" +
+ " / | \\/ \\ ___/ \\ \\// \\ \\/ \n" +
+ " / | \\ \\_\\ \\ \\___\\ \\__ \n" +
+ " \\____|__ /\\______ /\\______ /\\______ / \n" +
+ " \\/ \\/ \\/ \\/ \n" +
+ " \n" ,
+ footer = "\n ---- Provided by IUT Info Nice S3T-G4 ---- ",
+ description = "description"
+)
+
+
+public class Help implements Callable {
+
+ @Option(names= {"--help"}, required = true, arity = "0", order = 1, description = "help")
+ boolean help;
+
+
+ @Override
+ public Void call() throws Exception {
+ if(help) {
+ System.out.println("Commands List : -b, -r, -g, -p, -a, -e");
+
+
+ }
+
+ return null;
+
+ }
+}
diff --git a/NGCC/src/commands/Produce.java b/NGCC/src/commands/Produce.java
new file mode 100644
index 0000000..f2085dd
--- /dev/null
+++ b/NGCC/src/commands/Produce.java
@@ -0,0 +1,63 @@
+package commands;
+import java.util.concurrent.Callable;
+
+//import picocli.CommandLine;
+import picocli.CommandLine.*;
+
+
+@Command(
+ name = "produce",
+ version = "Version 1.0",
+ sortOptions = false,
+ usageHelpWidth = 60,
+ header = " -- Nicely Generated and Corrected Copies -- \n",
+ footer = "\n Provided by IUT Info Nice S3T-G4",
+ description = "description"
+)
+
+
+public class Produce implements Callable {
+
+ @Option(names= {"-p","--produce"}, arity = "0", order = 1, description = "produce mode")
+ boolean produce;
+
+ @Option(names= {"-u"}, arity = "1", order = 2, description = "update mode")
+ int step;
+
+ @Option(names= {"-v"}, arity = "0..*", order = 3, defaultValue = "1", description ="verbose mode")
+ int vb_level;
+
+ @Option(names= {"-c"}, arity = "1", order = 4, defaultValue = "corrected-sheet.pdf", description ="sheet")
+ String sheet_name;
+
+ @Parameters(arity = "0..1", defaultValue = "./source.txt", description ="source path")
+ String source_path;
+
+
+ public boolean isPdf(String file) {
+ return file.endsWith(".pdf");
+
+ }
+
+ @Override
+ public Void call() throws Exception {
+ if(produce) {
+ System.out.println("Produce mode activated ...");
+ System.out.println("Update : "+step);
+ System.out.println("Verbose : "+vb_level);
+
+ if (isPdf(sheet_name)) {
+ System.out.println("Sheet : "+sheet_name);
+ }
+ else {
+ System.out.println("The specified name for the result file is invalid");
+ //System.out.println("Sheet : "+sheet_name+".pdf");
+ }
+
+ System.out.println("Source : "+source_path);
+ }
+
+ return null;
+
+ }
+}
diff --git a/NGCC/src/commands/Read.java b/NGCC/src/commands/Read.java
new file mode 100644
index 0000000..40fa4c4
--- /dev/null
+++ b/NGCC/src/commands/Read.java
@@ -0,0 +1,66 @@
+package commands;
+import java.util.concurrent.Callable;
+
+//import picocli.CommandLine;
+import picocli.CommandLine.*;
+
+
+@Command(
+ name = "read",
+ version = "Version 1.0",
+ sortOptions = false,
+ usageHelpWidth = 60,
+ header = " -- Nicely Generated and Corrected Copies -- \n",
+ footer = "\n Provided by IUT Info Nice S3T-G4",
+ description = "description"
+)
+
+
+public class Read implements Callable {
+
+ @Option(names= {"-r","--read"}, arity = "0", order = 1, description = "read mode")
+ boolean read;
+
+ @Option(names= {"-u"}, arity = "1", order = 2, description = "update mode")
+ int step;
+
+ @Option(names= {"-v"}, arity = "0..*", order = 3, defaultValue = "1", description ="verbose mode")
+ int vb_level;
+
+ @Option(names= {"-d"}, arity = "1", order = 4, defaultValue = "copies", description ="directory")
+ String directory_name;
+
+ @Option(names= {"-o"}, arity = "1", order = 5, defaultValue = "result.csv", description ="result")
+ String result_name;
+
+ @Parameters(arity = "0..1", defaultValue = "./source.txt", description ="source path")
+ String source_path;
+
+
+ public boolean isCsv(String file) {
+ return file.endsWith(".csv");
+
+ }
+
+ @Override
+ public Void call() throws Exception {
+ if(read) {
+ System.out.println("Read mode activated ...");
+ System.out.println("Update : "+step);
+ System.out.println("Verbose : "+vb_level);
+ System.out.println("Directory : "+directory_name);
+
+ if (isCsv(result_name)) {
+ System.out.println("Result : "+result_name);
+ }
+ else {
+ System.out.println("The specified for the result file is invalid");
+ }
+
+ System.out.println("Source : "+source_path);
+ }
+
+ return null;
+
+ }
+}
diff --git a/NGCC/src/picocli/CommandLine.java b/NGCC/src/picocli/CommandLine.java
new file mode 100644
index 0000000..b148e71
--- /dev/null
+++ b/NGCC/src/picocli/CommandLine.java
@@ -0,0 +1,15165 @@
+/*
+ Copyright 2017 Remko Popma
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+package picocli;
+
+import java.io.*;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.*;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.NetworkInterface;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.ByteOrder;
+import java.nio.charset.Charset;
+import java.text.BreakIterator;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import picocli.CommandLine.Help.Ansi.IStyle;
+import picocli.CommandLine.Help.Ansi.Style;
+import picocli.CommandLine.Help.Ansi.Text;
+import picocli.CommandLine.Model.*;
+import picocli.CommandLine.ParseResult.GroupMatchContainer;
+
+import static java.util.Locale.ENGLISH;
+import static picocli.CommandLine.Help.Column.Overflow.SPAN;
+import static picocli.CommandLine.Help.Column.Overflow.TRUNCATE;
+import static picocli.CommandLine.Help.Column.Overflow.WRAP;
+
+/**
+ *
+ * CommandLine interpreter that uses reflection to initialize an annotated user object with values obtained from the
+ * command line arguments.
+ *
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 (MD5 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 = "MD5";
+ *
+ * // 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) throws Exception {
+ * int exitCode = new CommandLine(new CheckSum()).execute(args);
+ * System.exit(exitCode);
+ * }
+ *
+ * @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;
+ * }
+ * }
+ *
+ * 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 Related to Parsing Command Line Arguments
+ *
+ *
+ *
+ */
+public class CommandLine {
+
+ /** This is picocli version {@value}. */
+ public static final String VERSION = "4.0.5-SNAPSHOT";
+
+ private final Tracer tracer = new Tracer();
+ private final 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, 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, 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.factory = Assert.notNull(factory, "factory");
+ interpreter = new Interpreter();
+ commandSpec = CommandSpec.forAnnotatedObject(command, factory);
+ commandSpec.commandLine(this);
+ commandSpec.validate();
+ if (commandSpec.unmatchedArgsBindings().size() > 0) { setUnmatchedArgumentsAllowed(true); }
+ }
+
+ /**
+ * 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); }
+ 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 ComandSpec} 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 ComandSpec} 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 ComandSpec} 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);
+ subcommandLine.getCommandSpec().initParentCommand(getCommandSpec().userObject());
+ 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 LinkedHashMap(getCommandSpec().subcommands());
+ }
+ /**
+ * 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 {@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 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):
+ *
+ * {@link UsageMessageSpec#SECTION_KEY_HEADER_HEADING SECTION_KEY_HEADER_HEADING}
+ * {@link UsageMessageSpec#SECTION_KEY_HEADER SECTION_KEY_HEADER}
+ * {@link UsageMessageSpec#SECTION_KEY_SYNOPSIS_HEADING SECTION_KEY_SYNOPSIS_HEADING}
+ * {@link UsageMessageSpec#SECTION_KEY_SYNOPSIS SECTION_KEY_SYNOPSIS}
+ * {@link UsageMessageSpec#SECTION_KEY_DESCRIPTION_HEADING SECTION_KEY_DESCRIPTION_HEADING}
+ * {@link UsageMessageSpec#SECTION_KEY_DESCRIPTION SECTION_KEY_DESCRIPTION}
+ * {@link UsageMessageSpec#SECTION_KEY_PARAMETER_LIST_HEADING SECTION_KEY_PARAMETER_LIST_HEADING}
+ * {@link UsageMessageSpec#SECTION_KEY_PARAMETER_LIST SECTION_KEY_PARAMETER_LIST}
+ * {@link UsageMessageSpec#SECTION_KEY_OPTION_LIST_HEADING SECTION_KEY_OPTION_LIST_HEADING}
+ * {@link UsageMessageSpec#SECTION_KEY_OPTION_LIST SECTION_KEY_OPTION_LIST}
+ * {@link UsageMessageSpec#SECTION_KEY_COMMAND_LIST_HEADING SECTION_KEY_COMMAND_LIST_HEADING}
+ * {@link UsageMessageSpec#SECTION_KEY_COMMAND_LIST SECTION_KEY_COMMAND_LIST}
+ * {@link UsageMessageSpec#SECTION_KEY_EXIT_CODE_LIST_HEADING SECTION_KEY_EXIT_CODE_LIST_HEADING}
+ * {@link UsageMessageSpec#SECTION_KEY_EXIT_CODE_LIST SECTION_KEY_EXIT_CODE_LIST}
+ * {@link UsageMessageSpec#SECTION_KEY_FOOTER_HEADING SECTION_KEY_FOOTER_HEADING}
+ * {@link UsageMessageSpec#SECTION_KEY_FOOTER SECTION_KEY_FOOTER}
+ *
+ * @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 whether variables should be interpolated in String values. The default is {@code true}.
+ * @since 4.0 */
+ public boolean isInterpolateVariables() { return getCommandSpec().interpolateVariables(); }
+ /** Sets whether 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 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 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() { return out != null ? out : new PrintWriter(System.out, true); }
+
+ /** 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() { return err != null ? err : new PrintWriter(System.err, true); }
+
+ /** 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 execution mapper} for an exit code, with
+ * {@link CommandSpec#exitCodeOnInvalidInput() exitCodeOnInvalidInput} as the default exit code.
+ * @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
+ * @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();
+ }
+
+ /** Parses the specified command line 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);
+ }
+ /** Parses the specified command line arguments and returns a list of {@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 static 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 static 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 static 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 static 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, new PrintWriter(out, true), 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, new PrintWriter(err(), true), colorScheme()); return returnResultOrExit(null); }
+
+ static void internalHandleParseException(ParameterException ex, PrintWriter writer, Help.ColorScheme colorScheme) {
+ writer.println(ex.getMessage());
+ if (!UnmatchedArgumentException.printSuggestions(ex, writer)) {
+ ex.getCommandLine().usage(writer, colorScheme);
+ }
+ }
+ /** 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(new PrintWriter(out, true)).setErr(new PrintWriter(err, true)).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) {
+ for (int i = 0; i < parsedCommands.size(); i++) {
+ CommandLine parsed = parsedCommands.get(i);
+ Help.ColorScheme colorScheme = parsed.getColorScheme();
+ PrintWriter out = parsed.getOut();
+ if (parsed.isUsageHelpRequested()) {
+ parsed.usage(out, colorScheme);
+ return parsed.getCommandSpec().exitCodeOnUsageHelp();
+ } else if (parsed.isVersionHelpRequested()) {
+ parsed.printVersionHelp(out, colorScheme.ansi);
+ return parsed.getCommandSpec().exitCodeOnVersionHelp();
+ } else if (parsed.getCommandSpec().helpCommand()) {
+ PrintWriter err = parsed.getErr();
+ if (parsed.getCommand() instanceof IHelpCommandInitializable2) {
+ ((IHelpCommandInitializable2) parsed.getCommand()).init(parsed, colorScheme, out, err);
+ } else if (parsed.getCommand() instanceof IHelpCommandInitializable) {
+ ((IHelpCommandInitializable) parsed.getCommand()).init(parsed, colorScheme.ansi, System.out, System.err);
+ }
+ executeUserObject(parsed, new ArrayList());
+ return parsed.getCommandSpec().exitCodeOnUsageHelp();
+ }
+ }
+ return null;
+ }
+ private static List executeUserObject(CommandLine parsed, List executionResultList) {
+ Object command = parsed.getCommand();
+ if (command instanceof Runnable) {
+ try {
+ ((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 {
+ @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().argValues();
+ Object executionResult;
+ if (Modifier.isStatic(method.getModifiers())) {
+ executionResult = method.invoke(null, parsedArgs); // invoke static method
+ } else if (parsed.getCommandSpec().parent() != null) {
+ executionResult = method.invoke(parsed.getCommandSpec().parent().userObject(), parsedArgs);
+ } else {
+ executionResult = method.invoke(parsed.factory.create(method.getDeclaringClass()), 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);
+ }
+ }
+ throw new ExecutionException(parsed, "Parsed command (" + command + ") is not a Method, Runnable or Callable");
+ }
+
+ /**
+ * 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 {
+ @SuppressWarnings("unchecked")
+ 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) {
+ ex.printStackTrace(cmd.getErr());
+ return mappedExitCode(ex, cmd.getExitCodeExceptionMapper(), defaultExitCode);
+ }
+
+ 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(new PrintWriter(handler.out(), true)); }
+ if (handler.err() != System.err) { setErr(new PrintWriter(handler.err(), true)); }
+ 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; }
+
+ R executionResult = handle(parseResult);
+ List exitCodeGenerators = extractExitCodeGenerators(parseResult);
+ 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 < 0 && result <= 0 && exitCode < result)) {
+ result = exitCode;
+ }
+ } catch (Exception ex) {
+ result = (result == 0) ? 1 : result;
+ ex.printStackTrace();
+ }
+ }
+ if (executionResult instanceof List) {
+ List> resultList = (List>) executionResult;
+ for (Object obj : resultList) {
+ if (obj instanceof Integer) {
+ Integer exitCode = (Integer) obj;
+ if ((exitCode > 0 && exitCode > result) || (exitCode < 0 && result <= 0 && exitCode < result)) {
+ result = exitCode;
+ }
+ }
+ }
+ }
+ 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 */
+ @SuppressWarnings("deprecation")
+ public static class RunFirst extends AbstractParseResultHandler> implements IParseResultHandler {
+ /** 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 {
+ return executeUserObject(parseResult.commandSpec().commandLine(), new ArrayList()); // first
+ }
+
+ protected List extractExitCodeGenerators(ParseResult parseResult) {
+ if (parseResult.commandSpec().userObject() instanceof IExitCodeGenerator) {
+ return Arrays.asList((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 */
+ @SuppressWarnings("deprecation")
+ public static class RunLast extends AbstractParseResultHandler> implements IParseResultHandler {
+ /** Prints help if requested, and otherwise executes the most specific {@code Runnable} or {@code Callable} subcommand.
+ * 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(executeUserObject(parsedCommands.get(parsedCommands.size() - 1), new ArrayList()));
+ }
+ /** Executes the most specific {@code Runnable} or {@code Callable} subcommand.
+ * If the last (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 {
+ List parsedCommands = parseResult.asCommandLineList();
+ return executeUserObject(parsedCommands.get(parsedCommands.size() - 1), new ArrayList());
+ }
+ protected List extractExitCodeGenerators(ParseResult parseResult) {
+ List parsedCommands = parseResult.asCommandLineList();
+ Object userObject = parsedCommands.get(parsedCommands.size() - 1).getCommandSpec().userObject();
+ if (userObject instanceof IExitCodeGenerator) { return Arrays.asList((IExitCodeGenerator) userObject); }
+ return Collections.emptyList();
+ }
+ @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 */
+ @SuppressWarnings("deprecation")
+ public static class RunAll extends AbstractParseResultHandler> implements IParseResultHandler {
+ /** 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 {
+ List result = new ArrayList();
+ executeUserObject(parseResult.commandSpec().commandLine(), result);
+ while (parseResult.hasSubcommand()) {
+ parseResult = parseResult.subcommand();
+ executeUserObject(parseResult.commandSpec().commandLine(), result);
+ }
+ return returnResultOrExit(result);
+ }
+ protected List extractExitCodeGenerators(ParseResult parseResult) {
+ List result = new ArrayList();
+ if (parseResult.commandSpec().userObject() instanceof IExitCodeGenerator) { result.add((IExitCodeGenerator) parseResult.commandSpec().userObject()); }
+ while (parseResult.hasSubcommand()) {
+ parseResult = parseResult.subcommand();
+ if (parseResult.commandSpec().userObject() instanceof IExitCodeGenerator) { result.add((IExitCodeGenerator) parseResult.commandSpec().userObject()); }
+ }
+ 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(), getHelpFactory().create(getCommandSpec(), getColorScheme())).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));
+ }
+ 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)));
+ }
+ 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)));
+ }
+ 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 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 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 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 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) {
+ Set candidates = new HashSet();
+ // 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.getCommandSpec().resourceBundle(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 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.
+ * @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(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> 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);}
+ private static boolean isMultiValue(Class> cls) { return cls.isArray() || Collection.class.isAssignableFrom(cls) || Map.class.isAssignableFrom(cls); }
+ private static String format(String formatString, Object... params) {
+ try {
+ return formatString == null ? "" : String.format(formatString, params);
+ } catch (IllegalFormatException ex) {
+ new 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 '%%'.%n", formatString, ex.getMessage());
+ return formatString;
+ }
+ }
+
+ private static class NoCompletionCandidates implements Iterable {
+ public Iterator iterator() { throw new UnsupportedOperationException(); }
+ }
+ /**
+ *
+ * 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 {
+ /**
+ * 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;
+
+ /**
+ * Set {@code help=true} if this option should disable validation of the remaining arguments:
+ * If the {@code help} option is specified, no error message is generated for missing required options.
+ *
+ * This attribute is useful for special options like help ({@code -h} and {@code --help} on unix,
+ * {@code -?} and {@code -Help} on Windows) or version ({@code -V} and {@code --version} on unix,
+ * {@code -Version} on Windows).
+ *
+ *
+ * Note that the {@link #parse(String...)} method will not print help documentation. It will only set
+ * the value of the annotated field. It is the responsibility of the caller to inspect the annotated fields
+ * and take the appropriate action.
+ *
+ * @return whether this option disables validation of the other arguments
+ * @deprecated Use {@link #usageHelp()} and {@link #versionHelp()} instead. See {@link #printHelpIfRequested(List, PrintStream, CommandLine.Help.Ansi)}
+ */
+ @Deprecated 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
+ */
+ 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 zero,
+ * 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 does not expect boolean options (also called "flags" or "switches") to have a parameter.
+ * 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 make the boolean parameter possible but optional, define the field with {@code arity = "0..1"}.
+ * For example:
+ * @Option(names="-v", arity="0..1") boolean verbose;
+ * This will accept any of the below without throwing an exception:
+ *
+ * -v
+ * -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 extends ITypeConverter>>[] 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 "";
+
+ /**
+ * 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.
+ * @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} anywhere in the description that ignores this setting.
+ * @return whether this option's default value should be shown in the usage help message
+ */
+ Help.Visibility showDefaultValue() default Help.Visibility.ON_DEMAND;
+
+ /** Use this attribute to specify an {@code Iterable} class that generates completion candidates for this option.
+ * For map fields, completion candidates should be in {@code key=value} form.
+ *
+ * Completion candidates are used in bash completion scripts generated by the {@code picocli.AutoComplete} class.
+ * Bash has special completion options to generate file names and host names, and the bash completion scripts
+ * generated by {@code AutoComplete} delegate to these bash built-ins for {@code @Options} whose {@code type} is
+ * {@code java.io.File}, {@code java.nio.file.Path} or {@code java.net.InetAddress}.
+ *
+ * For {@code @Options} whose {@code type} is a Java {@code enum}, {@code AutoComplete} can generate completion
+ * candidates from the type. For other types, use this attribute to specify completion candidates.
+ *
+ *
+ * @return a class whose instances can iterate over the completion candidates for this option
+ * @see picocli.CommandLine.IFactory
+ * @since 3.2 */
+ Class extends Iterable> completionCandidates() default NoCompletionCandidates.class;
+
+ /**
+ * Set {@code interactive=true} if this option will 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, this will use the {@link Console#readPassword()} API to get a value without echoing input to the console.
+ *
+ * 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;
+
+ /** 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.
+ * @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;
+
+ /**
+ * 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.
+ *
+ * @see OptionSpec#fallbackValue()
+ * @since 4.0 */
+ String fallbackValue() default "";
+
+ /**
+ * 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 extends IParameterConsumer> parameterConsumer() default NullParameterConsumer.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 {
+ /** 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)
+ */
+ 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 extends ITypeConverter>>[] 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 "";
+
+ /**
+ * 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.
+ * @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} anywhere in the description that ignores this setting.
+ * @return whether this positional parameter's default value should be shown in the usage help message
+ */
+ Help.Visibility showDefaultValue() default Help.Visibility.ON_DEMAND;
+
+ /** Use this attribute to specify an {@code Iterable} class that generates completion candidates for
+ * this positional parameter. For map fields, completion candidates should be in {@code key=value} form.
+ *
+ * Completion candidates are used in bash completion scripts generated by the {@code picocli.AutoComplete} class.
+ * Unfortunately, {@code picocli.AutoComplete} is not very good yet at generating completions for positional parameters.
+ *
+ *
+ * @return a class whose instances can iterate over the completion candidates for this positional parameter
+ * @see picocli.CommandLine.IFactory
+ * @since 3.2 */
+ Class extends Iterable> 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, this will use the {@link Console#readPassword()} API to get a value without echoing input to the console.
+ * @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;
+
+ /** 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 "";
+
+ /**
+ * 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 extends IParameterConsumer> parameterConsumer() default NullParameterConsumer.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:
+ *
+ * class HelloWorld implements Runnable {
+ *
+ * // adds the --help and --version options to this command
+ * @Mixin
+ * private HelpOptions = 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 { }
+
+ /**
+ * 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());
+ *
+ * @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 {};
+
+ /** 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 extends IVersionProvider> 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. The default is to sort alphabetically.
+ * @return whether options should be shown in alphabetic order. */
+ boolean sortOptions() 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.
+ * @return a Class that can provide default values dynamically at runtime
+ * @since 3.6 */
+ Class extends IDefaultValueProvider> 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;
+
+ /** 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 {};
+ }
+ /** 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-ocurring 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
+ */
+ 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;
+ }
+ private static class NoVersionProvider implements IVersionProvider {
+ public String[] getVersion() throws Exception { throw new UnsupportedOperationException(); }
+ }
+
+ /**
+ * 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;
+ * }
+ * }
+ * }
+ * }
+ * }
+ * @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(); }
+ }
+
+ /** 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:+}
+ * @param cmd the command that the option is part of
+ * @return the documentation string for the negatable option, for example {@code --[no-]force}, or {@code -XX:(+|-) }
+ */
+ String makeSynopsis(String optionName, CommandSpec cmd);
+ }
+ /** A regular expression-based option name transformation for {@linkplain Option#negatable() negatable} options.
+ * A common way to negate GNU *nix long options is to prefix them with {@code "no-"}, so
+ * for a {@code --force} option the negative version would be {@code --no-force}.
+ * Java has the {@code -XX:[+|-]} JVM options, where
+ * "Boolean options are turned on with {@code -XX:+} and turned off with {@code -XX:- }".
+ * These are the negative forms {@linkplain #createDefault() supported by default} by this class.
+ *
+ * See the {@link picocli.CommandLine.RegexTransformer.Builder} for an example of customizing this to create negative forms for short options.
+ *
+ * @since 4.0
+ */
+ public static class RegexTransformer implements INegatableOptionTransformer {
+ final Map replacements;
+ final Map synopsis;
+
+ RegexTransformer(RegexTransformer.Builder builder) {
+ replacements = Collections.unmodifiableMap(new LinkedHashMap(builder.replacements));
+ synopsis = Collections.unmodifiableMap(new LinkedHashMap(builder.synopsis));
+ }
+
+ /**
+ * Returns the {@code RegexTransformer} used by default for negatable options.
+ *
+ * The regular expressions used by default for negatable options
+ *
+ * Regex
+ * Negative Replacement
+ * Synopsis Replacement
+ * Comment
+ *
+ *
+ * ^--no-(\w(-|\w)*)$
+ * --$1
+ * --[no-]$1
+ * Converts --no-force
to --force
+ *
+ *
+ * ^--(\w(-|\w)*)$
+ * --no-$1
+ * --[no-]$1
+ * Converts --force
to --no-force
+ *
+ *
+ * ^(-|--)(\w*:)\+(\w(-|\w)*)$
+ * $1$2-$3
+ * $1$2(+|-)$3
+ * Converts -XX:+Inline
to -XX:-Inline
+ *
+ *
+ * ^(-|--)(\w*:)\-(\w(-|\w)*)$
+ * $1$2+$3
+ * $1$2(+|-)$3
+ * Converts -XX:-Inline
to -XX:+Inline
+ *
+ *
+ */
+ public static RegexTransformer createDefault() {
+ CommandLine.RegexTransformer transformer = new CommandLine.RegexTransformer.Builder()
+ .addPattern("^--no-(\\w(-|\\w)*)$", "--$1", "--[no-]$1")
+ .addPattern("^--(\\w(-|\\w)*)$", "--no-$1", "--[no-]$1")
+ .addPattern("^(-|--)(\\w*:)\\+(\\w(-|\\w)*)$", "$1$2-$3", "$1$2(+|-)$3")
+ .addPattern("^(-|--)(\\w*:)\\-(\\w(-|\\w)*)$", "$1$2+$3", "$1$2(+|-)$3")
+ .build();
+ return transformer;
+ }
+
+ /** {@inheritDoc} */
+ public String makeNegative(String optionName, CommandSpec cmd) {
+ for (Map.Entry entry : replacements.entrySet()) {
+ Matcher matcher = entry.getKey().matcher(optionName);
+ if (matcher.find()) { return matcher.replaceAll(entry.getValue()); }
+ }
+ return optionName;
+ }
+
+ /** {@inheritDoc} */
+ public String makeSynopsis(String optionName, CommandSpec cmd) {
+ for (Map.Entry entry : synopsis.entrySet()) {
+ Matcher matcher = entry.getKey().matcher(optionName);
+ if (matcher.find()) { return matcher.replaceAll(entry.getValue()); }
+ }
+ return optionName;
+ }
+
+ public String toString() {
+ return getClass().getName() + "[replacements=" + replacements + ", synopsis=" + synopsis + "]@" + System.identityHashCode(this);
+ }
+
+ /** Builder for creating {@code RegexTransformer} objects.
+ * @since 4.0 */
+ public static class Builder {
+ Map replacements = new LinkedHashMap();
+ Map synopsis = new LinkedHashMap();
+ /** Constructs an empty builder. */
+ public Builder() {}
+ /** Constructs a builder populated with the values from the specified RegexTransformer. */
+ public Builder(RegexTransformer old) {
+ replacements.putAll(old.replacements);
+ synopsis.putAll(old.synopsis);
+ }
+ /**
+ * Adds the specified negative replacement and synopsis replacement for the specified regular expression.
+ * For example, to add negative forms for short options:
+ *
+ * Regular expressions for adding negative forms for short options
+ *
+ * Regex
+ * Negative Replacement
+ * Synopsis Replacement
+ * Comment
+ *
+ *
+ * ^-(\w)$
+ * +$1
+ * (+|-)$1
+ * Converts -v
to +v
+ *
+ *
+ * ^\+(\w)$
+ * -$1
+ * (+|-)$1
+ * Converts -v
to +v
+ *
+ *
+ *
+ * @param regex regular expression to match an option name
+ * @param negativeReplacement the replacement to use to generate a {@linkplain #makeNegative(String, CommandSpec) negative name} when the option name matches
+ * @param synopsisReplacement the replacement to use to generate a {@linkplain #makeSynopsis(String, CommandSpec) documentation string} when the option name matches
+ * @return this {@code RegexTransformer} for method chaining
+ */
+ public RegexTransformer.Builder addPattern(String regex, String negativeReplacement, String synopsisReplacement) {
+ Pattern pattern = Pattern.compile(regex);
+ replacements.put(pattern, negativeReplacement);
+ synopsis.put(pattern, synopsisReplacement);
+ return this;
+ }
+ /**
+ * Removes the negative replacement and synopsis replacement for the specified regular expression.
+ * @param regex regular expression to remove
+ * @return this {@code RegexTransformer} for method chaining
+ */
+ public RegexTransformer.Builder removePattern(String regex) {
+ for (Iterator iter = replacements.keySet().iterator(); iter.hasNext(); ) {
+ Pattern pattern = iter.next();
+ if (pattern.toString().equals(regex)) {
+ iter.remove();
+ synopsis.remove(pattern);
+ }
+ }
+ return this;
+ }
+
+ public RegexTransformer build() { return new RegexTransformer(this); }
+ }
+ }
+
+ /**
+ * Creates the {@link Help} instance used to render the usage help message.
+ * @since 3.9
+ */
+ public interface IHelpFactory {
+ /** Returns a {@code Help} instance to assist in rendering the usage help message
+ * @param commandSpec the command to create usage help for
+ * @param colorScheme the color scheme to use when rendering usage help
+ * @return a {@code Help} instance
+ */
+ Help create(CommandSpec commandSpec, Help.ColorScheme colorScheme);
+ }
+
+ private static class DefaultHelpFactory implements IHelpFactory {
+ public Help create(CommandSpec commandSpec, Help.ColorScheme colorScheme) {
+ return new Help(commandSpec, colorScheme);
+ }
+ }
+
+ /**
+ * Factory for instantiating classes that are registered declaratively with annotation attributes, like
+ * {@link Command#subcommands()}, {@link Option#converter()}, {@link Parameters#converter()} and {@link Command#versionProvider()}.
+ * The default factory implementation simply creates a new instance of the specified class when {@link #create(Class)} is invoked.
+ *
+ * You may provide a custom implementation of this interface.
+ * For example, a custom factory implementation could delegate to a dependency injection container that provides the requested instance.
+ *
+ * @see picocli.CommandLine#CommandLine(Object, IFactory)
+ * @see #call(Class, IFactory, PrintStream, PrintStream, Help.Ansi, String...)
+ * @see #run(Class, IFactory, PrintStream, PrintStream, Help.Ansi, String...)
+ * @see #defaultFactory()
+ * @since 2.2 */
+ public interface IFactory {
+ /**
+ * Returns an instance of the specified class.
+ * @param cls the class of the object to return
+ * @param the type of the object to return
+ * @return the instance
+ * @throws Exception an exception detailing what went wrong when creating or obtaining the instance
+ */
+ K create(Class cls) throws Exception;
+ }
+ /** Returns the default {@link IFactory} implementation used if no factory was specified in the {@link #CommandLine(Object) CommandLine constructor}.
+ * @since 4.0 */
+ public static IFactory defaultFactory() { return new DefaultFactory(); }
+ private static class DefaultFactory implements IFactory {
+ public T create(Class cls) throws Exception {
+ if (cls.isInterface() && Collection.class.isAssignableFrom(cls)) {
+ if (List.class.isAssignableFrom(cls)) {
+ return cls.cast(new ArrayList());
+ } else if (SortedSet.class.isAssignableFrom(cls)) {
+ return cls.cast(new TreeSet());
+ } else if (Set.class.isAssignableFrom(cls)) {
+ return cls.cast(new LinkedHashSet());
+ } else if (Queue.class.isAssignableFrom(cls)) {
+ return cls.cast(new LinkedList()); // ArrayDeque is only available since 1.6
+ }
+ return cls.cast(new ArrayList());
+ }
+ if (Map.class.isAssignableFrom(cls)) {
+ try { // if it is an implementation class, instantiate it
+ return cls.cast(cls.getDeclaredConstructor().newInstance());
+ } catch (Exception ignored) { }
+ return cls.cast(new LinkedHashMap());
+ }
+ try {
+ @SuppressWarnings("deprecation") // Class.newInstance is deprecated in Java 9
+ T result = cls.newInstance();
+ return result;
+ } catch (Exception ex) {
+ Constructor constructor = cls.getDeclaredConstructor();
+ constructor.setAccessible(true);
+ return constructor.newInstance();
+ }
+ }
+ private static ITypeConverter>[] createConverter(IFactory factory, Class extends ITypeConverter>>[] classes) {
+ ITypeConverter>[] result = new ITypeConverter>[classes.length];
+ for (int i = 0; i < classes.length; i++) { result[i] = create(factory, classes[i]); }
+ return result;
+ }
+ static IVersionProvider createVersionProvider(IFactory factory, Class extends IVersionProvider> cls) {
+ return create(factory, cls);
+ }
+ static IDefaultValueProvider createDefaultValueProvider(IFactory factory, Class extends IDefaultValueProvider> cls) {
+ return create(factory, cls);
+ }
+ static Iterable createCompletionCandidates(IFactory factory, Class extends Iterable> cls) {
+ return create(factory, cls);
+ }
+ static IParameterConsumer createParameterConsumer(IFactory factory, Class extends IParameterConsumer> cls) {
+ return create(factory, cls);
+ }
+ static T create(IFactory factory, Class cls) {
+ try { return factory.create(cls); }
+ catch (Exception ex) { throw new InitializationException("Could not instantiate " + cls + ": " + ex, ex); }
+ }
+ }
+ /** Describes the number of parameters required and accepted by an option or a positional parameter.
+ * @since 0.9.7
+ */
+ @SuppressWarnings("deprecation")
+ public static class Range implements Comparable {
+ /** @deprecated use {@link #min()} instead */
+ @Deprecated public final int min;
+ /** @deprecated use {@link #max()} instead */
+ @Deprecated public final int max;
+ /** @deprecated use {@link #isVariable()} instead */
+ @Deprecated public final boolean isVariable;
+ private final boolean isUnspecified;
+ private final String originalValue;
+
+ /** Constructs a new Range object with the specified parameters.
+ * @param min minimum number of required parameters
+ * @param max maximum number of allowed parameters (or Integer.MAX_VALUE if variable)
+ * @param variable {@code true} if any number or parameters is allowed, {@code false} otherwise
+ * @param unspecified {@code true} if no arity was specified on the option/parameter (value is based on type)
+ * @param originalValue the original value that was specified on the option or parameter
+ */
+ public Range(int min, int max, boolean variable, boolean unspecified, String originalValue) {
+ if (min < 0 || max < 0) { throw new InitializationException("Invalid negative range (min=" + min + ", max=" + max + ")"); }
+ if (min > max) { throw new InitializationException("Invalid range (min=" + min + ", max=" + max + ")"); }
+ this.min = min;
+ this.max = max;
+ this.isVariable = variable;
+ this.isUnspecified = unspecified;
+ this.originalValue = originalValue;
+ }
+ /** Returns a new {@code Range} based on the {@link Option#arity()} annotation on the specified field,
+ * or the field type's default arity if no arity was specified.
+ * @param field the field whose Option annotation to inspect
+ * @return a new {@code Range} based on the Option arity annotation on the specified field */
+ public static Range optionArity(Field field) { return optionArity(new TypedMember(field)); }
+ private static Range optionArity(IAnnotatedElement member) {
+ return member.isAnnotationPresent(Option.class)
+ ? adjustForType(Range.valueOf(member.getAnnotation(Option.class).arity()), member)
+ : new Range(0, 0, false, true, "0");
+ }
+ /** Returns a new {@code Range} based on the {@link Parameters#arity()} annotation on the specified field,
+ * or the field type's default arity if no arity was specified.
+ * @param field the field whose Parameters annotation to inspect
+ * @return a new {@code Range} based on the Parameters arity annotation on the specified field */
+ public static Range parameterArity(Field field) { return parameterArity(new TypedMember(field)); }
+ private static Range parameterArity(IAnnotatedElement member) {
+ if (member.isAnnotationPresent(Parameters.class)) {
+ return adjustForType(Range.valueOf(member.getAnnotation(Parameters.class).arity()), member);
+ } else {
+ return member.isMethodParameter()
+ ? adjustForType(Range.valueOf(""), member)
+ : new Range(0, 0, false, true, "0");
+ }
+ }
+ /** Returns a new {@code Range} based on the {@link Parameters#index()} annotation on the specified field.
+ * @param field the field whose Parameters annotation to inspect
+ * @return a new {@code Range} based on the Parameters index annotation on the specified field */
+ public static Range parameterIndex(Field field) { return parameterIndex(new TypedMember(field)); }
+ private static Range parameterIndex(IAnnotatedElement member) {
+ if (member.isAnnotationPresent(Parameters.class)) {
+ Range result = Range.valueOf(member.getAnnotation(Parameters.class).index());
+ if (!result.isUnspecified) { return result; }
+ }
+ if (member.isMethodParameter()) {
+ int min = member.getMethodParamPosition();
+ int max = member.isMultiValue() ? Integer.MAX_VALUE : min;
+ return new Range(min, max, member.isMultiValue(), false, "");
+ }
+ return Range.valueOf("*"); // the default
+ }
+ static Range adjustForType(Range result, IAnnotatedElement member) {
+ return result.isUnspecified ? defaultArity(member) : result;
+ }
+ /** Returns the default arity {@code Range}: for interactive options/positional parameters,
+ * this is 0; for {@link Option options} this is 0 for booleans and 1 for
+ * other types, for {@link Parameters parameters} booleans have arity 0, arrays or Collections have
+ * arity "0..*", and other types have arity 1.
+ * @param field the field whose default arity to return
+ * @return a new {@code Range} indicating the default arity of the specified field
+ * @since 2.0 */
+ public static Range defaultArity(Field field) { return defaultArity(new TypedMember(field)); }
+ private static Range defaultArity(IAnnotatedElement member) {
+ if (member.isInteractive()) { return Range.valueOf("0").unspecified(true); }
+ ITypeInfo info = member.getTypeInfo();
+ if (member.isAnnotationPresent(Option.class)) {
+ boolean zeroArgs = info.isBoolean() || (info.isMultiValue() && info.getAuxiliaryTypeInfos().get(0).isBoolean());
+ return zeroArgs ? Range.valueOf("0").unspecified(true)
+ : Range.valueOf("1").unspecified(true);
+ }
+ if (info.isMultiValue()) {
+ return Range.valueOf("0..1").unspecified(true);
+ }
+ return Range.valueOf("1").unspecified(true);// for single-valued fields (incl. boolean positional parameters)
+ }
+ /** Returns the default arity {@code Range} for {@link Option options}: booleans have arity 0, other types have arity 1.
+ * @param type the type whose default arity to return
+ * @return a new {@code Range} indicating the default arity of the specified type
+ * @deprecated use {@link #defaultArity(Field)} instead */
+ @Deprecated public static Range defaultArity(Class> type) {
+ return isBoolean(type) ? Range.valueOf("0").unspecified(true) : Range.valueOf("1").unspecified(true);
+ }
+ private int size() { return 1 + max - min; }
+ static Range parameterCapacity(IAnnotatedElement member) {
+ Range arity = parameterArity(member);
+ if (!member.isMultiValue()) { return arity; }
+ Range index = parameterIndex(member);
+ return parameterCapacity(arity, index);
+ }
+ private static Range parameterCapacity(Range arity, Range index) {
+ if (arity.max == 0) { return arity; }
+ if (index.size() == 1) { return arity; }
+ if (index.isVariable) { return Range.valueOf(arity.min + "..*"); }
+ if (arity.size() == 1) { return Range.valueOf(arity.min * index.size() + ""); }
+ if (arity.isVariable) { return Range.valueOf(arity.min * index.size() + "..*"); }
+ return Range.valueOf(arity.min * index.size() + ".." + arity.max * index.size());
+ }
+
+ /** Leniently parses the specified String as an {@code Range} value and return the result. A range string can
+ * be a fixed integer value or a range of the form {@code MIN_VALUE + ".." + MAX_VALUE}. If the
+ * {@code MIN_VALUE} string is not numeric, the minimum is zero. If the {@code MAX_VALUE} is not numeric, the
+ * range is taken to be variable and the maximum is {@code Integer.MAX_VALUE}.
+ * @param range the value range string to parse
+ * @return a new {@code Range} value */
+ public static Range valueOf(String range) {
+ if (range.contains("${")) {
+ return new Range(0, 0, false, false, range); // unresolved
+ }
+ range = range.trim();
+ boolean unspecified = range.length() == 0 || range.startsWith(".."); // || range.endsWith("..");
+ int min = -1, max = -1;
+ boolean variable = false;
+ int dots = -1;
+ if ((dots = range.indexOf("..")) >= 0) {
+ min = parseInt(range.substring(0, dots), 0);
+ max = parseInt(range.substring(dots + 2), Integer.MAX_VALUE);
+ variable = max == Integer.MAX_VALUE;
+ } else {
+ max = parseInt(range, Integer.MAX_VALUE);
+ variable = max == Integer.MAX_VALUE;
+ min = variable ? 0 : max;
+ }
+ Range result = new Range(min, max, variable, unspecified, range);
+ return result;
+ }
+ private static int parseInt(String str, int defaultValue) {
+ try {
+ return Integer.parseInt(str);
+ } catch (Exception ex) {
+ return defaultValue;
+ }
+ }
+ /** Returns a new Range object with the {@code min} value replaced by the specified value.
+ * The {@code max} of the returned Range is guaranteed not to be less than the new {@code min} value.
+ * @param newMin the {@code min} value of the returned Range object
+ * @return a new Range object with the specified {@code min} value */
+ public Range min(int newMin) { return new Range(newMin, Math.max(newMin, max), isVariable, isUnspecified, originalValue); }
+
+ /** Returns a new Range object with the {@code max} value replaced by the specified value.
+ * The {@code min} of the returned Range is guaranteed not to be greater than the new {@code max} value.
+ * @param newMax the {@code max} value of the returned Range object
+ * @return a new Range object with the specified {@code max} value */
+ public Range max(int newMax) { return new Range(Math.min(min, newMax), newMax, isVariable, isUnspecified, originalValue); }
+
+ /** Returns a new Range object with the {@code isUnspecified} value replaced by the specified value.
+ * @param unspecified the {@code unspecified} value of the returned Range object
+ * @return a new Range object with the specified {@code unspecified} value */
+ public Range unspecified(boolean unspecified) { return new Range(min, max, isVariable, unspecified, originalValue); }
+ /** Returns {@code true} if this Range is a default value, {@code false} if the user specified this value.
+ * @since 4.0 */
+ public boolean isUnspecified() { return isUnspecified; }
+ /** Returns {@code true} if this range contains variables that have not been expanded yet,
+ * {@code false} if this Range does not contain any variables.
+ * @since 4.0 */
+ public boolean isUnresolved() { return originalValue != null && originalValue.contains("${"); }
+ /** Returns the lower bound of this range (inclusive).
+ * @since 4.0 */
+ public int min() { return min; }
+ /** Returns the upper bound of this range (inclusive), or {@code Integer.MAX_VALUE} if this range has {@linkplain #isVariable() no upper bound}.
+ * @since 4.0 */
+ public int max() { return max; }
+ /** Returns {@code true} if this range has no fixed upper bound.
+ * @since 4.0 */
+ public boolean isVariable() { return isVariable; }
+
+ /**
+ * Returns {@code true} if this Range includes the specified value, {@code false} otherwise.
+ * @param value the value to check
+ * @return {@code true} if the specified value is not less than the minimum and not greater than the maximum of this Range
+ */
+ public boolean contains(int value) { return min <= value && max >= value; }
+
+ public boolean equals(Object object) {
+ if (!(object instanceof Range)) { return false; }
+ Range other = (Range) object;
+ return other.max == this.max && other.min == this.min && other.isVariable == this.isVariable;
+ }
+ public int hashCode() {
+ return ((17 * 37 + max) * 37 + min) * 37 + (isVariable ? 1 : 0);
+ }
+ public String toString() {
+ if (isUnresolved()) { return originalValue; }
+ return min == max ? String.valueOf(min) : min + ".." + (isVariable ? "*" : max);
+ }
+ public int compareTo(Range other) {
+ int result = min - other.min;
+ return (result == 0) ? max - other.max : result;
+ }
+ /** Returns true for these ranges: 0 and 0..1. */
+ boolean isValidForInteractiveArgs() { return (min == 0 && (max == 0 || max == 1)); }
+ boolean overlaps(Range index) {
+ return contains(index.min) || contains(index.max) || index.contains(min) || index.contains(max);
+ }
+ }
+ private static void validatePositionalParameters(List positionalParametersFields) {
+ int min = 0;
+ for (PositionalParamSpec positional : positionalParametersFields) {
+ Range index = positional.index();
+ if (index.min > min) {
+ throw new ParameterIndexGapException("Command definition should have a positional parameter with index=" + min +
+ ". Nearest positional parameter '" + positional.paramLabel() + "' has index=" + index.min);
+ }
+ min = Math.max(min, index.max);
+ min = min == Integer.MAX_VALUE ? min : min + 1;
+ }
+ }
+ @SuppressWarnings("unchecked") private static Stack copy(Stack stack) { return (Stack) stack.clone(); }
+ private static Stack reverse(Stack stack) {
+ Collections.reverse(stack);
+ return stack;
+ }
+ private static List reverseList(List list) {
+ Collections.reverse(list);
+ return list;
+ }
+
+ /** This class provides a namespace for classes and interfaces that model concepts and attributes of command line interfaces in picocli.
+ * @since 3.0 */
+ public static final class Model {
+ private Model() {}
+
+ /** The scope of a binding is the context where the current value should be gotten from or set to.
+ * For a field, the scope is the object whose field value to get/set. For a method binding, it is the
+ * object on which the method should be invoked.
+ * The getter and setter of the scope allow you to change the object onto which the option and positional parameter getters and setters should be applied.
+ * @since 4.0
+ */
+ public interface IScope extends IGetter, ISetter {}
+
+ /** Customizable getter for obtaining the current value of an option or positional parameter.
+ * When an option or positional parameter is matched on the command line, its getter or setter is invoked to capture the value.
+ * For example, an option can be bound to a field or a method, and when the option is matched on the command line, the
+ * field's value is set or the method is invoked with the option parameter value.
+ * @since 3.0 */
+ public static interface IGetter {
+ /** Returns the current value of the binding. For multi-value options and positional parameters,
+ * this method returns an array, collection or map to add values to.
+ * @throws PicocliException if a problem occurred while obtaining the current value
+ * @throws Exception internally, picocli call sites will catch any exceptions thrown from here and rethrow them wrapped in a PicocliException */
+ T get() throws Exception;
+ }
+ /** Customizable setter for modifying the value of an option or positional parameter.
+ * When an option or positional parameter is matched on the command line, its setter is invoked to capture the value.
+ * For example, an option can be bound to a field or a method, and when the option is matched on the command line, the
+ * field's value is set or the method is invoked with the option parameter value.
+ * @since 3.0 */
+ public static interface ISetter {
+ /** Sets the new value of the option or positional parameter.
+ *
+ * @param value the new value of the option or positional parameter
+ * @param type of the value
+ * @return the previous value of the binding (if supported by this binding)
+ * @throws PicocliException if a problem occurred while setting the new value
+ * @throws Exception internally, picocli call sites will catch any exceptions thrown from here and rethrow them wrapped in a PicocliException */
+ T set(T value) throws Exception;
+ }
+
+ /** The {@code CommandSpec} class models a command specification, including the options, positional parameters and subcommands
+ * supported by the command, as well as attributes for the version help message and the usage help message of the command.
+ *
+ * Picocli views a command line application as a hierarchy of commands: there is a top-level command (usually the Java
+ * class with the {@code main} method) with optionally a set of command line options, positional parameters and subcommands.
+ * Subcommands themselves can have options, positional parameters and nested sub-subcommands to any level of depth.
+ *
+ * The object model has a corresponding hierarchy of {@code CommandSpec} objects, each with a set of {@link OptionSpec},
+ * {@link PositionalParamSpec} and {@linkplain CommandLine subcommands} associated with it.
+ * This object model is used by the picocli command line interpreter and help message generator.
+ *
Picocli can construct a {@code CommandSpec} automatically from classes with {@link Command @Command}, {@link Option @Option} and
+ * {@link Parameters @Parameters} annotations. Alternatively a {@code CommandSpec} can be constructed programmatically.
+ *
+ * @since 3.0 */
+ public static class CommandSpec {
+ /** Constant String holding the default program name: {@code "" }.
+ * @since 4.0 */
+ public static final String DEFAULT_COMMAND_NAME = "";
+
+ /** Constant Boolean holding the default setting for whether this is a help command: {@value}
.*/
+ static final Boolean DEFAULT_IS_HELP_COMMAND = false;
+
+ /** Constant Boolean holding the default setting for whether method commands should be added as subcommands: {@value}
.*/
+ static final Boolean DEFAULT_IS_ADD_METHOD_SUBCOMMANDS = true;
+
+ /** Constant Boolean holding the default setting for whether variables should be interpolated in String values: {@value}
.*/
+ static final Boolean DEFAULT_INTERPOLATE_VARIABLES = true;
+
+ private final Map commands = new LinkedHashMap();
+ private final Map optionsByNameMap = new LinkedHashMap();
+ private final Map negatedOptionsByNameMap = new LinkedHashMap();
+ private final Map posixOptionsByKeyMap = new LinkedHashMap();
+ private final Map mixins = new LinkedHashMap();
+ private final List requiredArgs = new ArrayList();
+ private final List args = new ArrayList();
+ private final List options = new ArrayList();
+ private final List positionalParameters = new ArrayList();
+ private final List unmatchedArgs = new ArrayList();
+ private final List specElements = new ArrayList();
+ private final List parentCommandElements = new ArrayList();
+ private final List groups = new ArrayList();
+ private final ParserSpec parser = new ParserSpec();
+ private final Interpolator interpolator = new Interpolator(this);
+ private final UsageMessageSpec usageMessage = new UsageMessageSpec(interpolator);
+
+ private final Object userObject;
+ private CommandLine commandLine;
+ private CommandSpec parent;
+ private Boolean isAddMethodSubcommands;
+ private Boolean interpolateVariables;
+
+ private String name;
+ private Set aliases = new LinkedHashSet();
+ private Boolean isHelpCommand;
+ private IVersionProvider versionProvider;
+ private IDefaultValueProvider defaultValueProvider;
+ private INegatableOptionTransformer negatableOptionTransformer = RegexTransformer.createDefault();
+ private String[] version;
+ private String toString;
+
+ private Integer exitCodeOnSuccess;
+ private Integer exitCodeOnUsageHelp;
+ private Integer exitCodeOnVersionHelp;
+ private Integer exitCodeOnInvalidInput;
+ private Integer exitCodeOnExecutionException;
+
+ private CommandSpec(Object userObject) { this.userObject = userObject; }
+
+ /** Creates and returns a new {@code CommandSpec} without any associated user object. */
+ public static CommandSpec create() { return wrapWithoutInspection(null); }
+
+ /** Creates and returns a new {@code CommandSpec} with the specified associated user object.
+ * The specified user object is not inspected for annotations.
+ * @param userObject the associated user object. May be any object, may be {@code null}.
+ */
+ public static CommandSpec wrapWithoutInspection(Object userObject) { return new CommandSpec(userObject); }
+
+ /** Creates and returns a new {@code CommandSpec} initialized from the specified associated user object. The specified
+ * user object must have at least one {@link Command}, {@link Option} or {@link Parameters} annotation.
+ * @param userObject the user object annotated with {@link Command}, {@link Option} and/or {@link Parameters} annotations.
+ * @throws InitializationException if the specified object has no picocli annotations or has invalid annotations
+ */
+ public static CommandSpec forAnnotatedObject(Object userObject) { return forAnnotatedObject(userObject, new DefaultFactory()); }
+
+ /** Creates and returns a new {@code CommandSpec} initialized from the specified associated user object. The specified
+ * user object must have at least one {@link Command}, {@link Option} or {@link Parameters} annotation.
+ * @param userObject the user object annotated with {@link Command}, {@link Option} and/or {@link Parameters} annotations.
+ * @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 object has no picocli annotations or has invalid annotations
+ */
+ public static CommandSpec forAnnotatedObject(Object userObject, IFactory factory) { return CommandReflection.extractCommandSpec(userObject, factory, true); }
+
+ /** Creates and returns a new {@code CommandSpec} initialized from the specified associated user object. If the specified
+ * user object has no {@link Command}, {@link Option} or {@link Parameters} annotations, an empty {@code CommandSpec} is returned.
+ * @param userObject the user object annotated with {@link Command}, {@link Option} and/or {@link Parameters} annotations.
+ * @throws InitializationException if the specified object has invalid annotations
+ */
+ public static CommandSpec forAnnotatedObjectLenient(Object userObject) { return forAnnotatedObjectLenient(userObject, new DefaultFactory()); }
+
+ /** Creates and returns a new {@code CommandSpec} initialized from the specified associated user object. If the specified
+ * user object has no {@link Command}, {@link Option} or {@link Parameters} annotations, an empty {@code CommandSpec} is returned.
+ * @param userObject the user object annotated with {@link Command}, {@link Option} and/or {@link Parameters} annotations.
+ * @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 object has invalid annotations
+ */
+ public static CommandSpec forAnnotatedObjectLenient(Object userObject, IFactory factory) { return CommandReflection.extractCommandSpec(userObject, factory, false); }
+
+ /** Ensures all attributes of this {@code CommandSpec} have a valid value; throws an {@link InitializationException} if this cannot be achieved. */
+ void validate() {
+ Collections.sort(positionalParameters, new PositionalParametersSorter());
+ validatePositionalParameters(positionalParameters);
+ List wrongUsageHelpAttr = new ArrayList();
+ List wrongVersionHelpAttr = new ArrayList();
+ List usageHelpAttr = new ArrayList();
+ List versionHelpAttr = new ArrayList();
+ for (OptionSpec option : options()) {
+ if (option.usageHelp()) {
+ usageHelpAttr.add(option.longestName());
+ if (!isBoolean(option.type())) { wrongUsageHelpAttr.add(option.longestName()); }
+ }
+ if (option.versionHelp()) {
+ versionHelpAttr.add(option.longestName());
+ if (!isBoolean(option.type())) { wrongVersionHelpAttr.add(option.longestName()); }
+ }
+ }
+ String wrongType = "Non-boolean options like %s should not be marked as '%s=true'. Usually a command has one %s boolean flag that triggers display of the %s. Alternatively, consider using @Command(mixinStandardHelpOptions = true) on your command instead.";
+ String multiple = "Multiple options %s are marked as '%s=true'. Usually a command has only one %s option that triggers display of the %s. Alternatively, consider using @Command(mixinStandardHelpOptions = true) on your command instead.%n";
+ if (!wrongUsageHelpAttr.isEmpty()) {
+ throw new InitializationException(String.format(wrongType, wrongUsageHelpAttr, "usageHelp", "--help", "usage help message"));
+ }
+ if (!wrongVersionHelpAttr.isEmpty()) {
+ throw new InitializationException(String.format(wrongType, wrongVersionHelpAttr, "versionHelp", "--version", "version information"));
+ }
+ if (usageHelpAttr.size() > 1) { new Tracer().warn(multiple, usageHelpAttr, "usageHelp", "--help", "usage help message"); }
+ if (versionHelpAttr.size() > 1) { new Tracer().warn(multiple, versionHelpAttr, "versionHelp", "--version", "version information"); }
+ }
+
+ /** Returns the user object associated with this command.
+ * @see CommandLine#getCommand() */
+ public Object userObject() { return userObject; }
+
+ /** Returns the CommandLine constructed with this {@code CommandSpec} model. */
+ public CommandLine commandLine() { return commandLine;}
+
+ /** Sets the CommandLine constructed with this {@code CommandSpec} model. */
+ protected CommandSpec commandLine(CommandLine commandLine) {
+ this.commandLine = commandLine;
+ for (CommandSpec mixedInSpec : mixins.values()) {
+ mixedInSpec.commandLine(commandLine);
+ }
+ for (CommandLine sub : commands.values()) {
+ sub.getCommandSpec().parent(this);
+ }
+ return this;
+ }
+
+ /** Returns the parser specification for this command. */
+ public ParserSpec parser() { return parser; }
+ /** Initializes the parser specification for this command from the specified settings and returns this commandSpec.*/
+ public CommandSpec parser(ParserSpec settings) { parser.initFrom(settings); return this; }
+
+ /** Returns the usage help message specification for this command. */
+ public UsageMessageSpec usageMessage() { return usageMessage; }
+ /** Initializes the usageMessage specification for this command from the specified settings and returns this commandSpec.*/
+ public CommandSpec usageMessage(UsageMessageSpec settings) { usageMessage.initFrom(settings, this); return this; }
+
+ /** Returns the resource bundle base name for this command.
+ * @return the resource bundle base name from the {@linkplain UsageMessageSpec#messages()}
+ * @since 4.0 */
+ public String resourceBundleBaseName() { return Messages.resourceBundleBaseName(usageMessage.messages()); }
+ /** Initializes the resource bundle for this command: sets the {@link UsageMessageSpec#messages(Messages) UsageMessageSpec.messages} to
+ * a {@link Messages Messages} object created from this command spec and the specified bundle, and then sets the
+ * {@link ArgSpec#messages(Messages) ArgSpec.messages} of all options and positional parameters in this command
+ * to the same {@code Messages} instance. Subcommands are not modified.
+ * This method is preferable to {@link #resourceBundle(ResourceBundle)} for pre-Java 8
+ * @param resourceBundleBaseName the base name of the ResourceBundle to set, may be {@code null}
+ * @return this commandSpec
+ * @see #addSubcommand(String, CommandLine)
+ * @since 4.0 */
+ public CommandSpec resourceBundleBaseName(String resourceBundleBaseName) {
+ ResourceBundle bundle = empty(resourceBundleBaseName) ? null : ResourceBundle.getBundle(resourceBundleBaseName);
+ setBundle(resourceBundleBaseName, bundle);
+ return this;
+ }
+ /** Returns the resource bundle for this command.
+ * @return the resource bundle from the {@linkplain UsageMessageSpec#messages()}
+ * @since 3.6 */
+ public ResourceBundle resourceBundle() { return Messages.resourceBundle(usageMessage.messages()); }
+ /** Initializes the resource bundle for this command: sets the {@link UsageMessageSpec#messages(Messages) UsageMessageSpec.messages} to
+ * a {@link Messages Messages} object created from this command spec and the specified bundle, and then sets the
+ * {@link ArgSpec#messages(Messages) ArgSpec.messages} of all options and positional parameters in this command
+ * to the same {@code Messages} instance. Subcommands are not modified.
+ * @param bundle the ResourceBundle to set, may be {@code null}
+ * @return this commandSpec
+ * @see #addSubcommand(String, CommandLine)
+ * @since 3.6 */
+ public CommandSpec resourceBundle(ResourceBundle bundle) {
+ setBundle(Messages.extractName(bundle), bundle);
+ return this;
+ }
+ private void setBundle(String bundleBaseName, ResourceBundle bundle) {
+ usageMessage().messages(new Messages(this, bundleBaseName, bundle));
+ updateArgSpecMessages();
+ }
+ private void updateArgSpecMessages() {
+ for (OptionSpec opt : options()) { opt.messages(usageMessage().messages()); }
+ for (PositionalParamSpec pos : positionalParameters()) { pos.messages(usageMessage().messages()); }
+ for (ArgGroupSpec group : argGroups()) { group.messages(usageMessage().messages()); }
+ }
+
+ /** Returns a read-only view of the subcommand map. */
+ public Map subcommands() { return Collections.unmodifiableMap(commands); }
+
+ /** Adds the specified subcommand with the specified name.
+ * If the specified subcommand does not have a ResourceBundle set, it is initialized to the ResourceBundle of this command spec.
+ * @param name subcommand name - the preferred subcommand name to register the subcommand under.
+ * 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.
+ * When this String is encountered in the command line arguments, the subcommand is invoked.
+ * @param subcommand describes the subcommand to envoke when the name is encountered on the command line
+ * @return this {@code CommandSpec} object for method chaining
+ * @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 CommandSpec addSubcommand(String name, CommandSpec subcommand) {
+ return addSubcommand(name, new CommandLine(subcommand));
+ }
+
+ /** Adds the specified subcommand with the specified name.
+ * If the specified subcommand does not have a ResourceBundle set, it is initialized to the ResourceBundle of this command spec.
+ * @param name subcommand name - the preferred subcommand name to register the subcommand under.
+ * If {@code null}, the {@linkplain CommandLine#getCommandName() name} of the specified subcommand is used;
+ * if this is also {@code null}, the first {@linkplain CommandSpec#aliases() alias} is used.
+ * When this String is encountered in the command line arguments, the subcommand is invoked.
+ * @param subCommandLine the subcommand to envoke when the name is encountered on the command line
+ * @return this {@code CommandSpec} object for method chaining
+ * @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 CommandSpec addSubcommand(String name, CommandLine subCommandLine) {
+ CommandSpec subSpec = subCommandLine.getCommandSpec();
+ String actualName = validateSubcommandName(name, subSpec);
+ Tracer t = new Tracer();
+ if (t.isDebug()) {t.debug("Adding subcommand '%s' to '%s'%n", actualName, this.qualifiedName());}
+ CommandLine previous = commands.put(actualName, subCommandLine);
+ if (previous != null && previous != subCommandLine) { throw new InitializationException("Another subcommand named '" + actualName + "' already exists for command '" + this.name() + "'"); }
+ if (subSpec.name == null) { subSpec.name(actualName); }
+ subSpec.parent(this);
+ for (String alias : subSpec.aliases()) {
+ if (t.isDebug()) {t.debug("Adding alias '%s' for subcommand '%s' to '%s'%n", alias, actualName, this.qualifiedName());}
+ previous = commands.put(alias, subCommandLine);
+ if (previous != null && previous != subCommandLine) { throw new InitializationException("Alias '" + alias + "' for subcommand '" + actualName + "' is already used by another subcommand of '" + this.name() + "'"); }
+ }
+ subSpec.initCommandHierarchyWithResourceBundle(resourceBundleBaseName(), resourceBundle());
+ return this;
+ }
+
+ private String validateSubcommandName(String name, CommandSpec subSpec) {
+ String result = name == null ? subSpec.name : name; // NOTE: check subSpec.name field, not subSpec.name()!
+ if (result == null && !subSpec.aliases.isEmpty()) {
+ Iterator iter = subSpec.aliases.iterator();
+ result = iter.next();
+ iter.remove();
+ }
+ if (result == null) {
+ throw new InitializationException("Cannot add subcommand with null name to " + this.qualifiedName());
+ }
+ return result;
+ }
+
+ private void initCommandHierarchyWithResourceBundle(String bundleBaseName, ResourceBundle rb) {
+ if (resourceBundle() == null && resourceBundleBaseName() == null) {
+ setBundle(bundleBaseName, rb);
+ }
+ for (CommandLine sub : commands.values()) { // percolate down the hierarchy
+ sub.getCommandSpec().initCommandHierarchyWithResourceBundle(bundleBaseName, rb);
+ }
+ }
+
+ /** Returns whether method commands should be added as subcommands. True by default. Used by the annotation processor.
+ * @since 4.0 */
+ public boolean isAddMethodSubcommands() { return (isAddMethodSubcommands == null) ? DEFAULT_IS_ADD_METHOD_SUBCOMMANDS : isAddMethodSubcommands; }
+ /** Sets whether method commands should be added as subcommands. True by default. Used by the annotation processor.
+ * @since 4.0 */
+ public CommandSpec setAddMethodSubcommands(Boolean addMethodSubcommands) { isAddMethodSubcommands = addMethodSubcommands; return this; }
+
+ /** Returns whether whether variables should be interpolated in String values. True by default.
+ * @since 4.0 */
+ public boolean interpolateVariables() { return (interpolateVariables == null) ? DEFAULT_INTERPOLATE_VARIABLES : interpolateVariables; }
+ /** Sets whether whether variables should be interpolated in String values. True by default.
+ * @since 4.0 */
+ public CommandSpec interpolateVariables(Boolean interpolate) { interpolateVariables = interpolate; return this; }
+
+ /** Reflects on the class of the {@linkplain #userObject() user object} and registers any command methods
+ * (class methods annotated with {@code @Command}) as subcommands.
+ *
+ * @return this {@link CommandSpec} object for method chaining
+ * @see #addMethodSubcommands(IFactory)
+ * @see #addSubcommand(String, CommandLine)
+ * @since 3.6.0
+ */
+ public CommandSpec addMethodSubcommands() { return addMethodSubcommands(new DefaultFactory()); }
+
+ /** Reflects on the class of the {@linkplain #userObject() user object} and registers any command methods
+ * (class methods annotated with {@code @Command}) as subcommands.
+ * @param factory the factory used to create instances of subcommands, converters, etc., that are registered declaratively with annotation attributes
+ * @return this {@link CommandSpec} object for method chaining
+ * @see #addSubcommand(String, CommandLine)
+ * @since 3.7.0
+ */
+ public CommandSpec addMethodSubcommands(IFactory factory) {
+ if (userObject() instanceof Method) {
+ throw new InitializationException("Cannot discover subcommand methods of this Command Method: " + userObject());
+ }
+ for (CommandLine sub : createMethodSubcommands(userObject().getClass(), factory)) {
+ addSubcommand(sub.getCommandName(), sub);
+ }
+ isAddMethodSubcommands = true;
+ return this;
+ }
+ static List createMethodSubcommands(Class> cls, IFactory factory) {
+ List result = new ArrayList();
+ for (Method method : getCommandMethods(cls, null)) {
+ result.add(new CommandLine(method, factory));
+ }
+ return result;
+ }
+
+ /** Returns the parent command of this subcommand, or {@code null} if this is a top-level command. */
+ public CommandSpec parent() { return parent; }
+
+ /** Sets the parent command of this subcommand.
+ * @return this CommandSpec for method chaining */
+ public CommandSpec parent(CommandSpec parent) { this.parent = parent; return this; }
+
+ /** Adds the specified option spec or positional parameter spec to the list of configured arguments to expect.
+ * @param arg the option spec or positional parameter spec to add
+ * @return this CommandSpec for method chaining */
+ public CommandSpec add(ArgSpec arg) { return arg.isOption() ? addOption((OptionSpec) arg) : addPositional((PositionalParamSpec) arg); }
+
+ /** Adds the specified option spec to the list of configured arguments to expect.
+ * The option's {@linkplain OptionSpec#description()} may now return Strings from this
+ * CommandSpec's {@linkplain UsageMessageSpec#messages() messages}.
+ * The option parameter's {@linkplain OptionSpec#defaultValueString()} may
+ * now return Strings from this CommandSpec's {@link CommandSpec#defaultValueProvider()} IDefaultValueProvider}.
+ * @param option the option spec to add
+ * @return this CommandSpec for method chaining
+ * @throws DuplicateOptionAnnotationsException if any of the names of the specified option is the same as the name of another option */
+ public CommandSpec addOption(OptionSpec option) {
+ Tracer tracer = new Tracer();
+ for (String name : interpolator.interpolate(option.names())) { // cannot be null or empty
+ OptionSpec existing = optionsByNameMap.put(name, option);
+ if (existing != null) { /* was: && !existing.equals(option)) {*/ // since 4.0 ArgGroups: an option cannot be in multiple groups
+ throw DuplicateOptionAnnotationsException.create(name, option, existing);
+ }
+ if (name.length() == 2 && name.startsWith("-")) { posixOptionsByKeyMap.put(name.charAt(1), option); }
+ }
+ options.add(option);
+ addOptionNegative(option, tracer);
+ return addArg(option);
+ }
+
+ private void addOptionNegative(OptionSpec option, Tracer tracer) {
+ if (option.negatable()) {
+ if (!option.typeInfo().isBoolean()) {
+ throw new InitializationException("Only boolean options can be negatable, but " + option + " is of type " + option.typeInfo().getClassName());
+ }
+ for (String name : interpolator.interpolate(option.names())) { // cannot be null or empty
+ String negatedName = negatableOptionTransformer().makeNegative(name, this);
+ if (name.equals(negatedName)) {
+ tracer.debug("Option %s is negatable, but has no negative form.%n", name);
+ } else {
+ tracer.debug("Option %s is negatable, registering negative name %s.%n", name, negatedName);
+ OptionSpec existing = negatedOptionsByNameMap.put(negatedName, option);
+ if (existing == null) { existing = optionsByNameMap.get(negatedName); }
+ if (existing != null) {
+ throw DuplicateOptionAnnotationsException.create(negatedName, option, existing);
+ }
+ }
+ }
+ }
+ }
+
+ private void resetNegativeOptionNames() {
+ Tracer tracer = new Tracer();
+ tracer.debug("Clearing negatedOptionsByNameMap...%n");
+ negatedOptionsByNameMap.clear();
+ for (OptionSpec option : options) {
+ addOptionNegative(option, tracer);
+ }
+ }
+
+ /** Adds the specified positional parameter spec to the list of configured arguments to expect.
+ * The positional parameter's {@linkplain PositionalParamSpec#description()} may
+ * now return Strings from this CommandSpec's {@linkplain UsageMessageSpec#messages() messages}.
+ * The positional parameter's {@linkplain PositionalParamSpec#defaultValueString()} may
+ * now return Strings from this CommandSpec's {@link CommandSpec#defaultValueProvider()} IDefaultValueProvider}.
+ * @param positional the positional parameter spec to add
+ * @return this CommandSpec for method chaining */
+ public CommandSpec addPositional(PositionalParamSpec positional) {
+ positionalParameters.add(positional);
+ addArg(positional);
+ if (positional.index().isUnresolved()) {
+ positional.index = Range.valueOf(interpolator.interpolate(positional.index().originalValue));
+ positional.initCapacity();
+ }
+ return this;
+ }
+ private CommandSpec addArg(ArgSpec arg) {
+ args.add(arg);
+ arg.messages(usageMessage().messages());
+ arg.commandSpec = this;
+ if (arg.arity().isUnresolved()) {
+ arg.arity = Range.valueOf(interpolator.interpolate(arg.arity().originalValue));
+ }
+ // do this last: arg.required() needs to resolve variables in arg.defaultValue()
+ if (arg.required() && arg.group() == null) { requiredArgs.add(arg); }
+ return this;
+ }
+
+ /** (INCUBATING) Removes the specified option spec or positional parameter spec from the list of configured arguments to expect.
+ * @param arg the option spec or positional parameter spec to remove
+ * @return this CommandSpec for method chaining
+ * @throws UnsupportedOperationException if the specified ArgSpec is part of a {@link ArgGroupSpec}
+ * @throws NoSuchElementException if the specified ArgSpec is not part of this {@code CommandSpec}
+ * @since 4.0 */
+ public CommandSpec remove(ArgSpec arg) {
+ if (arg.group() != null) {
+ throw new UnsupportedOperationException("Cannot remove ArgSpec that is part of an ArgGroup");
+ }
+ int removed = remove(arg, optionsByNameMap);
+ removed += remove(arg, posixOptionsByKeyMap);
+ removed += remove(arg, negatedOptionsByNameMap);
+ requiredArgs.remove(arg);
+ options.remove(arg);
+ if (positionalParameters.remove(arg)) {
+ removed++;
+ }
+ if (removed == 0) {
+ throw new NoSuchElementException(String.valueOf(arg));
+ }
+ arg.commandSpec = null;
+ arg.messages(null);
+ return this;
+ }
+ private static int remove(ArgSpec arg, Map map) {
+ int result = 0;
+ for (Iterator