/** Adds the specified mixin {@code CommandSpec} object to the map of mixins for this command. * @param name the name that can be used to later retrieve the mixin * @param mixin the mixin whose options and positional parameters and other attributes to add to this command * @return this CommandSpec for method chaining */ public CommandSpec addMixin(String name, CommandSpec mixin) { mixins.put(name, mixin); parser.initSeparator(mixin.parser.separator()); initName(mixin.name()); initVersion(mixin.version()); initHelpCommand(mixin.helpCommand()); initVersionProvider(mixin.versionProvider()); initDefaultValueProvider(mixin.defaultValueProvider()); usageMessage.initFromMixin(mixin.usageMessage, this); for (Map.Entry<String, CommandLine> entry : mixin.subcommands().entrySet()) { addSubcommand(entry.getKey(), entry.getValue()); } for (OptionSpec optionSpec : mixin.options()) { addOption(optionSpec); } for (PositionalParamSpec paramSpec : mixin.positionalParameters()) { addPositional(paramSpec); } return this; }
@Test public void testMultiValuePositionalParamWithMapWithoutAuxTypes() { CommandSpec spec = CommandSpec.create(); PositionalParamSpec positional = PositionalParamSpec.builder().index("0").arity("3").type(Map.class).build(); assertTrue(positional.isMultiValue()); spec.addPositional(positional); CommandLine commandLine = new CommandLine(spec); commandLine.parse("1=1.0", "2=2.0", "3=3.0"); Map<String, String> expected = new LinkedHashMap<String, String>(); expected.put("1", "1.0"); expected.put("2", "2.0"); expected.put("3", "3.0"); assertEquals(expected, spec.positionalParameters().get(0).getValue()); }
@Test public void testMultiValuePositionalParamWithMapAndAuxTypes() { CommandSpec spec = CommandSpec.create(); PositionalParamSpec positional = PositionalParamSpec.builder().index("0").arity("3").type(Map.class).auxiliaryTypes(Integer.class, Double.class).build(); assertTrue(positional.isMultiValue()); spec.addPositional(positional); CommandLine commandLine = new CommandLine(spec); commandLine.parse("1=1.0", "2=2.0", "3=3.0"); Map<Integer, Double> expected = new LinkedHashMap<Integer, Double>(); expected.put(1, 1.0); expected.put(2, 2.0); expected.put(3, 3.0); assertEquals(expected, spec.positionalParameters().get(0).getValue()); }
.optionListHeading("Options%n") .parameterListHeading("Positional Parameters%n"); spec.addPositional(PositionalParamSpec.builder().description("positional param").build()); CommandLine commandLine = new CommandLine(spec); String actual = usageString(commandLine, Ansi.OFF);
.type(int.class) .description("number of times to execute").build()); spec.addPositional(PositionalParamSpec.builder() .paramLabel("FILES") .type(List.class)
.type(int.class) .description("number of times to execute").build()); spec.addPositional(PositionalParamSpec.builder() .paramLabel("FILES") .type(List.class)
private static boolean initFromAnnotatedTypedMembers(TypedMember member, CommandSpec receiver, IFactory factory) { boolean result = false; if (member == null) { return result; } if (member.isMixin()) { validateMixin(member); receiver.addMixin(member.getMixinName(), buildMixinForField(member, factory)); result = true; } if (member.isUnmatched()) { validateUnmatched(member); receiver.addUnmatchedArgsBinding(buildUnmatchedForField(member)); } if (member.isArgSpec()) { validateArgSpecField(member); Messages msg = receiver.usageMessage.messages(); if (member.isOption()) { receiver.addOption(OptionSpec.builder(member, factory).build()); } else if (member.isParameter()) { receiver.addPositional(PositionalParamSpec.builder(member, factory).build()); } else { receiver.addPositional(PositionalParamSpec.builder(member, factory).build()); } } if (member.isInjectSpec()) { validateInjectSpec(member); try { member.setter().set(receiver); } catch (Exception ex) { throw new InitializationException("Could not inject spec", ex); } } return result; } private static boolean initFromMethodParameters(Object scope, Method method, CommandSpec receiver, IFactory factory) {
@Test public void testParseResetsRawAndOriginalStringValues() { CommandSpec spec = CommandSpec.create() .addOption(OptionSpec.builder("-x").type(String.class).build()) .addPositional(PositionalParamSpec.builder().build()); CommandLine cmd = new CommandLine(spec); ParseResult parseResult = cmd.parseArgs("-x", "XVAL", "POSITIONAL"); assertEquals("XVAL", parseResult.matchedOption('x').getValue()); assertEquals(Arrays.asList("XVAL"), parseResult.matchedOption('x').stringValues()); assertEquals(Arrays.asList("XVAL"), parseResult.matchedOption('x').originalStringValues()); assertEquals("POSITIONAL", parseResult.matchedPositional(0).getValue()); assertEquals(Arrays.asList("POSITIONAL"), parseResult.matchedPositional(0).stringValues()); assertEquals(Arrays.asList("POSITIONAL"), parseResult.matchedPositional(0).originalStringValues()); ParseResult parseResult2 = cmd.parseArgs("-x", "222", "$$$$"); assertEquals("222", parseResult2.matchedOption('x').getValue()); assertEquals(Arrays.asList("222"), parseResult2.matchedOption('x').stringValues()); assertEquals(Arrays.asList("222"), parseResult2.matchedOption('x').originalStringValues()); assertEquals("$$$$", parseResult2.matchedPositional(0).getValue()); assertEquals(Arrays.asList("$$$$"), parseResult2.matchedPositional(0).stringValues()); assertEquals(Arrays.asList("$$$$"), parseResult2.matchedPositional(0).originalStringValues()); }
@Test public void testMultiValuePositionalParamArityAloneIsInsufficient() { CommandSpec spec = CommandSpec.create(); PositionalParamSpec positional = PositionalParamSpec.builder().index("0").arity("3").type(int.class).build(); assertFalse(positional.isMultiValue()); spec.addPositional(positional); CommandLine commandLine = new CommandLine(spec); try { commandLine.parse("1", "2", "3"); fail("Expected exception"); } catch (UnmatchedArgumentException ex) { assertEquals("Unmatched arguments: 2, 3", ex.getMessage()); } }
@Test public void testUsageHelp_abbreviateSynopsisWithPositional() throws UnsupportedEncodingException { CommandSpec spec = CommandSpec.create(); spec.usageMessage().abbreviateSynopsis(true).requiredOptionMarker('!').sortOptions(false); spec.addOption(OptionSpec.builder("-x").required(true).description("required").build()); spec.addPositional(PositionalParamSpec.builder().arity("1").paramLabel("POSITIONAL").description("positional").build()); CommandLine commandLine = new CommandLine(spec); String actual = usageString(commandLine, Ansi.OFF); String expected = String.format("" + "Usage: <main class> [OPTIONS] POSITIONAL...%n" + "! POSITIONAL... positional%n" + "! -x required%n"); assertEquals(expected, actual); }
/** Adds the specified option spec or positional parameter spec to the list of configured arguments to expect. * @param arg the option spec or positional parameter spec to add * @return this CommandSpec for method chaining */ public CommandSpec add(ArgSpec arg) { return arg.isOption() ? addOption((OptionSpec) arg) : addPositional((PositionalParamSpec) arg); }
@Test public void testMultiValuePositionalParamArityAloneIsInsufficient() throws Exception { CommandLine.Model.CommandSpec spec = CommandLine.Model.CommandSpec.create(); CommandLine.Model.PositionalParamSpec positional = CommandLine.Model.PositionalParamSpec.builder().index("0").arity("3").type(int.class).build(); assertFalse(positional.isMultiValue()); spec.addPositional(positional); spec.parser().collectErrors(true); CommandLine commandLine = new CommandLine(spec); commandLine.parse("1", "2", "3"); assertEquals(1, commandLine.getParseResult().errors().size()); assertEquals("Unmatched arguments: 2, 3", commandLine.getParseResult().errors().get(0).getMessage()); } @Test
@Test public void testPositionalConvertersOverridesRegisteredTypeConverter() { CommandSpec spec = CommandSpec.create(); spec.addPositional(PositionalParamSpec.builder().paramLabel("COUNT").index("0").type(int.class).description("number of times to execute").build()); spec.addPositional(PositionalParamSpec.builder().paramLabel("SQLTYPE").index("1").type(int.class).converters( new CommandLineTypeConversionTest.SqlTypeConverter()).description("sql type converter").build()); CommandLine commandLine = new CommandLine(spec); commandLine.parse("33", "BLOB"); assertEquals(Integer.valueOf(33), spec.positionalParameters().get(0).getValue()); assertEquals(Integer.valueOf(Types.BLOB), spec.positionalParameters().get(1).getValue()); }
@Test public void testMultiValuePositionalParamWithArray() { CommandSpec spec = CommandSpec.create(); PositionalParamSpec positional = PositionalParamSpec.builder().index("0").arity("3").type(int[].class).build(); assertTrue(positional.isMultiValue()); spec.addPositional(positional); CommandLine commandLine = new CommandLine(spec); commandLine.parse("1", "2", "3"); assertArrayEquals(new int[] {1, 2, 3}, (int[]) spec.positionalParameters().get(0).getValue()); }
@Test public void testUsageHelpPositional_empty() { CommandSpec spec = CommandSpec.create(); spec.addPositional(PositionalParamSpec.builder().build()); CommandLine commandLine = new CommandLine(spec); String actual = usageString(commandLine, Ansi.OFF); String expected = String.format("" + "Usage: <main class> PARAM...%n" + " PARAM...%n"); assertEquals(expected, actual); }
@Test public void testInitializingDefaultsShouldNotAddPositionalToParseResult() { CommandSpec spec = CommandSpec.create() .addPositional(PositionalParamSpec.builder().defaultValue("xyz").build()); CommandLine cmd = new CommandLine(spec); ParseResult parseResult = cmd.parseArgs(); assertFalse(parseResult.hasMatchedPositional(0)); }
@Test public void testMultiValuePositionalParamWithListAndAuxTypes() { CommandSpec spec = CommandSpec.create(); PositionalParamSpec positional = PositionalParamSpec.builder().index("0").arity("3").type(List.class).auxiliaryTypes(Integer.class).build(); assertTrue(positional.isMultiValue()); spec.addPositional(positional); CommandLine commandLine = new CommandLine(spec); commandLine.parse("1", "2", "3"); assertEquals(Arrays.asList(1, 2, 3), spec.positionalParameters().get(0).getValue()); }
@Test public void testAbbreviatedSynopsis() { CommandSpec spec = CommandSpec.create(); spec.addPositional(PositionalParamSpec.builder().paramLabel("a").hidden(true).build()); spec.addPositional(PositionalParamSpec.builder().paramLabel("b").build()); Help help = new Help(spec, new Help.ColorScheme(Help.Ansi.OFF)); String actual = help.abbreviatedSynopsis(); assertEquals(String.format("<main class> b...%n"), actual); }
@Test public void testMultiValuePositionalParamWithListWithoutAuxTypes() { CommandSpec spec = CommandSpec.create(); PositionalParamSpec positional = PositionalParamSpec.builder().index("0").arity("3").type(List.class).build(); assertTrue(positional.isMultiValue()); spec.addPositional(positional); CommandLine commandLine = new CommandLine(spec); commandLine.parse("1", "2", "3"); assertEquals(Arrays.asList("1", "2", "3"), spec.positionalParameters().get(0).getValue()); }
@Test public void testUsageHelpPositional_withDescription() { CommandSpec spec = CommandSpec.create(); spec.addPositional(PositionalParamSpec.builder().description("positional param").build()); CommandLine commandLine = new CommandLine(spec); String actual = usageString(commandLine, Ansi.OFF); String expected = String.format("" + "Usage: <main class> PARAM...%n" + " PARAM... positional param%n"); assertEquals(expected, actual); }