private static Object findCompletionStartPoint(ParseResult parseResult) { List<Object> tentativeMatches = parseResult.tentativeMatch; for (int i = 1; i <= tentativeMatches.size(); i++) { Object found = tentativeMatches.get(tentativeMatches.size() - i); if (found instanceof CommandSpec) { return found; } if (found instanceof ArgSpec) { CommandLine.Range arity = ((ArgSpec) found).arity(); if (i < arity.min) { return found; // not all parameters have been supplied yet } else { return findCommandFor((ArgSpec) found, parseResult.commandSpec()); } } } return parseResult.commandSpec(); }
/** Returns this {@code ParseResult} as a list of {@code CommandLine} objects, one for each matched command/subcommand. * For backwards compatibility with pre-3.0 methods. */ public List<CommandLine> asCommandLineList() { List<CommandLine> result = new ArrayList<CommandLine>(); ParseResult pr = this; while (pr != null) { result.add(pr.commandSpec().commandLine()); pr = pr.hasSubcommand() ? pr.subcommand() : null; } return result; } }
/** Executes the top-level {@code Runnable} or {@code Callable} subcommand. * 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 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<Object> handle(ParseResult parseResult) throws ExecutionException { return execute(parseResult.commandSpec().commandLine(), new ArrayList<Object>()); // first } @Override protected RunFirst self() { return this; }
@Test public void testPositionalParamSpec_setsDefaultValue_ifNotMatched() { CommandSpec cmd = CommandSpec.create().add(PositionalParamSpec.builder().defaultValue("123").type(int.class).build()); ParseResult parseResult = new CommandLine(cmd).parseArgs(); assertFalse(parseResult.hasMatchedPositional(0)); // TODO this method should be renamed to matchedPositionalValue assertEquals(Integer.valueOf(-1), parseResult.matchedPositionalValue(0, -1)); // TODO positionalValue should return the value of the option, matched or not //assertEquals(Integer.valueOf(123), parseResult.positionalValue(0)); assertEquals(Integer.valueOf(123), parseResult.commandSpec().positionalParameters().get(0).getValue()); }
@Test public void testOptionSpec_setsDefaultValue_ifNotMatched() { CommandSpec cmd = CommandSpec.create().addOption(OptionSpec.builder("-x").defaultValue("123").type(int.class).build()); ParseResult parseResult = new CommandLine(cmd).parseArgs(); assertFalse(parseResult.hasMatchedOption('x')); // TODO this method should be renamed to matchedOptionValue assertEquals(Integer.valueOf(-1), parseResult.matchedOptionValue('x', -1)); // TODO optionValue should return the value of the option, matched or not //assertEquals(Integer.valueOf(123), parseResult.optionValue('x')); assertEquals(Integer.valueOf(123), parseResult.commandSpec().findOption('x').getValue()); }
assertEquals(Arrays.asList("-x", "xval", "sub", "1", "2", "3"), parseResult.originalArgs()); assertSame(parseResult.commandSpec().findOption("-x"), parseResult.tentativeMatch.get(0)); assertSame(parseResult.originalArgs().get(1), parseResult.tentativeMatch.get(1)); assertSame(parseResult.subcommand().commandSpec(), parseResult.tentativeMatch.get(2)); assertSame(parseResult.subcommand().commandSpec().positionalParameters().get(0), parseResult.tentativeMatch.get(3)); assertSame(parseResult.subcommand().commandSpec().positionalParameters().get(0), parseResult.tentativeMatch.get(4)); assertSame(parseResult.subcommand().commandSpec().positionalParameters().get(0), parseResult.tentativeMatch.get(5));
assertEquals(Arrays.asList(args), result.originalArgs()); assertSame(result.commandSpec().positionalParameters().get(0), result.tentativeMatch.get(0)); assertSame(result.commandSpec().positionalParameters().get(0), result.tentativeMatch.get(1)); assertSame(result.commandSpec().positionalParameters().get(1), result.tentativeMatch.get(2)); assertSame(result.commandSpec().positionalParameters().get(1), result.tentativeMatch.get(3)); assertSame(result.commandSpec().positionalParameters().get(1), result.tentativeMatch.get(4));
@Test public void testRawOptionValueReturnsFirstValue() { CommandSpec spec = CommandSpec.create(); spec.addOption(OptionSpec.builder("-V", "--verbose").build()); spec.addOption(OptionSpec.builder("-f", "--file") .paramLabel("FILES") .type(List.class) .auxiliaryTypes(File.class) // List<File> .description("The files to process").build()); CommandLine commandLine = new CommandLine(spec); String[] args = { "--verbose", "-f", "file1", "--file=file2" }; ParseResult pr = commandLine.parseArgs(args); assertEquals(Arrays.asList(args), pr.originalArgs()); assertEquals("file1", pr.matchedOption('f').stringValues().get(0)); assertEquals("file1", pr.matchedOption("-f").stringValues().get(0)); assertEquals("file1", pr.matchedOption("--file").stringValues().get(0)); List<String> expected = Arrays.asList("file1", "file2"); assertEquals(expected, pr.matchedOption('f').stringValues()); assertEquals(expected, pr.matchedOption("file").stringValues()); // for examples in Programmatic API wiki page assert expected.equals(pr.matchedOption('f').stringValues()); assert expected.equals(pr.matchedOption("file").stringValues()); assertSame(pr.commandSpec().findOption("-V"), pr.tentativeMatch.get(0)); assertSame(pr.commandSpec().findOption("-f"), pr.tentativeMatch.get(1)); assertSame(pr.originalArgs().get(2), pr.tentativeMatch.get(2)); assertSame(pr.commandSpec().findOption("-f"), pr.tentativeMatch.get(3)); assertEquals(4, pr.tentativeMatch.size()); }
@Test public void testBasicUsage() { class App { @Option(names = {"-t", "-ttt"}) boolean boolVal; @Option(names = {"-i", "-int"}) int intVal; @Parameters String[] positional; } ParseResult result = new CommandLine(new App()).parseArgs("-t", "-i", "1", "a", "b"); assertEquals(Arrays.asList("-t", "-i", "1", "a", "b"), result.originalArgs()); assertSame(result.commandSpec().findOption("-t"), result.tentativeMatch.get(0)); assertSame(result.commandSpec().findOption("-i"), result.tentativeMatch.get(1)); assertSame(result.originalArgs().get(2), result.tentativeMatch.get(2)); assertSame(result.commandSpec().positionalParameters().get(0), result.tentativeMatch.get(3)); assertSame(result.commandSpec().positionalParameters().get(0), result.tentativeMatch.get(4)); assertTrue(result.unmatched().isEmpty()); assertFalse(result.hasSubcommand()); assertFalse(result.isUsageHelpRequested()); assertFalse(result.isVersionHelpRequested()); assertTrue(result.hasMatchedOption("-ttt")); assertTrue(result.hasMatchedOption("-t")); assertTrue(result.hasMatchedOption("-i")); assertTrue(result.hasMatchedOption("-int")); assertFalse(result.hasMatchedOption("-unknown")); assertTrue(result.hasMatchedPositional(0)); assertTrue(result.hasMatchedPositional(1)); } @Test
@Test public void testOptionValue() { class App { @Option(names = {"-x", "++XX", "/XXX"}) int[] x; @Option(names = "-y") double y; } CommandLine cmd = new CommandLine(new App()); ParseResult result = cmd.parseArgs("-x", "123", "-x", "456", "-y", "3.14"); int[] expected = {123, 456}; assertArrayEquals(expected, result.matchedOptionValue("x", expected)); assertArrayEquals(expected, result.matchedOptionValue("-x", expected)); assertArrayEquals(expected, result.matchedOptionValue("XX", expected)); assertArrayEquals(expected, result.matchedOptionValue("++XX", expected)); assertArrayEquals(expected, result.matchedOptionValue("XXX", expected)); assertArrayEquals(expected, result.matchedOptionValue("/XXX", expected)); assertEquals(Double.valueOf(3.14), result.matchedOptionValue("y", 3.14)); assertEquals(Double.valueOf(3.14), result.matchedOptionValue("-y", 3.14)); assertSame(result.commandSpec().findOption("-x"), result.tentativeMatch.get(0)); assertSame(result.originalArgs().get(1), result.tentativeMatch.get(1)); assertSame(result.commandSpec().findOption("-x"), result.tentativeMatch.get(2)); assertSame(result.originalArgs().get(3), result.tentativeMatch.get(3)); assertSame(result.commandSpec().findOption("-y"), result.tentativeMatch.get(4)); assertSame(result.originalArgs().get(5), result.tentativeMatch.get(5)); }
/** 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}, 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<Object> handle(ParseResult parseResult) throws ExecutionException { List<Object> result = new ArrayList<Object>(); execute(parseResult.commandSpec().commandLine(), result); while (parseResult.hasSubcommand()) { parseResult = parseResult.subcommand(); execute(parseResult.commandSpec().commandLine(), result); } return returnResultOrExit(result); } @Override protected RunAll self() { return this; }
@Test public void testHasMatchedOptionByName_VariousPrefixes() { class App { @Option(names = {"-x", "++XX", "/XXX"}) String[] x; @Option(names = "-y") String y; } CommandLine cmd = new CommandLine(new App()); ParseResult result = cmd.parseArgs("-x", "value1", "-x", "value2"); assertTrue(result.hasMatchedOption("x")); assertTrue(result.hasMatchedOption("-x")); assertTrue(result.hasMatchedOption("XX")); assertTrue(result.hasMatchedOption("++XX")); assertTrue(result.hasMatchedOption("XXX")); assertTrue(result.hasMatchedOption("/XXX")); assertFalse(result.hasMatchedOption("y")); assertFalse(result.hasMatchedOption("-y")); assertSame(result.commandSpec().findOption("-x"), result.tentativeMatch.get(0)); assertSame(result.originalArgs().get(1), result.tentativeMatch.get(1)); assertSame(result.commandSpec().findOption("-x"), result.tentativeMatch.get(2)); assertSame(result.originalArgs().get(3), result.tentativeMatch.get(3)); }
@Test public void testTypedValues() { class App { @Option(names="-x") int x; } ParseResult result1 = new CommandLine(new App()).parseArgs();// not specified assertFalse(result1.hasMatchedOption('x')); assertTrue(result1.commandSpec().findOption('x').typedValues().isEmpty()); ParseResult result2 = new CommandLine(new App()).parseArgs("-x", "123"); assertTrue(result2.hasMatchedOption('x')); assertEquals(Integer.valueOf(123), result2.matchedOptionValue('x', 0)); ParseResult result3 = new CommandLine(new App()) .setOverwrittenOptionsAllowed(true) .parseArgs("-x", "1", "-x", "2", "-x", "3"); assertTrue(result3.hasMatchedOption('x')); assertEquals(Integer.valueOf(3), result3.matchedOptionValue('x', 0)); assertEquals(Arrays.asList("1", "2", "3"), result3.matchedOption('x').stringValues()); assertEquals(Arrays.asList(1, 2, 3), result3.matchedOption('x').typedValues()); }
@Test public void testHasMatchedPositionalByPositionalSpec() { class App { @Option(names = "-x") String x; @Parameters(index = "0", arity = "0..1") int index0 = -1; @Parameters(index = "1", arity = "0..1") int index1 = -1; @Parameters(index = "2", arity = "0..1") int index2 = -1; } CommandLine cmd = new CommandLine(new App()); ParseResult result = cmd.parseArgs("-x", "xval", "0", "1"); assertSame(result.commandSpec().findOption("-x"), result.tentativeMatch.get(0)); assertSame(result.originalArgs().get(1), result.tentativeMatch.get(1)); assertSame(result.commandSpec().positionalParameters().get(0), result.tentativeMatch.get(2)); assertSame(result.commandSpec().positionalParameters().get(1), result.tentativeMatch.get(3)); List<PositionalParamSpec> all = cmd.getCommandSpec().positionalParameters(); assertTrue(result.hasMatchedPositional(all.get(0))); assertTrue(result.hasMatchedPositional(all.get(1))); assertFalse(result.hasMatchedPositional(all.get(2))); }
@Test public void testOptionSpec_defaultValue_overwritesInitialValue() { class Params { @Option(names = "-x") int num = 12345; } CommandLine cmd = new CommandLine(new Params()); OptionSpec x = cmd.getCommandSpec().posixOptionsMap().get('x').toBuilder().defaultValue("54321").build(); cmd = new CommandLine(CommandSpec.create().addOption(x)); ParseResult parseResult = cmd.parseArgs(); assertFalse(parseResult.hasMatchedOption('x')); // TODO this method should be renamed to matchedOptionValue assertEquals(Integer.valueOf(-1), parseResult.matchedOptionValue('x', -1)); // TODO optionValue should return the value of the option, matched or not //assertEquals(Integer.valueOf(54321), parseResult.optionValue('x')); assertEquals(Integer.valueOf(54321), parseResult.commandSpec().findOption('x').getValue()); }
@Test public void testClusteredAndAttached() { class App { @Option(names = "-x") boolean extract; @Option(names = "-v") boolean verbose; @Option(names = "-f") File file; @Option(names = "-o") File outputFile; @Option(names = "-i") File inputFile; } CommandLine cmd = new CommandLine(new App()); ParseResult pr = cmd.parseArgs("-xvfFILE", "-oOUT", "-iOUT"); assertSame(pr.commandSpec().findOption("-f"), pr.tentativeMatch.get(0)); assertSame(pr.commandSpec().findOption("-o"), pr.tentativeMatch.get(1)); assertSame(pr.commandSpec().findOption("-i"), pr.tentativeMatch.get(2)); assertEquals(3, pr.tentativeMatch.size()); }
@Test public void testPositionalParamSpec_defaultValue_overwritesInitialValue() { class Params { @Parameters int num = 12345; } CommandLine cmd = new CommandLine(new Params()); PositionalParamSpec x = cmd.getCommandSpec().positionalParameters().get(0).toBuilder().defaultValue("54321").build(); cmd = new CommandLine(CommandSpec.create().add(x)); ParseResult parseResult = cmd.parseArgs(); // default not in the parse result assertFalse(parseResult.hasMatchedPositional(0)); assertEquals(Integer.valueOf(-1), parseResult.matchedPositionalValue(0, -1)); // but positional spec does have the default value assertEquals(Integer.valueOf(54321), parseResult.commandSpec().positionalParameters().get(0).getValue()); }
@Test public void testPositionalParamSpec_setsDefaultValue_ifNotMatched() { CommandSpec cmd = CommandSpec.create().add(PositionalParamSpec.builder().defaultValue("123").type(int.class).build()); ParseResult parseResult = new CommandLine(cmd).parseArgs(); assertFalse(parseResult.hasMatchedPositional(0)); // TODO this method should be renamed to matchedPositionalValue assertEquals(Integer.valueOf(-1), parseResult.matchedPositionalValue(0, -1)); // TODO positionalValue should return the value of the option, matched or not //assertEquals(Integer.valueOf(123), parseResult.positionalValue(0)); assertEquals(Integer.valueOf(123), parseResult.commandSpec().positionalParameters().get(0).getValue()); }
@Test public void testOptionSpec_setsDefaultValue_ifNotMatched() { CommandSpec cmd = CommandSpec.create().addOption(OptionSpec.builder("-x").defaultValue("123").type(int.class).build()); ParseResult parseResult = new CommandLine(cmd).parseArgs(); assertFalse(parseResult.hasMatchedOption('x')); // TODO this method should be renamed to matchedOptionValue assertEquals(Integer.valueOf(-1), parseResult.matchedOptionValue('x', -1)); // TODO optionValue should return the value of the option, matched or not //assertEquals(Integer.valueOf(123), parseResult.optionValue('x')); assertEquals(Integer.valueOf(123), parseResult.commandSpec().findOption('x').getValue()); }
@Test public void testCommandSpec_IsCommandLineCommandSpec() { class App { @Parameters String[] positional; } CommandLine cmd = new CommandLine(new App()); ParseResult result = cmd.parseArgs("a", "b"); assertSame(cmd.getCommandSpec(), result.commandSpec()); } @Test