public static void main(String[] args) { 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) // so, this option is of type List<File> .description("The files to process").build()); spec.addOption(OptionSpec.builder("-n", "--num") .paramLabel("COUNT") .type(int[].class) .splitRegex(",") .description("Comma-separated list of integers").build()); CommandLine commandLine = new CommandLine(spec);
OptionSpec.Builder builder = OptionSpec.builder(typedMember, factory); builder.completionCandidates(extractCompletionCandidates(variable, variable.getAnnotationMirrors())); builder.converters(extractConverters(variable, variable.getAnnotationMirrors())); options.put(variable, builder); } else if (!isMixin) {
@SuppressWarnings("unchecked") @Ignore @Test public void testInterpreterProcessClusteredShortOptions() throws Exception { Class c = Class.forName("picocli.CommandLine$Interpreter"); Method processClusteredShortOptions = c.getDeclaredMethod("processClusteredShortOptions", Collection.class, Set.class, String.class, Stack.class); processClusteredShortOptions.setAccessible(true); CommandSpec spec = CommandSpec.create(); spec.addOption(OptionSpec.builder("-x").arity("0").build()); spec.parser().trimQuotes(true); CommandLine cmd = new CommandLine(spec); Object interpreter = PicocliTestUtil.interpreter(cmd); Stack<String> stack = new Stack<String>(); String arg = "-xa"; processClusteredShortOptions.invoke(interpreter, new ArrayList<ArgSpec>(), new HashSet<String>(), arg, stack); // TODO }
builder.auxiliaryTypes(Integer.class, Integer.TYPE) .type(Double.TYPE) .splitRegex(",,,") .required(true) .defaultValue("DEF") .description("Description") .paramLabel("param") .arity("1") .help(true) .versionHelp(true) .usageHelp(true) .order(123) .hidden(true) .setter(setter) .getter(getter) .converters(converter) .initialValue("ABC") .showDefaultValue(Visibility.NEVER) .withToString("TOSTRING"); assertArrayEquals(new Class[]{Integer.class, Integer.TYPE}, builder.auxiliaryTypes()); assertEquals(Double.TYPE, builder.type()); assertEquals(",,,", builder.splitRegex()); assertTrue(builder.required()); assertEquals("DEF", builder.defaultValue()); assertArrayEquals(new String[]{"Description"}, builder.description()); assertEquals("param", builder.paramLabel()); assertEquals(Range.valueOf("1"), builder.arity()); assertTrue(builder.help()); assertTrue(builder.versionHelp());
@Test public void testOptionSpecEquals() { OptionSpec.Builder option = OptionSpec.builder("-x") .arity("1") .hideParamSyntax(true) .required(true) .splitRegex(";") .description("desc") .descriptionKey("key") .auxiliaryTypes(Integer.class, Double.class) .help(true) .usageHelp(true) .versionHelp(true) .order(123); OptionSpec p1 = option.build(); assertEquals(p1, p1); assertEquals(p1, option.build()); assertNotEquals(p1, option.arity("2").build()); assertNotEquals(p1, option.arity("1").hideParamSyntax(false).build()); assertNotEquals(p1, option.hideParamSyntax(true).required(false).build()); assertNotEquals(p1, option.required(true).splitRegex(",").build()); assertNotEquals(p1, option.splitRegex(";").description("xyz").build()); assertNotEquals(p1, option.description("desc").descriptionKey("XX").build()); assertNotEquals(p1, option.descriptionKey("key").auxiliaryTypes(Short.class).build()); assertEquals(p1, option.auxiliaryTypes(Integer.class, Double.class).build()); assertNotEquals(p1, option.help(false).build()); assertNotEquals(p1, option.help(true).usageHelp(false).build()); assertNotEquals(p1, option.usageHelp(true).versionHelp(false).build());
@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()); }
static OptionSpec extractOptionSpec(TypedMember member, IFactory factory) { Option option = member.getAnnotation(Option.class); OptionSpec.Builder builder = OptionSpec.builder(option.names()); initCommon(builder, member); builder.order(option.order()); builder.help(option.help()); builder.usageHelp(option.usageHelp()); builder.versionHelp(option.versionHelp()); builder.showDefaultValue(option.showDefaultValue()); if (!NoCompletionCandidates.class.equals(option.completionCandidates())) { builder.completionCandidates(DefaultFactory.createCompletionCandidates(factory, option.completionCandidates())); } builder.arity(Range.optionArity(member)); builder.required(option.required()); builder.interactive(option.interactive()); Class<?>[] elementTypes = inferTypes(member.getType(), option.type(), member.getGenericType()); builder.auxiliaryTypes(elementTypes); builder.paramLabel(inferLabel(option.paramLabel(), member.name(), member.getType(), elementTypes)); builder.hideParamSyntax(option.hideParamSyntax()); builder.description(option.description()); builder.descriptionKey(option.descriptionKey()); builder.splitRegex(option.split()); builder.hidden(option.hidden()); builder.defaultValue(option.defaultValue()); builder.converters(DefaultFactory.createConverter(factory, option.converter())); return builder.build(); } static PositionalParamSpec extractPositionalParamSpec(TypedMember member, IFactory factory) {
@Test public void testOptionValueReturnsAllValuesConvertedToType() { 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); List<File> expected = Arrays.asList(new File("file1"), new File("file2")); assertEquals(expected, pr.matchedOptionValue('f', Collections.<File>emptyList())); assertEquals(expected, pr.matchedOptionValue("--file", Collections.<File>emptyList())); // for examples in Programmatic API wiki page assert expected.equals(pr.matchedOptionValue('f', Collections.<File>emptyList())); assert expected.equals(pr.matchedOptionValue("--file", Collections.<File>emptyList())); }
@Test public void testShowAbbreviatedSynopsisUsageWithCommandOption() { CommandSpec spec = CommandSpec.create(); spec.addOption(OptionSpec.builder("-h", "--help").usageHelp(true).description("show help and exit").build()); // using abbreviated synopsis spec.usageMessage().abbreviateSynopsis(true); // adding a subcommand should show "COMMAND" option to the help synopsis spec.addSubcommand("subcommand", CommandSpec.create()); CommandLine commandLine = new CommandLine(spec); String actual = usageString(commandLine, Help.Ansi.OFF); String expected = String.format("" + "Usage: <main class> [OPTIONS] [COMMAND]%n" + " -h, --help show help and exit%n" + "Commands:%n" + " subcommand%n"); assertEquals(expected, actual); }
@Test public void testOptionSpec_defaultValue_overwritesInitialValue() { @Command(showDefaultValues = true) class Params { @Option(names = {"-x", "--array"}, required = true, paramLabel = "INT", description = "the array") int[] array = {1, 5, 11, 23}; } CommandLine cmd = new CommandLine(new Params()); OptionSpec x = cmd.getCommandSpec().posixOptionsMap().get('x').toBuilder().defaultValue("5,4,3,2,1").splitRegex(",").build(); cmd = new CommandLine(CommandSpec.create().addOption(x)); cmd.getCommandSpec().usageMessage().showDefaultValues(true); String result = usageString(cmd, Help.Ansi.OFF); assertEquals(format("" + "Usage: <main class> [-x=INT[,INT...]]...%n" + " -x, --array=INT[,INT...] the array%n" + " Default: 5,4,3,2,1%n"), result); }
@Test public void test381_NPE_whenAddingSubcommand() { CommandSpec toplevel = CommandSpec.create(); toplevel.addOption(OptionSpec.builder("-o").description("o option").build()); CommandSpec sub = CommandSpec.create(); sub.addOption(OptionSpec.builder("-x").description("x option").build()); CommandLine commandLine = new CommandLine(toplevel); commandLine.addSubcommand("sub", sub); // NPE here commandLine.usage(System.out); String expected = String.format("" + "Usage: <main class> [-o] [COMMAND]%n" + " -o o option%n" + "Commands:%n" + " sub%n"); assertEquals(expected, systemOutRule.getLog()); }
@Test public void testModelUsageHelp() { CommandSpec spec = CommandSpec.create(); spec.addOption(OptionSpec.builder("-h", "--help").usageHelp(true).description("show help and exit").build()); spec.addOption(OptionSpec.builder("-V", "--version").versionHelp(true).description("show help and exit").build()); spec.addOption(OptionSpec.builder("-c", "--count").paramLabel("COUNT").arity("1").type(int.class).description("number of times to execute").build()); spec.addOption(OptionSpec.builder("-f", "--fix").paramLabel("FIXED(BOOLEAN)").arity("1").hideParamSyntax(true).required(true).description("run with fixed option").build()); CommandLine commandLine = new CommandLine(spec); String actual = usageString(commandLine, Ansi.OFF); String expected = String.format("" + "Usage: <main class> [-hV] [-c=COUNT] -f=FIXED(BOOLEAN)%n" + " -c, --count=COUNT number of times to execute%n" + " -f, --fix=FIXED(BOOLEAN) run with fixed option%n" + " -h, --help show help and exit%n" + " -V, --version show help and exit%n"); assertEquals(expected, actual); }
@Test public void testModelUsageHelpWithCustomSeparator() { CommandSpec spec = CommandSpec.create(); spec.addOption(OptionSpec.builder("-h", "--help").usageHelp(true).description("show help and exit").build()); spec.addOption(OptionSpec.builder("-V", "--version").versionHelp(true).description("show help and exit").build()); spec.addOption(OptionSpec.builder("-c", "--count").paramLabel("COUNT").arity("1").type(int.class).description("number of times to execute").build()); spec.addOption(OptionSpec.builder("-f", "--fix").paramLabel("FIXED(=BOOLEAN)").arity("1").hideParamSyntax(true).required(true).description("run with fixed option").build()); CommandLine commandLine = new CommandLine(spec).setSeparator(" "); String actual = usageString(commandLine, Ansi.OFF); String expected = String.format("" + "Usage: <main class> [-hV] [-c COUNT] -f FIXED(=BOOLEAN)%n" + " -c, --count COUNT number of times to execute%n" + " -f, --fix FIXED(=BOOLEAN)%n" + " run with fixed option%n" + " -h, --help show help and exit%n" + " -V, --version show help and exit%n"); assertEquals(expected, actual); }
@Test public void testShowSynopsisUsageWithCommandOption() { CommandSpec spec = CommandSpec.create(); spec.addOption(OptionSpec.builder("-h", "--help").usageHelp(true).description("show help and exit").build()); // adding a subcommand should show "COMMAND" option to the help synopsis spec.addSubcommand("subcommand", CommandSpec.create()); CommandLine commandLine = new CommandLine(spec); String actual = usageString(commandLine, Help.Ansi.OFF); String expected = String.format("" + "Usage: <main class> [-h] [COMMAND]%n" + " -h, --help show help and exit%n" + "Commands:%n" + " subcommand%n"); assertEquals(expected, actual); }
@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 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); }
@Test public void testMultiValueOptionWithMapAndAuxTypes() { CommandSpec spec = CommandSpec.create(); OptionSpec option = OptionSpec.builder("-c", "--count").arity("3").type(Map.class).auxiliaryTypes(Integer.class, Double.class).build(); assertTrue(option.isMultiValue()); spec.addOption(option); CommandLine commandLine = new CommandLine(spec); commandLine.parse("-c", "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.optionsMap().get("-c").getValue()); }
@Test public void testOptionSpec_notRequiredIfNonNullDefaultValue() { assertTrue(OptionSpec.builder("-x").required(true).build().required()); assertFalse(OptionSpec.builder("-x").defaultValue("123").required(true).build().required()); }
@Test public void testUsageHelp_abbreviateSynopsisWithoutPositional() throws UnsupportedEncodingException { CommandSpec spec = CommandSpec.create(); spec.usageMessage().abbreviateSynopsis(true).requiredOptionMarker('!').sortOptions(false); spec.addOption(OptionSpec.builder("-x").required(true).description("required").build()); CommandLine commandLine = new CommandLine(spec); String actual = usageString(commandLine, Ansi.OFF); String expected = String.format("" + "Usage: <main class> [OPTIONS]%n" + "! -x required%n"); assertEquals(expected, actual); }
@Test public void testCompletionCandidatesValues_forOptionSpec() { CommandSpec spec = CommandSpec.create(); spec.add(OptionSpec.builder("-x").completionCandidates(Arrays.asList("x", "y", "z")).build()); assertEquals(Arrays.asList("x", "y", "z"), extract(spec.findOption("x").completionCandidates())); } @Test