diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..9be205f
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,17 @@
+# Dependabot configuration:
+# https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/configuration-options-for-dependency-updates
+
+version: 2
+updates:
+ # Maintain dependencies for Gradle dependencies
+ - package-ecosystem: "gradle"
+ directory: "/"
+ target-branch: "next"
+ schedule:
+ interval: "daily"
+ # Maintain dependencies for GitHub Actions
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ target-branch: "next"
+ schedule:
+ interval: "daily"
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..a0b6859
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,158 @@
+# GitHub Actions Workflow created for testing and preparing the plugin release in following steps:
+# - validate Gradle Wrapper,
+# - run 'test' and 'verifyPlugin' tasks,
+# - run Qodana inspections,
+# - run 'buildPlugin' task and prepare artifact for the further tests,
+# - run 'runPluginVerifier' task,
+# - create a draft release.
+#
+# Workflow is triggered on push and pull_request events.
+#
+# GitHub Actions reference: https://help.github.com/en/actions
+#
+## JBIJPPTPL
+
+name: Build
+on:
+ # Trigger the workflow on pushes to only the 'main' branch (this avoids duplicate checks being run e.g. for dependabot pull requests)
+ push:
+ branches: [main]
+ # Trigger the workflow on any pull request
+ pull_request:
+
+jobs:
+
+ # Run Gradle Wrapper Validation Action to verify the wrapper's checksum
+ # Run verifyPlugin, IntelliJ Plugin Verifier, and test Gradle tasks
+ # Build plugin and provide the artifact for the next workflow jobs
+ build:
+ name: Build
+ runs-on: ubuntu-latest
+ outputs:
+ version: ${{ steps.properties.outputs.version }}
+ changelog: ${{ steps.properties.outputs.changelog }}
+ steps:
+
+ # Check out current repository
+ - name: Fetch Sources
+ uses: actions/checkout@v2.4.0
+
+ # Validate wrapper
+ - name: Gradle Wrapper Validation
+ uses: gradle/wrapper-validation-action@v1.0.4
+
+ # Setup Java 11 environment for the next steps
+ - name: Setup Java
+ uses: actions/setup-java@v2
+ with:
+ distribution: zulu
+ java-version: 11
+ cache: gradle
+
+ # Set environment variables
+ - name: Export Properties
+ id: properties
+ shell: bash
+ run: |
+ PROPERTIES="$(./gradlew properties --console=plain -q)"
+ VERSION="$(echo "$PROPERTIES" | grep "^version:" | cut -f2- -d ' ')"
+ NAME="$(echo "$PROPERTIES" | grep "^pluginName:" | cut -f2- -d ' ')"
+ CHANGELOG="$(./gradlew getChangelog --unreleased --no-header --console=plain -q)"
+ CHANGELOG="${CHANGELOG//'%'/'%25'}"
+ CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
+ CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
+
+ echo "::set-output name=version::$VERSION"
+ echo "::set-output name=name::$NAME"
+ echo "::set-output name=changelog::$CHANGELOG"
+ echo "::set-output name=pluginVerifierHomeDir::~/.pluginVerifier"
+
+ ./gradlew listProductsReleases # prepare list of IDEs for Plugin Verifier
+
+ # Run tests
+ - name: Run Tests
+ run: ./gradlew test
+
+ # Collect Tests Result of failed tests
+ - name: Collect Tests Result
+ if: ${{ failure() }}
+ uses: actions/upload-artifact@v2
+ with:
+ name: tests-result
+ path: ${{ github.workspace }}/build/reports/tests
+
+ # Cache Plugin Verifier IDEs
+ - name: Setup Plugin Verifier IDEs Cache
+ uses: actions/cache@v2.1.7
+ with:
+ path: ${{ steps.properties.outputs.pluginVerifierHomeDir }}/ides
+ key: plugin-verifier-${{ hashFiles('build/listProductsReleases.txt') }}
+
+ # Run Verify Plugin task and IntelliJ Plugin Verifier tool
+ - name: Run Plugin Verification tasks
+ run: ./gradlew runPluginVerifier -Pplugin.verifier.home.dir=${{ steps.properties.outputs.pluginVerifierHomeDir }}
+
+ # Collect Plugin Verifier Result
+ - name: Collect Plugin Verifier Result
+ if: ${{ always() }}
+ uses: actions/upload-artifact@v2
+ with:
+ name: pluginVerifier-result
+ path: ${{ github.workspace }}/build/reports/pluginVerifier
+
+ # Run Qodana inspections
+ - name: Qodana - Code Inspection
+ uses: JetBrains/qodana-action@v4.2.5
+
+ # Prepare plugin archive content for creating artifact
+ - name: Prepare Plugin Artifact
+ id: artifact
+ shell: bash
+ run: |
+ cd ${{ github.workspace }}/build/distributions
+ FILENAME=`ls *.zip`
+ unzip "$FILENAME" -d content
+
+ echo "::set-output name=filename::${FILENAME:0:-4}"
+
+ # Store already-built plugin as an artifact for downloading
+ - name: Upload artifact
+ uses: actions/upload-artifact@v2.2.4
+ with:
+ name: ${{ steps.artifact.outputs.filename }}
+ path: ./build/distributions/content/*/*
+
+ # Prepare a draft release for GitHub Releases page for the manual verification
+ # If accepted and published, release workflow would be triggered
+ releaseDraft:
+ name: Release Draft
+ if: github.event_name != 'pull_request'
+ needs: build
+ runs-on: ubuntu-latest
+ steps:
+
+ # Check out current repository
+ - name: Fetch Sources
+ uses: actions/checkout@v2.4.0
+
+ # Remove old release drafts by using the curl request for the available releases with draft flag
+ - name: Remove Old Release Drafts
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ gh api repos/{owner}/{repo}/releases \
+ --jq '.[] | select(.draft == true) | .id' \
+ | xargs -I '{}' gh api -X DELETE repos/{owner}/{repo}/releases/{}
+
+ # Create new release draft - which is not publicly visible and requires manual acceptance
+ - name: Create Release Draft
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ gh release create v${{ needs.build.outputs.version }} \
+ --draft \
+ --title "v${{ needs.build.outputs.version }}" \
+ --notes "$(cat << 'EOM'
+ ${{ needs.build.outputs.changelog }}
+ EOM
+ )"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..0bcf2d5
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,87 @@
+# GitHub Actions Workflow created for handling the release process based on the draft release prepared
+# with the Build workflow. Running the publishPlugin task requires the PUBLISH_TOKEN secret provided.
+
+name: Release
+on:
+ release:
+ types: [prereleased, released]
+
+jobs:
+
+ # Prepare and publish the plugin to the Marketplace repository
+ release:
+ name: Publish Plugin
+ runs-on: ubuntu-latest
+ steps:
+
+ # Check out current repository
+ - name: Fetch Sources
+ uses: actions/checkout@v2.4.0
+ with:
+ ref: ${{ github.event.release.tag_name }}
+
+ # Setup Java 11 environment for the next steps
+ - name: Setup Java
+ uses: actions/setup-java@v2
+ with:
+ distribution: zulu
+ java-version: 11
+ cache: gradle
+
+ # Set environment variables
+ - name: Export Properties
+ id: properties
+ shell: bash
+ run: |
+ CHANGELOG="$(cat << 'EOM' | sed -e 's/^[[:space:]]*$//g' -e '/./,$!d'
+ ${{ github.event.release.body }}
+ EOM
+ )"
+
+ CHANGELOG="${CHANGELOG//'%'/'%25'}"
+ CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
+ CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
+
+ echo "::set-output name=changelog::$CHANGELOG"
+
+ # Update Unreleased section with the current release note
+ - name: Patch Changelog
+ if: ${{ steps.properties.outputs.changelog != '' }}
+ env:
+ CHANGELOG: ${{ steps.properties.outputs.changelog }}
+ run: |
+ ./gradlew patchChangelog --release-note="$CHANGELOG"
+
+ # Publish the plugin to the Marketplace
+ - name: Publish Plugin
+ env:
+ PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }}
+ run: ./gradlew publishPlugin
+
+ # Upload artifact as a release asset
+ - name: Upload Release Asset
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: gh release upload ${{ github.event.release.tag_name }} ./build/distributions/*
+
+ # Create pull request
+ - name: Create Pull Request
+ if: ${{ steps.properties.outputs.changelog != '' }}
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ VERSION="${{ github.event.release.tag_name }}"
+ BRANCH="changelog-update-$VERSION"
+
+ git config user.email "action@github.com"
+ git config user.name "GitHub Action"
+
+ git checkout -b $BRANCH
+ git commit -am "Changelog update - $VERSION"
+ git push --set-upstream origin $BRANCH
+
+ gh pr create \
+ --title "Changelog update - \`$VERSION\`" \
+ --body "Current pull request contains patched \`CHANGELOG.md\` file for the \`$VERSION\` version." \
+ --base main \
+ --head $BRANCH
diff --git a/.github/workflows/run-ui-tests.yml b/.github/workflows/run-ui-tests.yml
new file mode 100644
index 0000000..3108cf1
--- /dev/null
+++ b/.github/workflows/run-ui-tests.yml
@@ -0,0 +1,60 @@
+# GitHub Actions Workflow for launching UI tests on Linux, Windows, and Mac in the following steps:
+# - prepare and launch IDE with your plugin and robot-server plugin, which is needed to interact with UI
+# - wait for IDE to start
+# - run UI tests with separate Gradle task
+#
+# Please check https://github.com/JetBrains/intellij-ui-test-robot for information about UI tests with IntelliJ Platform
+#
+# Workflow is triggered manually.
+
+name: Run UI Tests
+on:
+ workflow_dispatch
+
+jobs:
+
+ testUI:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - os: ubuntu-latest
+ runIde: |
+ export DISPLAY=:99.0
+ Xvfb -ac :99 -screen 0 1920x1080x16 &
+ gradle runIdeForUiTests &
+ - os: windows-latest
+ runIde: start gradlew.bat runIdeForUiTests
+ - os: macos-latest
+ runIde: ./gradlew runIdeForUiTests &
+
+ steps:
+
+ # Check out current repository
+ - name: Fetch Sources
+ uses: actions/checkout@v2.4.0
+
+ # Setup Java 11 environment for the next steps
+ - name: Setup Java
+ uses: actions/setup-java@v2
+ with:
+ distribution: zulu
+ java-version: 11
+ cache: gradle
+
+ # Run IDEA prepared for UI testing
+ - name: Run IDE
+ run: ${{ matrix.runIde }}
+
+ # Wait for IDEA to be started
+ - name: Health Check
+ uses: jtalk/url-health-check-action@v2
+ with:
+ url: http://127.0.0.1:8082
+ max-attempts: 15
+ retry-delay: 30s
+
+ # Run tests
+ - name: Tests
+ run: ./gradlew test
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e2e5d94
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+.gradle
+.idea
+.qodana
+build
diff --git a/.run/Run IDE for UI Tests.run.xml b/.run/Run IDE for UI Tests.run.xml
new file mode 100644
index 0000000..9b028c3
--- /dev/null
+++ b/.run/Run IDE for UI Tests.run.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
Support for developing mosn plugin applications. Mosn mecha gives developers an easy and productive
+way to build and deploy cross-platform.
Adds Mosn Plugin to File | New | Project...
+
Some example plugin programs are provided:
++ * CommandLine interpreter that uses reflection to initialize an annotated user object with values obtained from the + * command line arguments. + *
+ * The full user manual is hosted at https://picocli.info. + *
+ * An example that implements {@code Callable} and uses the {@link #execute(String...) CommandLine.execute} convenience API to run in a single line of code: + *
+ *+ * @Command(name = "checksum", mixinStandardHelpOptions = true, version = "checksum 4.0", + * description = "Prints the checksum (SHA-1 by default) of a file to STDOUT.") + * class CheckSum implements Callable<Integer> { + * + * @Parameters(index = "0", description = "The file whose checksum to calculate.") + * private File file; + * + * @Option(names = {"-a", "--algorithm"}, description = "MD5, SHA-1, SHA-256, ...") + * private String algorithm = "SHA-1"; + * + * @Override + * public Integer call() throws Exception { // your business logic goes here... + * byte[] fileContents = Files.readAllBytes(file.toPath()); + * byte[] digest = MessageDigest.getInstance(algorithm).digest(fileContents); + * System.out.printf("%0" + (digest.length*2) + "x%n", new BigInteger(1,digest)); + * return 0; + * } + * + * // CheckSum implements Callable, so parsing, error handling and handling user + * // requests for usage help or version help can be done with one line of code. + * public static void main(String[] args) { + * int exitCode = new CommandLine(new CheckSum()).execute(args); + * System.exit(exitCode); + * } + * } + *+ *
Another example where the application calls {@code parseArgs} and takes responsibility + * for error handling and checking whether the user requested help:
+ *import static io.mosn.coder.cli.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 + *+ *
+ *
+ *
+ *
+ *
The specified object may be a {@link CommandSpec CommandSpec} object, or it may be a {@code @Command}-annotated + * user object with {@code @Option} and {@code @Parameters}-annotated fields and methods, in which case picocli automatically + * constructs a {@code CommandSpec} from this user object. + *
If the specified command object is an interface {@code Class} with {@code @Option} and {@code @Parameters}-annotated methods, + * picocli creates a {@link java.lang.reflect.Proxy Proxy} whose methods return the matched command line values. + * If the specified command object is a concrete {@code Class}, picocli delegates to the default factory to get an instance. + *
+ * If the specified object implements {@code Runnable} or {@code Callable}, or if it is a {@code Method} object, + * the command can be run as an application in a single line of code by using the + * {@link #execute(String...) execute} method to omit some boilerplate code for handling help requests and invalid input. + * See {@link #getCommandMethods(Class, String) getCommandMethods} for a convenient way to obtain a command {@code Method}. + *
+ * When the {@link #parseArgs(String...)} method is called, the {@link CommandSpec CommandSpec} object will be + * initialized based on command line arguments. If the commandSpec is created from an annotated user object, this + * user object will be initialized based on the command line arguments. + *
+ * @param command an annotated user object or a {@code CommandSpec} object to initialize from the command line arguments + * @throws InitializationException if the specified command object does not have a {@link Command}, {@link Option} or {@link Parameters} annotation + */ + public CommandLine(Object command) { + this(command, new DefaultFactory()); + } + /** + * Constructs a new {@code CommandLine} interpreter with the specified object (which may be an annotated user object or a {@link CommandSpec CommandSpec}) and object factory. + *The specified object may be a {@link CommandSpec CommandSpec} object, or it may be a {@code @Command}-annotated + * user object with {@code @Option} and {@code @Parameters}-annotated fields and methods, in which case picocli automatically + * constructs a {@code CommandSpec} from this user object. + *
If the specified command object is an interface {@code Class} with {@code @Option} and {@code @Parameters}-annotated methods, + * picocli creates a {@link java.lang.reflect.Proxy Proxy} whose methods return the matched command line values. + * If the specified command object is a concrete {@code Class}, picocli delegates to the {@linkplain IFactory factory} to get an instance. + *
+ * If the specified object implements {@code Runnable} or {@code Callable}, or if it is a {@code Method} object, + * the command can be run as an application in a single line of code by using the + * {@link #execute(String...) execute} method to omit some boilerplate code for handling help requests and invalid input. + * See {@link #getCommandMethods(Class, String) getCommandMethods} for a convenient way to obtain a command {@code Method}. + *
+ * When the {@link #parseArgs(String...)} method is called, the {@link CommandSpec CommandSpec} object will be + * initialized based on command line arguments. If the commandSpec is created from an annotated user object, this + * user object will be initialized based on the command line arguments. + *
+ * @param command an annotated user object or a {@code CommandSpec} object to initialize from the command line arguments + * @param factory the factory used to create instances of {@linkplain Command#subcommands() subcommands}, {@linkplain Option#converter() converters}, etc., that are registered declaratively with annotation attributes + * @throws InitializationException if the specified command object does not have a {@link Command}, {@link Option} or {@link Parameters} annotation + * @since 2.2 */ + public CommandLine(Object command, IFactory factory) { + this(command, factory, true); + } + + private CommandLine(Object command, IFactory factory, boolean userCalled) { + this.factory = Assert.notNull(factory, "factory"); + interpreter = new Interpreter(); + commandSpec = CommandSpec.forAnnotatedObject(command, factory); + commandSpec.commandLine(this); + if (userCalled) { this.applyModelTransformations(); } + commandSpec.validate(); + if (commandSpec.unmatchedArgsBindings().size() > 0) { setUnmatchedArgumentsAllowed(true); } + } + + /** Apply transformers to command spec recursively. */ + private void applyModelTransformations() { + if (commandSpec.modelTransformer != null) { + commandSpec = commandSpec.modelTransformer.transform(commandSpec); + } + for (CommandLine cmd : getSubcommands().values()) { + cmd.applyModelTransformations(); + } + } + + private CommandLine copy() { + CommandLine result = new CommandLine(commandSpec.copy(), factory); // create a new sub-hierarchy + result.err = err; + result.out = out; + result.colorScheme = colorScheme; + result.executionStrategy = executionStrategy; + result.exitCodeExceptionMapper = exitCodeExceptionMapper; + result.executionExceptionHandler = executionExceptionHandler; + result.parameterExceptionHandler = parameterExceptionHandler; + + result.interpreter.converterRegistry.clear(); + result.interpreter.converterRegistry.putAll(interpreter.converterRegistry); + return result; + } + + /** + * Returns the {@code CommandSpec} model that this {@code CommandLine} was constructed with. + * @return the {@code CommandSpec} model + * @since 3.0 */ + public CommandSpec getCommandSpec() { return commandSpec; } + + /** + * Adds the options and positional parameters in the specified mixin to this command. + *The specified object may be a {@link CommandSpec CommandSpec} object, or it may be a user object with + * {@code @Option} and {@code @Parameters}-annotated fields, in which case picocli automatically + * constructs a {@code CommandSpec} from this user object. + *
+ * @param name the name by which the mixin object may later be retrieved + * @param mixin an annotated user object or a {@link CommandSpec CommandSpec} object whose options and positional parameters to add to this command + * @return this CommandLine object, to allow method chaining + * @since 3.0 */ + public CommandLine addMixin(String name, Object mixin) { + getCommandSpec().addMixin(name, CommandSpec.forAnnotatedObject(mixin, factory)); + return this; + } + + /** + * Returns a map of user objects whose options and positional parameters were added to ("mixed in" with) this command. + * @return a new Map containing the user objects mixed in with this command. If {@code CommandSpec} objects without + * user objects were programmatically added, use the {@link CommandSpec#mixins() underlying model} directly. + * @since 3.0 */ + public Map+ * CommandLine commandLine = new CommandLine(new Git()) + * .addSubcommand("status", new GitStatus()) + * .addSubcommand("commit", new GitCommit(); + * .addSubcommand("add", new GitAdd()) + * .addSubcommand("branch", new GitBranch()) + * .addSubcommand("checkout", new GitCheckout()) + * //... + * ; + *+ * + *
The specified object can be an annotated object or a + * {@code CommandLine} instance with its own nested subcommands. For example:
+ *+ * CommandLine commandLine = new CommandLine(new MainCommand()) + * .addSubcommand("cmd1", new ChildCommand1()) // subcommand + * .addSubcommand("cmd2", new ChildCommand2()) + * .addSubcommand("cmd3", new CommandLine(new ChildCommand3()) // subcommand with nested sub-subcommands + * .addSubcommand("cmd3sub1", new GrandChild3Command1()) + * .addSubcommand("cmd3sub2", new GrandChild3Command2()) + * .addSubcommand("cmd3sub3", new CommandLine(new GrandChild3Command3()) // deeper nesting + * .addSubcommand("cmd3sub3sub1", new GreatGrandChild3Command3_1()) + * .addSubcommand("cmd3sub3sub2", new GreatGrandChild3Command3_2()) + * ) + * ); + *+ *
The default type converters are available on all subcommands and nested sub-subcommands, but custom type + * converters are registered only with the subcommand hierarchy as it existed when the custom type was registered. + * To ensure a custom type converter is available to all subcommands, register the type converter last, after + * adding subcommands.
+ *See also the {@link Command#subcommands()} annotation to register subcommands declaratively.
+ * + * @param name the string to recognize on the command line as a subcommand. + * If {@code null}, the {@linkplain CommandSpec#name() name} of the specified subcommand is used; + * if this is also {@code null}, the first {@linkplain CommandSpec#aliases() alias} is used. + * @param command the object to initialize with command line arguments following the subcommand name. + * This may be a {@code Class} that has a {@code @Command} annotation, or an instance of such a + * class, or a {@code CommandSpec} or {@code CommandLine} instance with its own (nested) subcommands. + * @return this CommandLine object, to allow method chaining + * @see #registerConverter(Class, ITypeConverter) + * @since 0.9.7 + * @see Command#subcommands() + * @throws InitializationException if the specified name is {@code null}, and no alternative name could be found, + * or if another subcommand was already registered under the same name, or if one of the aliases + * of the specified subcommand was already used by another subcommand. + */ + public CommandLine addSubcommand(String name, Object command) { + return addSubcommand(name, command, new String[0]); + } + + /** Registers a subcommand with the specified name and all specified aliases. See also {@link #addSubcommand(String, Object)}. + * @param name the string to recognize on the command line as a subcommand. + * If {@code null}, the {@linkplain CommandSpec#name() name} of the specified subcommand is used; + * if this is also {@code null}, the first {@linkplain CommandSpec#aliases() alias} is used. + * @param command the object to initialize with command line arguments following the subcommand name. + * This may be a {@code Class} that has a {@code @Command} annotation, or an instance of such a + * class, or a {@code CommandSpec} or {@code CommandLine} instance with its own (nested) subcommands. + * @param aliases zero or more alias names that are also recognized on the command line as this subcommand + * @return this CommandLine object, to allow method chaining + * @since 3.1 + * @see #addSubcommand(String, Object) + * @throws InitializationException if the specified name is {@code null}, and no alternative name could be found, + * or if another subcommand was already registered under the same name, or if one of the aliases + * of the specified subcommand was already used by another subcommand. + */ + public CommandLine addSubcommand(String name, Object command, String... aliases) { + CommandLine subcommandLine = toCommandLine(command, factory); + subcommandLine.getCommandSpec().aliases.addAll(Arrays.asList(aliases)); + getCommandSpec().addSubcommand(name, subcommandLine); + return this; + } + /** Returns a map with the subcommands {@linkplain #addSubcommand(String, Object) registered} on this instance. + * @return a map with the registered subcommands + * @since 0.9.7 + */ + public MapThe 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): + *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+ * 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 MapThe 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(MapThe specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param adjustForWideChars if true, wide Chinese, Japanese and Korean characters are counted as double the size of other characters for line-breaking purposes + * @since 4.0 */ + public CommandLine setAdjustLineBreaksForWideCJKCharacters(boolean adjustForWideChars) { + getCommandSpec().usageMessage().adjustLineBreaksForWideCJKCharacters(adjustForWideChars); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setAdjustLineBreaksForWideCJKCharacters(adjustForWideChars); + } + return this; + } + + /** Returns whether the value of boolean flag options should be "toggled" when the option is matched. + * From 4.0, this is {@code false} by default, and when a flag option is specified on the command line picocli + * will set its value to the opposite of its default value. + * If this method returns {@code true}, flags are toggled, so if the value is {@code true} it is + * set to {@code false}, and when the value is {@code false} it is set to {@code true}. + * When toggling is enabled, specifying a flag option twice on the command line will have no effect because they cancel each other out. + * @return {@code true} the value of boolean flag options should be "toggled" when the option is matched, {@code false} otherwise + * @since 3.0 + */ + public boolean isToggleBooleanFlags() { + return getCommandSpec().parser().toggleBooleanFlags(); + } + + /** Sets whether the value of boolean flag options should be "toggled" when the option is matched. The default is {@code false}, + * and when a flag option is specified on the command line picocli will set its value to the opposite of its default value. + *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param newValue the new setting + * @return this {@code CommandLine} object, to allow method chaining + * @since 3.0 + */ + public CommandLine setToggleBooleanFlags(boolean newValue) { + getCommandSpec().parser().toggleBooleanFlags(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setToggleBooleanFlags(newValue); + } + return this; + } + + /** Returns whether variables should be interpolated in String values. The default is {@code true}. + * @since 4.0 */ + public boolean isInterpolateVariables() { return getCommandSpec().interpolateVariables(); } + /** Sets whether variables should be interpolated in String values. The default is {@code true}. + *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @since 4.0 */ + public CommandLine setInterpolateVariables(boolean interpolate) { + getCommandSpec().interpolateVariables(interpolate); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setInterpolateVariables(interpolate); + } + return this; + } + + /** Returns whether options for single-value fields can be specified multiple times on the command line. + * The default is {@code false} and a {@link OverwrittenOptionException} is thrown if this happens. + * When {@code true}, the last specified value is retained. + * @return {@code true} if options for single-value fields can be specified multiple times on the command line, {@code false} otherwise + * @since 0.9.7 + */ + public boolean isOverwrittenOptionsAllowed() { + return getCommandSpec().parser().overwrittenOptionsAllowed(); + } + + /** Sets whether options for single-value fields can be specified multiple times on the command line without a {@link OverwrittenOptionException} being thrown. + * The default is {@code false}. + *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param newValue the new setting + * @return this {@code CommandLine} object, to allow method chaining + * @since 0.9.7 + */ + public CommandLine setOverwrittenOptionsAllowed(boolean newValue) { + getCommandSpec().parser().overwrittenOptionsAllowed(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setOverwrittenOptionsAllowed(newValue); + } + return this; + } + + /** Returns whether the parser accepts clustered short options. The default is {@code true}. + * @return {@code true} if short options like {@code -x -v -f SomeFile} can be clustered together like {@code -xvfSomeFile}, {@code false} otherwise + * @since 3.0 */ + public boolean isPosixClusteredShortOptionsAllowed() { return getCommandSpec().parser().posixClusteredShortOptionsAllowed(); } + + /** Sets whether short options like {@code -x -v -f SomeFile} can be clustered together like {@code -xvfSomeFile}. The default is {@code true}. + *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param newValue the new setting + * @return this {@code CommandLine} object, to allow method chaining + * @since 3.0 + */ + public CommandLine setPosixClusteredShortOptionsAllowed(boolean newValue) { + getCommandSpec().parser().posixClusteredShortOptionsAllowed(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setPosixClusteredShortOptionsAllowed(newValue); + } + return this; + } + + /** Returns whether the parser should ignore case when converting arguments to {@code enum} values. The default is {@code false}. + * @return {@code true} if enum values can be specified that don't match the {@code toString()} value of the enum constant, {@code false} otherwise; + * e.g., for an option of type java.time.DayOfWeek, + * values {@code MonDaY}, {@code monday} and {@code MONDAY} are all recognized if {@code true}. + * @since 3.4 */ + public boolean isCaseInsensitiveEnumValuesAllowed() { return getCommandSpec().parser().caseInsensitiveEnumValuesAllowed(); } + + /** Sets whether the parser should ignore case when converting arguments to {@code enum} values. The default is {@code false}. + * When set to true, for example, for an option of type java.time.DayOfWeek, + * values {@code MonDaY}, {@code monday} and {@code MONDAY} are all recognized if {@code true}. + *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param newValue the new setting + * @return this {@code CommandLine} object, to allow method chaining + * @since 3.4 + */ + public CommandLine setCaseInsensitiveEnumValuesAllowed(boolean newValue) { + getCommandSpec().parser().caseInsensitiveEnumValuesAllowed(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setCaseInsensitiveEnumValuesAllowed(newValue); + } + return this; + } + + /** Returns whether the parser should trim quotes from command line arguments. The default is + * read from the system property "picocli.trimQuotes" and will be {@code true} if the property is present and empty, + * or if its value is "true". + *If this property is set to {@code true}, the parser will remove quotes from the command line arguments, as follows:
+ *If this property is set to {@code true}, the parser will remove quotes from the command line arguments, as follows:
+ *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ *Calling this method will cause the "picocli.trimQuotes" property to have no effect.
+ * @param newValue the new setting + * @return this {@code CommandLine} object, to allow method chaining + * @see ParserSpec#trimQuotes(boolean) + * @since 3.7 + */ + public CommandLine setTrimQuotes(boolean newValue) { + getCommandSpec().parser().trimQuotes(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setTrimQuotes(newValue); + } + return this; + } + + /** Returns whether the parser is allowed to split quoted Strings or not. The default is {@code false}, + * so quotes are respected: quoted strings are treated as a single value that should not be broken up. + *+ * For example, take a single command line parameter {@code "a,b","x,y"}. With a comma split regex, the default of {@code splitQuotedStrings = false} + * means that this value will be split into two strings: {@code "a,b"} and {@code "x,y"}. This is usually what you want. + *
+ * If {@code splitQuotedStrings} is set to {@code true}, quotes are not respected, and the value is split up into four parts: + * the first is {@code "a}, the second is {@code b"}, the third is {@code "x}, and the last part is {@code y"}. This is generally not what you want. + *
+ * @deprecated Most applications should not change the default. The rare application that does need to split parameter values + * without respecting quotes should use {@link ParserSpec#splitQuotedStrings(boolean)}. + * @return {@code true} if the parser is allowed to split quoted Strings, {@code false} otherwise; + * @see ArgSpec#splitRegex() + * @see ParserSpec#splitQuotedStrings() + * @since 3.7 */ + @Deprecated public boolean isSplitQuotedStrings() { return getCommandSpec().parser().splitQuotedStrings(); } + + /** Sets whether the parser is allowed to split quoted Strings. The default is {@code false}, + * so quotes are respected: quoted strings are treated as a single value that should not be broken up. + *+ * For example, take a single command line parameter {@code "a,b","x,y"}. With a comma split regex, the default of {@code splitQuotedStrings = false} + * means that this value will be split into two strings: {@code "a,b"} and {@code "x,y"}. This is usually what you want. + *
+ * However, if {@code splitQuotedStrings} is set to {@code true}, quotes are not respected, and the value is split up into four parts: + * the first is {@code "a}, the second is {@code b"}, the third is {@code "x}, and the last part is {@code y"}. This is generally not what you want. + *
+ *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @deprecated Most applications should not change the default. The rare application that does need to split parameter values + * without respecting quotes should use {@link ParserSpec#splitQuotedStrings(boolean)}. + * @param newValue the new setting + * @return this {@code CommandLine} object, to allow method chaining + * @see ArgSpec#splitRegex() + * @see ParserSpec#splitQuotedStrings(boolean) + * @since 3.7 + */ + @Deprecated public CommandLine setSplitQuotedStrings(boolean newValue) { + getCommandSpec().parser().splitQuotedStrings(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setSplitQuotedStrings(newValue); + } + return this; + } + + /** Returns the end-of-options delimiter that signals that the remaining command line arguments should be treated as positional parameters. + * @return the end-of-options delimiter. The default is {@code "--"}. + * @since 3.5 */ + public String getEndOfOptionsDelimiter() { return getCommandSpec().parser().endOfOptionsDelimiter(); } + + /** Sets the end-of-options delimiter that signals that the remaining command line arguments should be treated as positional parameters. + * @param delimiter the end-of-options delimiter; must not be {@code null}. The default is {@code "--"}. + * @return this {@code CommandLine} object, to allow method chaining + * @since 3.5 */ + public CommandLine setEndOfOptionsDelimiter(String delimiter) { + getCommandSpec().parser().endOfOptionsDelimiter(delimiter); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setEndOfOptionsDelimiter(delimiter); + } + return this; + } + + /** Returns whether upper case and lower case should be ignored when matching subcommands. The default is {@code false}. + * @return {@code true} if subcommands can be matched when they differ only in case from the {@code getCommandName()} value of a registered one, {@code false} otherwise. + * For example, if true, for a subcommand with name {@code help}, inputs like {@code help}, {@code HeLp} and {@code HELP} are all recognized. + * @since 4.3 */ + public boolean isSubcommandsCaseInsensitive() { return getCommandSpec().subcommandsCaseInsensitive(); } + + /** Sets whether upper case and lower case should be ignored when matching subcommands. The default is {@code false}. + * For example, when set to {@code true}, for a subcommand with name {@code help}, inputs like {@code help}, {@code HeLp} and {@code HELP} are all recognized. + *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param newValue the new setting + * @return this {@code CommandLine} object, to allow method chaining + * @since 4.3 + */ + public CommandLine setSubcommandsCaseInsensitive(boolean newValue) { + getCommandSpec().subcommandsCaseInsensitive(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setSubcommandsCaseInsensitive(newValue); + } + return this; + } + + /** Returns whether upper case and lower case should be ignored when matching option names. The default is {@code false}. + * @return {@code true} if options can be matched when they differ only in case from the {@code names()} value of a registered one, {@code false} otherwise; + * For example, if true, for an option with name {@code -h}, inputs like {@code -h}, {@code -H} are both recognized. + * @since 4.3 */ + public boolean isOptionsCaseInsensitive() { return getCommandSpec().optionsCaseInsensitive(); } + + /** Sets whether upper case and lower case should be ignored when matching option names. The default is {@code false}. + * For example, when set to {@code true}, for an option with name {@code -h}, inputs like {@code -h}, {@code -H} are both recognized. + *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * Note that changing case sensitivity will also change the case sensitivity of {@linkplain Option#negatable() negatable} options: + * any custom {@link INegatableOptionTransformer} that was previously installed will be replaced by the case-insensitive + * version of the default transformer. To ensure your custom transformer is used, install it last, after changing case sensitivity. + * @param newValue the new setting + * @return this {@code CommandLine} object, to allow method chaining + * @since 4.3 + */ + public CommandLine setOptionsCaseInsensitive(boolean newValue) { + getCommandSpec().optionsCaseInsensitive(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setOptionsCaseInsensitive(newValue); + } + return this; + } + + /** Returns whether abbreviation of subcommands should be allowed when matching subcommands. The default is {@code false}. + * @return {@code true} if subcommands can be matched when they are abbrevations of the {@code getCommandName()} value of a registered one, {@code false} otherwise. + * For example, if true, for a subcommand with name {@code helpCommand}, inputs like {@code h}, {@code h-c} and {@code hC} are all recognized. + * @since 4.4 */ + public boolean isAbbreviatedSubcommandsAllowed() { + return getCommandSpec().parser().abbreviatedSubcommandsAllowed(); + } + + /** Sets whether abbreviated subcommands should be matched. The default is {@code false}. + * For example, when set to {@code true}, for a subcommand {@code helpCommand}, inputs like {@code h}, {@code h-c} and {@code hC} are all recognized. + *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param newValue the new setting + * @return this {@code CommandLine} object, to allow method chaining + * @since 4.4 + */ + public CommandLine setAbbreviatedSubcommandsAllowed(boolean newValue) { + getCommandSpec().parser().abbreviatedSubcommandsAllowed(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setAbbreviatedSubcommandsAllowed(newValue); + } + return this; + } + + /** Returns whether abbreviation of option names should be allowed when matching options. The default is {@code false}. + * @return {@code true} if options can be matched when they are abbrevations of the {@code names()} value of a registered one, {@code false} otherwise. + * For example, if true, for a subcommand with name {@code --helpMe}, inputs like {@code --h}, {@code --h-m} and {@code --hM} are all recognized. + * @since 4.4 */ + public boolean isAbbreviatedOptionsAllowed() { + return getCommandSpec().parser().abbreviatedOptionsAllowed(); + } + + /** Sets whether abbreviated option names should be matched. The default is {@code false}. + * For example, when set to {@code true}, for an option with name {@code --helpMe}, inputs like {@code --h}, {@code --h-m} and {@code --hM} are all recognized. + *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param newValue the new setting + * @return this {@code CommandLine} object, to allow method chaining + * @since 4.4 + */ + public CommandLine setAbbreviatedOptionsAllowed(boolean newValue) { + getCommandSpec().parser().abbreviatedOptionsAllowed(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setAbbreviatedOptionsAllowed(newValue); + } + return this; + } + + /** Returns the default value provider for the command, or {@code null} if none has been set. + * @return the default value provider for this command, or {@code null} + * @since 3.6 + * @see Command#defaultValueProvider() + * @see CommandSpec#defaultValueProvider() + * @see ArgSpec#defaultValueString() + */ + public IDefaultValueProvider getDefaultValueProvider() { + return getCommandSpec().defaultValueProvider(); + } + + /** Sets a default value provider for the command and sub-commands + *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * sub-commands and nested sub-subcommands at the moment this method is called. Sub-commands added + * later will have the default setting. To ensure a setting is applied to all + * sub-commands, call the setter last, after adding sub-commands.
+ * @param newValue the default value provider to use + * @return this {@code CommandLine} object, to allow method chaining + * @since 3.6 + */ + public CommandLine setDefaultValueProvider(IDefaultValueProvider newValue) { + getCommandSpec().defaultValueProvider(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setDefaultValueProvider(newValue); + } + return this; + } + + /** Returns whether the parser interprets the first positional parameter as "end of options" so the remaining + * arguments are all treated as positional parameters. The default is {@code false}. + * @return {@code true} if all values following the first positional parameter should be treated as positional parameters, {@code false} otherwise + * @since 2.3 + */ + public boolean isStopAtPositional() { + return getCommandSpec().parser().stopAtPositional(); + } + + /** Sets whether the parser interprets the first positional parameter as "end of options" so the remaining + * arguments are all treated as positional parameters. The default is {@code false}. + *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param newValue {@code true} if all values following the first positional parameter should be treated as positional parameters, {@code false} otherwise + * @return this {@code CommandLine} object, to allow method chaining + * @since 2.3 + */ + public CommandLine setStopAtPositional(boolean newValue) { + getCommandSpec().parser().stopAtPositional(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setStopAtPositional(newValue); + } + return this; + } + + /** Returns whether the parser should stop interpreting options and positional parameters as soon as it encounters an + * unmatched option. Unmatched options are arguments that look like an option but are not one of the known options, or + * positional arguments for which there is no available slots (the command has no positional parameters or their size is limited). + * The default is {@code false}. + *Setting this flag to {@code true} automatically sets the {@linkplain #isUnmatchedArgumentsAllowed() unmatchedArgumentsAllowed} flag to {@code true} also.
+ * @return {@code true} when an unmatched option should result in the remaining command line arguments to be added to the + * {@linkplain #getUnmatchedArguments() unmatchedArguments list} + * @since 2.3 + */ + public boolean isStopAtUnmatched() { + return getCommandSpec().parser().stopAtUnmatched(); + } + + /** Sets whether the parser should stop interpreting options and positional parameters as soon as it encounters an + * unmatched option. Unmatched options are arguments that look like an option but are not one of the known options, or + * positional arguments for which there is no available slots (the command has no positional parameters or their size is limited). + * The default is {@code false}. + *Setting this flag to {@code true} automatically sets the {@linkplain #setUnmatchedArgumentsAllowed(boolean) unmatchedArgumentsAllowed} flag to {@code true} also.
+ *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param newValue {@code true} when an unmatched option should result in the remaining command line arguments to be added to the + * {@linkplain #getUnmatchedArguments() unmatchedArguments list} + * @return this {@code CommandLine} object, to allow method chaining + * @since 2.3 + */ + public CommandLine setStopAtUnmatched(boolean newValue) { + getCommandSpec().parser().stopAtUnmatched(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setStopAtUnmatched(newValue); + } + if (newValue) { setUnmatchedArgumentsAllowed(true); } + return this; + } + /** Returns whether options can have parameter values that match subcommand names or aliases, + * or whether such values should be rejected with a missing parameter exception. + * The default is {@code false}, so by default input like {@code -x=subcommand} is rejected if {@code -x} is an option that takes a String parameter, and {@code subcommand} is a subcommand of this command. + * @return {@code true} when options can have parameter values that match subcommand names or aliases, {@code false} when such values should be rejected with a missing parameter exception + * @since 4.7.0 + * @see ParserSpec#allowSubcommandsAsOptionParameters() + */ + public boolean isAllowSubcommandsAsOptionParameters() { + return getCommandSpec().parser().allowSubcommandsAsOptionParameters(); + } + /** Sets whether options can have parameter values that match subcommand names or aliases, or whether such values should be rejected with a missing parameter exception. + * The default is {@code false}, so by default + * input like {@code -x=subcommand} is rejected if {@code -x} is an option that takes a String parameter, and {@code subcommand} is a subcommand of this command. + *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param newValue the new setting. When {@code true}, options can have parameter values that match subcommand names or aliases, when {@code false}, such values are rejected with a missing parameter exception + * @return this {@code CommandLine} object, to allow method chaining + * @since 4.7.0 + * @see ParserSpec#allowSubcommandsAsOptionParameters(boolean) + */ + public CommandLine setAllowSubcommandsAsOptionParameters(boolean newValue) { + getCommandSpec().parser().allowSubcommandsAsOptionParameters(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setAllowSubcommandsAsOptionParameters(newValue); + } + return this; + } + /** Returns whether options can have parameter values that match the name of an option in this command, + * or whether such values should be rejected with a missing parameter exception. + * The default is {@code false}, so by default input like {@code -x=--some-option} is rejected if {@code -x} is an option that takes a String parameter, and {@code --some-option} is an option of this command. + *This method only considers actual options of this command, as opposed to {@link #isUnmatchedOptionsAllowedAsOptionParameters()}, which considers values that resemble options.
+ * @return {@code true} when options can have parameter values that match the name of an option in this command, {@code false} when such values should be rejected with a missing parameter exception + * @since 4.7.0 + * @see #isUnmatchedOptionsAllowedAsOptionParameters() + * @see ParserSpec#allowOptionsAsOptionParameters() + */ + public boolean isAllowOptionsAsOptionParameters() { + return getCommandSpec().parser().allowOptionsAsOptionParameters(); + } + /** Sets whether options can have parameter values that match the name of an option in this command, or whether such values should be rejected with a missing parameter exception. + * The default is {@code false}, so by default + * input like {@code -x=--some-option} is rejected if {@code -x} is an option that takes a String parameter, and {@code --some-option} is an option of this command. + *This method only considers actual options of this command, as opposed to {@link #setUnmatchedOptionsAllowedAsOptionParameters(boolean)}, which considers values that resemble options.
+ *Use with caution! When set to {@code true}, any option in the command will consume the maximum number of arguments possible for its arity. + * This means that an option with {@code arity = "*"} will consume all command line arguments following that option. + * If this is not what you want, consider custom parameter processing.
+ *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param newValue the new setting. When {@code true}, options can have parameter values that match the name of an option in this command, when {@code false}, such values are rejected with a missing parameter exception + * @return this {@code CommandLine} object, to allow method chaining + * @since 4.7.0 + * @see #setUnmatchedOptionsAllowedAsOptionParameters(boolean) + * @see ParserSpec#allowOptionsAsOptionParameters(boolean) + */ + public CommandLine setAllowOptionsAsOptionParameters(boolean newValue) { + getCommandSpec().parser().allowOptionsAsOptionParameters(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setAllowOptionsAsOptionParameters(newValue); + } + return this; + } + + /** Returns whether options can have parameter values that resemble an option, or whether such values should be rejected as unknown options. + * The default is {@code true}, so by default input like {@code -x=-unknown} is accepted if {@code -x} is an option that takes a String parameter. + *This method only considers values that resemble options, as opposed to {@link #isAllowOptionsAsOptionParameters()}, which considers actual options of this command.
+ * @return {@code true} when options can have parameter values that resemble an option, {@code false} when such values should be rejected as unknown options + * @since 4.4 + * @see #isAllowOptionsAsOptionParameters() + * @see ParserSpec#unmatchedOptionsAllowedAsOptionParameters() + */ + public boolean isUnmatchedOptionsAllowedAsOptionParameters() { + return getCommandSpec().parser().unmatchedOptionsAllowedAsOptionParameters(); + } + + /** Sets whether options can have parameter values that resemble an option, or whether such values should be rejected as unknown options. + * The default is {@code true}, so by default + * input like {@code -x=-unknown} is accepted if {@code -x} is an option that takes a String parameter. + *This method only considers values that resemble options, as opposed to {@link #setAllowOptionsAsOptionParameters(boolean)}, which considers actual options of this command.
+ *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param newValue the new setting. When {@code true}, options can have parameter values that resemble an option, when {@code false}, such values are rejected as unknown options + * @return this {@code CommandLine} object, to allow method chaining + * @since 4.4 + * @see #setAllowOptionsAsOptionParameters(boolean) + * @see ParserSpec#unmatchedOptionsAllowedAsOptionParameters(boolean) + */ + public CommandLine setUnmatchedOptionsAllowedAsOptionParameters(boolean newValue) { + getCommandSpec().parser().unmatchedOptionsAllowedAsOptionParameters(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setUnmatchedOptionsAllowedAsOptionParameters(newValue); + } + return this; + } + /** Returns whether arguments on the command line that resemble an option should be treated as positional parameters. + * The default is {@code false} and the parser behaviour depends on {@link #isUnmatchedArgumentsAllowed()}. + * @return {@code true} arguments on the command line that resemble an option should be treated as positional parameters, {@code false} otherwise + * @see #getUnmatchedArguments() + * @since 3.0 + */ + public boolean isUnmatchedOptionsArePositionalParams() { + return getCommandSpec().parser().unmatchedOptionsArePositionalParams(); + } + + /** Sets whether arguments on the command line that resemble an option should be treated as positional parameters. + * The default is {@code false}. + *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param newValue the new setting. When {@code true}, arguments on the command line that resemble an option should be treated as positional parameters. + * @return this {@code CommandLine} object, to allow method chaining + * @since 3.0 + * @see #getUnmatchedArguments() + * @see #isUnmatchedArgumentsAllowed + */ + public CommandLine setUnmatchedOptionsArePositionalParams(boolean newValue) { + getCommandSpec().parser().unmatchedOptionsArePositionalParams(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setUnmatchedOptionsArePositionalParams(newValue); + } + return this; + } + + /** Returns whether the end user may specify arguments on the command line that are not matched to any option or parameter fields. + * The default is {@code false} and a {@link UnmatchedArgumentException} is thrown if this happens. + * When {@code true}, the last unmatched arguments are available via the {@link #getUnmatchedArguments()} method. + * @return {@code true} if the end use may specify unmatched arguments on the command line, {@code false} otherwise + * @see #getUnmatchedArguments() + * @since 0.9.7 + */ + public boolean isUnmatchedArgumentsAllowed() { + return getCommandSpec().parser().unmatchedArgumentsAllowed(); + } + + /** Sets whether the end user may specify unmatched arguments on the command line without a {@link UnmatchedArgumentException} being thrown. + * The default is {@code false}. + *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param newValue the new setting. When {@code true}, the last unmatched arguments are available via the {@link #getUnmatchedArguments()} method. + * @return this {@code CommandLine} object, to allow method chaining + * @since 0.9.7 + * @see #getUnmatchedArguments() + */ + public CommandLine setUnmatchedArgumentsAllowed(boolean newValue) { + getCommandSpec().parser().unmatchedArgumentsAllowed(newValue); + for (CommandLine command : getCommandSpec().subcommands().values()) { + command.setUnmatchedArgumentsAllowed(newValue); + } + return this; + } + + /** Returns the list of unmatched command line arguments, if any. + * @return the list of unmatched command line arguments or an empty list + * @see #isUnmatchedArgumentsAllowed() + * @since 0.9.7 + */ + public ListCommands 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.
+ *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:
+ *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 io.mosn.coder.cli.CommandLine.Help#defaultColorScheme(CommandLine.Help.Ansi) default color scheme} with {@link Help.Ansi#AUTO Ansi.AUTO}. + * @see #execute(String...) + * @see #usage(PrintStream) + * @see #usage(PrintWriter) + * @see #getUsageMessage() + * @see Help#defaultColorScheme(CommandLine.Help.Ansi) + * @since 4.0 + */ + public Help.ColorScheme getColorScheme() { return colorScheme; } + + /** Sets the color scheme to use when printing help. + *
The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param colorScheme the new color scheme + * @see #execute(String...) + * @see #usage(PrintStream) + * @see #usage(PrintWriter) + * @see #getUsageMessage() + * @since 4.0 + */ + public CommandLine setColorScheme(Help.ColorScheme colorScheme) { + this.colorScheme = Assert.notNull(colorScheme, "colorScheme"); + for (CommandLine sub : getSubcommands().values()) { sub.setColorScheme(colorScheme); } + return this; + } + + /** Returns the writer used when printing user-requested usage help or version help during command {@linkplain #execute(String...) execution}. + * Defaults to a PrintWriter wrapper around {@code System.out} unless {@link #setOut(PrintWriter)} was called with a different writer. + *This method is used by {@link #execute(String...)}. Custom {@link IExecutionStrategy IExecutionStrategy} implementations should also use this writer. + *
+ * By convention, when the user requests + * help with a {@code --help} or similar option, the usage help message is printed to the standard output stream so that it can be easily searched and paged.
+ * @since 4.0 */ + public PrintWriter getOut() { + if (out == null) { setOut(newPrintWriter(System.out, getStdoutEncoding())); } + return out; + } + + /** Sets the writer to use when printing user-requested usage help or version help during command {@linkplain #execute(String...) execution}. + *This method is used by {@link #execute(String...)}. Custom {@link IExecutionStrategy IExecutionStrategy} implementations should also use this writer.
+ *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param out the new PrintWriter to use + * @return this CommandLine for method chaining + * @since 4.0 + */ + public CommandLine setOut(PrintWriter out) { + this.out = Assert.notNull(out, "out"); + for (CommandLine sub : getSubcommands().values()) { sub.setOut(out); } + return this; + } + + /** Returns the writer to use when printing diagnostic (error) messages during command {@linkplain #execute(String...) execution}. + * Defaults to a PrintWriter wrapper around {@code System.err}, unless {@link #setErr(PrintWriter)} was called with a different writer. + *This method is used by {@link #execute(String...)}. + * {@link IParameterExceptionHandler IParameterExceptionHandler} and {@link IExecutionExceptionHandler IExecutionExceptionHandler} implementations + * should use this writer to print error messages (which may include a usage help message) when an unexpected error occurs.
+ * @since 4.0 */ + public PrintWriter getErr() { + if (err == null) { setErr(newPrintWriter(System.err, getStderrEncoding())); } + return err; + } + + /** Sets the writer to use when printing diagnostic (error) messages during command {@linkplain #execute(String...) execution}. + *This method is used by {@link #execute(String...)}. + * {@link IParameterExceptionHandler IParameterExceptionHandler} and {@link IExecutionExceptionHandler IExecutionExceptionHandler} implementations + * should use this writer to print error messages (which may include a usage help message) when an unexpected error occurs.
+ *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param err the new PrintWriter to use + * @return this CommandLine for method chaining + * @since 4.0 */ + public CommandLine setErr(PrintWriter err) { + this.err = Assert.notNull(err, "err"); + for (CommandLine sub : getSubcommands().values()) { sub.setErr(err); } + return this; + } + + /** + * Returns the mapper that was set by the application to map from exceptions to exit codes, for use by the {@link #execute(String...) execute} method. + * @return the mapper that was {@linkplain #setExitCodeExceptionMapper(IExitCodeExceptionMapper) set}, or {@code null} if none was set + * @since 4.0 */ + public IExitCodeExceptionMapper getExitCodeExceptionMapper() { return exitCodeExceptionMapper; } + + /** Sets the mapper used by the {@link #execute(String...) execute} method to map exceptions to exit codes. + *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param exitCodeExceptionMapper the new value + * @return this CommandLine for method chaining + * @since 4.0 */ + public CommandLine setExitCodeExceptionMapper(IExitCodeExceptionMapper exitCodeExceptionMapper) { + this.exitCodeExceptionMapper = Assert.notNull(exitCodeExceptionMapper, "exitCodeExceptionMapper"); + for (CommandLine sub : getSubcommands().values()) { sub.setExitCodeExceptionMapper(exitCodeExceptionMapper); } + return this; + } + + /** Returns the execution strategy used by the {@link #execute(String...) execute} method to invoke + * the business logic on the user objects of this command and/or the user-specified subcommand(s). + * The default value is {@link RunLast RunLast}. + * @return the execution strategy to run the user-specified command + * @since 4.0 */ + public IExecutionStrategy getExecutionStrategy() { return executionStrategy; } + + /** Sets the execution strategy that the {@link #execute(String...) execute} method should use to invoke + * the business logic on the user objects of this command and/or the user-specified subcommand(s). + *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param executionStrategy the new execution strategy to run the user-specified command + * @return this CommandLine for method chaining + * @since 4.0 */ + public CommandLine setExecutionStrategy(IExecutionStrategy executionStrategy) { + this.executionStrategy = Assert.notNull(executionStrategy, "executionStrategy"); + for (CommandLine sub : getSubcommands().values()) { sub.setExecutionStrategy(executionStrategy); } + return this; + } + + /** + * Returns the handler for dealing with invalid user input when the command is {@linkplain #execute(String...) executed}. + *The default implementation prints an error message describing the problem, followed by either {@linkplain UnmatchedArgumentException#printSuggestions(PrintWriter) suggested alternatives} + * for mistyped options, or the full {@linkplain #usage(PrintWriter, Help.ColorScheme) usage} help message of the {@linkplain ParameterException#getCommandLine() problematic command}; + * it then delegates to the {@linkplain #getExitCodeExceptionMapper() exit code exception mapper} for an exit code, with + * {@link CommandSpec#exitCodeOnInvalidInput() exitCodeOnInvalidInput} as the default exit code.
+ *+ * Alternatively, you can install a "short error message handler" like this: + *
+ *+ * static class ShortErrorMessageHandler implements IParameterExceptionHandler { + * public int handleParseException(ParameterException ex, String[] args) { + * CommandLine cmd = ex.getCommandLine(); + * PrintWriter writer = cmd.getErr(); + * + * writer.println(ex.getMessage()); + * UnmatchedArgumentException.printSuggestions(ex, writer); + * writer.print(cmd.getHelp().fullSynopsis()); + * + * CommandSpec spec = cmd.getCommandSpec(); + * writer.printf("Try '%s --help' for more information.%n", spec.qualifiedName()); + * + * return cmd.getExitCodeExceptionMapper() != null + * ? cmd.getExitCodeExceptionMapper().getExitCode(ex) + * : spec.exitCodeOnInvalidInput(); + * } + * } + *+ *
Install this error handler like this:
+ *+ * new CommandLine(new MyApp()) + * .setParameterExceptionHandler(new ShortErrorMessageHandler()) + * .execute(args); + *+ * @return the handler for dealing with invalid user input + * @since 4.0 */ + public IParameterExceptionHandler getParameterExceptionHandler() { return parameterExceptionHandler; } + + /** + * Sets the handler for dealing with invalid user input when the command is {@linkplain #execute(String...) executed}. + *
The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param parameterExceptionHandler the new handler for dealing with invalid user input + * @return this CommandLine for method chaining + * @see #getParameterExceptionHandler() an example short exception handler + * @since 4.0 */ + public CommandLine setParameterExceptionHandler(IParameterExceptionHandler parameterExceptionHandler) { + this.parameterExceptionHandler = Assert.notNull(parameterExceptionHandler, "parameterExceptionHandler"); + for (CommandLine sub : getSubcommands().values()) { sub.setParameterExceptionHandler(parameterExceptionHandler); } + return this; + } + + /** Returns the handler for dealing with exceptions that occurred in the {@code Callable}, {@code Runnable} or {@code Method} + * user object of a command when the command was {@linkplain #execute(String...) executed}. + *The default implementation rethrows the specified exception.
+ * @return the handler for dealing with exceptions that occurred in the business logic when the {@link #execute(String...) execute} method was invoked. + * @since 4.0 */ + public IExecutionExceptionHandler getExecutionExceptionHandler() { return executionExceptionHandler; } + + /** + * Sets a custom handler for dealing with exceptions that occurred in the {@code Callable}, {@code Runnable} or {@code Method} + * user object of a command when the command was executed via the {@linkplain #execute(String...) execute} method. + *The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its + * subcommands and nested sub-subcommands at the moment this method is called. Subcommands added + * later will have the default setting. To ensure a setting is applied to all + * subcommands, call the setter last, after adding subcommands.
+ * @param executionExceptionHandler the handler for dealing with exceptions that occurred in the business logic when the {@link #execute(String...) execute} method was invoked. + * @return this CommandLine for method chaining + * @since 4.0 */ + public CommandLine setExecutionExceptionHandler(IExecutionExceptionHandler executionExceptionHandler) { + this.executionExceptionHandler = Assert.notNull(executionExceptionHandler, "executionExceptionHandler"); + for (CommandLine sub : getSubcommands().values()) { sub.setExecutionExceptionHandler(executionExceptionHandler); } + return this; + } + + /** + *+ * Convenience method that initializes the specified annotated object from the specified command line arguments. + *
+ * This is equivalent to + *
+ * new CommandLine(command).parseArgs(args); + * return command; + *+ *
All this method does is parse the arguments and populate the annotated fields and methods. + * The caller is responsible for catching any exceptions, handling requests for usage help + * or version information, and invoking the business logic. + * Applications may be interested in using the {@link #execute(String...)} method instead.
+ * + * @param command the object to initialize. This object contains fields annotated with + * {@code @Option} or {@code @Parameters}. + * @param args the command line arguments to parse + * @param+ * 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+ * 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 ListIf 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+ * Implementations of this functions can be passed to the {@link #parseWithHandlers(IParseResultHandler, PrintStream, Help.Ansi, IExceptionHandler, String...) CommandLine::parseWithHandler} + * methods to take some next step after the command line was successfully parsed. + *
+ * @see RunFirst + * @see RunLast + * @see RunAll + * @deprecated Use {@link IExecutionStrategy} instead. + * @since 2.0 */ + @Deprecated public interface IParseResultHandler { + /** Processes a List of {@code CommandLine} objects resulting from successfully + * {@linkplain #parse(String...) parsing} the command line arguments and optionally returns a list of results. + * @param parsedCommands the {@code CommandLine} objects that resulted from successfully parsing the command line arguments + * @param out the {@code PrintStream} to print help to if requested + * @param ansi for printing help messages using ANSI styles and colors + * @return a list of results, or an empty list if there are no results + * @throws ParameterException if a help command was invoked for an unknown subcommand. Any {@code ParameterExceptions} + * thrown from this method are treated as if this exception was thrown during parsing and passed to the {@link IExceptionHandler} + * @throws ExecutionException if a problem occurred while processing the parse results; use + * {@link ExecutionException#getCommandLine()} to get the command or subcommand where processing failed + */ + List