@Before public void setUp() { cli = new DefaultCLI(); cli.setName("test").setHidden(false).setDescription("A test command"); cli.addOption(new TypedOption<Boolean>().setType(Boolean.class).setShortName("a").setLongName("enable-a") .setFlag(true).setDescription("turn [a] on or off")); cli.addOption(new TypedOption<String>().setType(String.class).setShortName("b").setLongName("bfile").setSingleValued(true) .setDescription("set the value of [b]")); cli.addOption(new TypedOption<Boolean>().setType(Boolean.class).setShortName("c").setLongName("copt").setSingleValued(false) .setDescription("turn [c] on or off")); }
@Test public void testHelloCLIFromClass() { CLI command = CLIConfigurator.define(HelloClI.class); assertThat(command.getOptions()).hasSize(1); TypedOption option = (TypedOption) find(command.getOptions(), "name"); assertThat(option.getLongName()).isEqualToIgnoringCase("name"); assertThat(option.getShortName()).isEqualToIgnoringCase("n"); assertThat(option.getType()).isEqualTo(String.class); assertThat(option.getArgName()).isEqualTo("name"); assertThat(option.getDescription()).isEqualToIgnoringCase("your name"); assertThat(option.getDefaultValue()).isNull(); assertThat(option.acceptValue()).isTrue(); assertThat(option.isMultiValued()).isFalse(); assertThat(option.isRequired()).isTrue(); }
/** * Creates an instance of {@link TypedOption} by copying the state of another {@link TypedOption} * * @param option the copied option */ public TypedOption(TypedOption<T> option) { super(option); this.type = option.getType(); this.converter = option.getConverter(); this.parsedAsList = option.isParsedAsList(); this.listSeparator = option.getListSeparator(); }
/** * Creates the value for the given option from the given raw value. * * @param value the value * @return the created value */ public static <T> T create(String value, TypedOption<T> option) { Objects.requireNonNull(option); if (value == null) { value = option.getDefaultValue(); } if (value == null) { return null; } try { if (option.getConverter() != null) { return Converters.create(value, option.getConverter()); } else { return Converters.create(option.getType(), value); } } catch (Exception e) { throw new InvalidValueException(option, value, e); } }
@SuppressWarnings("unchecked") private static io.vertx.core.cli.Option createOption(Method method) { TypedOption opt = new TypedOption(); opt.setLongName(option.longName()) .setShortName(option.shortName()) .setMultiValued(option.acceptMultipleValues()) .setSingleValued(option.acceptValue()) .setArgName(option.argName()) .setFlag(option.flag()) .setHelp(option.help()) .setRequired(option.required()); opt.setDescription(description.value()); opt.setHidden(true); .setType(ReflectionUtils.getComponentType(method.getParameters()[0])) .setMultiValued(true); } else { final Class<?> type = method.getParameters()[0].getType(); opt.setType(type); if (type != Boolean.TYPE && type != Boolean.class) { opt.setSingleValued(true); opt.setConverter(ReflectionUtils.newInstance(convertedBy.value())); opt.setParsedAsList(true).setListSeparator(parsedAsList.separator());
CLI cli = new DefaultCLI().setName("test"); Option[] options = new Option[]{ new TypedOption<String>().setLongName("conf").setType(String.class) .setSingleValued(true), new TypedOption<Integer>().setLongName("instances").setType(Integer.class) .setSingleValued(true).setDefaultValue("1"), new TypedOption<Boolean>().setLongName("worker").setType(Boolean.class) .setFlag(true), new TypedOption<String>().setLongName("classpath").setShortName("cp") .setListSeparator(File.pathSeparator) .setType(String.class).setSingleValued(true), new TypedOption<Boolean>().setLongName("cluster").setType(Boolean.class) .setFlag(true), new TypedOption<Integer>().setLongName("cluster-port").setType(Integer.class) .setSingleValued(true), new TypedOption<String>().setLongName("cluster-host").setType(String.class) .setSingleValued(true), new TypedOption<Boolean>().setLongName("ha").setType(Boolean.class) .setFlag(true).setSingleValued(true), new TypedOption<Integer>().setLongName("quorum").setType(Integer.class) .setSingleValued(true), new TypedOption<String>().setLongName("ha-group").setType(String.class) .setDefaultValue("__DEFAULT__").setSingleValued(true) }; cli.addOptions(Arrays.asList(options));
@Test public void testWithDashD() throws CLIException { CLI cli = new DefaultCLI().setName("test"); Option[] options = new Option[]{ new TypedOption<String>().setShortName("D").setLongName("systemProperty") .setMultiValued(true).setType(String.class), new TypedOption<Boolean>().setShortName("F").setLongName("flag") .setFlag(true) .setType(Boolean.class) }; cli.addOptions(Arrays.asList(options)); CommandLine evaluated = cli.parse(Arrays.asList("-Dx=y", "-F")); assertThat(evaluated.cli().getOptions()).hasSize(2); assertThat(evaluated.getRawValueForOption(evaluated.cli().getOption("systemProperty"))) .isEqualTo("x=y"); assertThat((boolean) evaluated.getOptionValue("flag")).isTrue(); }
@Test public void testMultiValues() throws Exception { String[] args = new String[]{"-e", "one", "two", "-f", "1"}; TypedOption<String> e = new TypedOption<String>().setShortName("e") .setMultiValued(true).setType(String.class); TypedOption<Integer> f = new TypedOption<Integer>().setShortName("f") .setMultiValued(true).setType(Integer.class); cli.addOption(e).addOption(f); CommandLine evaluated = cli.parse(Arrays.asList(args)); assertThat(evaluated.getOptionValues("e")).contains("one", "two").hasSize(2); assertThat(evaluated.getOptionValues("f")).contains(1).hasSize(1); }
@Test public void testRequiredOptions() throws CLIException { Option[] options = new Option[]{ new TypedOption<Boolean>().setShortName("f").setLongName("flag") .setType(Boolean.class).setRequired(true).setFlag(true) }; cli.addOptions(Arrays.asList(options)); cli.parse(Collections.singletonList("-f")); }
@Test public void testWithList() throws CLIException { CLI cli = new DefaultCLI().setName("test"); Option[] options = new Option[]{ new TypedOption<String>().setShortName("f").setLongName("file") .setParsedAsList(true).setType(String.class) }; cli.addOptions(Arrays.asList(options)); CommandLine evaluated = cli.parse(Collections.singletonList("-f=hello.txt,hello2.txt")); assertThat(evaluated.cli().getOptions()).hasSize(1); assertThat((String) evaluated.getOptionValue("file")).isEqualTo("hello.txt,hello2.txt"); assertThat(evaluated.getOptionValues("f")) .containsExactly("hello.txt", "hello2.txt"); }
@Test public void testConcatenatedOptions() throws CLIException { CLI cli = new DefaultCLI().setName("test"); Option[] options = new Option[]{ new TypedOption<Boolean>().setShortName("d").setFlag(true) .setType(Boolean.class), new TypedOption<Boolean>().setShortName("e").setFlag(true) .setType(Boolean.class), new TypedOption<Boolean>().setShortName("f").setFlag(true) .setType(Boolean.class) }; cli.addOptions(Arrays.asList(options)); CommandLine evaluated = cli.parse(Arrays.asList("-d", "-e", "-f")); assertThat((boolean) evaluated.getOptionValue("d")).isTrue(); assertThat((boolean) evaluated.getOptionValue("e")).isTrue(); assertThat((boolean) evaluated.getOptionValue("f")).isTrue(); evaluated = cli.parse(Collections.singletonList("-de")); assertThat((boolean) evaluated.getOptionValue("d")).isTrue(); assertThat((boolean) evaluated.getOptionValue("e")).isTrue(); assertThat((boolean) evaluated.getOptionValue("f")).isFalse(); evaluated = cli.parse(Collections.singletonList("-def")); assertThat((boolean) evaluated.getOptionValue("d")).isTrue(); assertThat((boolean) evaluated.getOptionValue("e")).isTrue(); assertThat((boolean) evaluated.getOptionValue("f")).isTrue(); }
@Test public void testOptionsWithChoicesUsingEnum() { CLI cli = new DefaultCLI().setName("test"); cli.addOption(new TypedOption<RetentionPolicy>().setLongName("retention").setType(RetentionPolicy.class)); StringBuilder builder = new StringBuilder(); cli.usage(builder); assertThat(builder.toString()) .contains("[--retention {CLASS, RUNTIME, SOURCE}]") // Usage line .contains(" --retention {CLASS, RUNTIME, SOURCE}"); // options CommandLine line = cli.parse(Arrays.asList("--retention", "CLASS")); assertThat((RetentionPolicy) line.getOptionValue("retention")).isEqualTo(RetentionPolicy.CLASS); try { cli.parse(Collections.singletonList("--retention=nope")); fail("Invalid value expected"); } catch (InvalidValueException e) { // OK } }
@Test public void testOptionsParsedAsList() { CLI command = CLIConfigurator.define(CommandForParsedAsList.class); assertThat(command.getOptions()).hasSize(1); assertThat(((TypedOption) find(command.getOptions(), "option")) .getListSeparator()).isEqualTo(":"); assertThat(find(command.getOptions(), "option").isMultiValued()).isTrue(); assertThat(((TypedOption) find(command.getOptions(), "option")).getType()) .isEqualTo(String.class); }
private <T> T getValue(TypedOption<T> option) { if (isOptionAssigned(option)) { return create(getRawValueForOption(option), option); } else { if (option.getDefaultValue() != null) { return create(getRawValueForOption(option), option); } if (option.isFlag() || isBoolean(option)) { try { if (isSeenInCommandLine(option)) { return (T) Boolean.TRUE; } else { return (T) Boolean.FALSE; } } catch (InvalidValueException e) { throw new IllegalArgumentException(e); } } } return null; }
@Test public void testTypeExtraction() { CLI command = CLIConfigurator.define(CommandForTypeExtractTest.class); assertThat(command.getOptions()).hasSize(6); TypedOption model = (TypedOption) find(command.getOptions(), "list"); assertThat(model.getType()).isEqualTo(String.class); assertThat(model.isMultiValued()).isTrue(); model = (TypedOption) find(command.getOptions(), "set"); assertThat(model.getType()).isEqualTo(Character.class); assertThat(model.isMultiValued()).isTrue(); model = (TypedOption) find(command.getOptions(), "collection"); assertThat(model.getType()).isEqualTo(Integer.class); assertThat(model.isMultiValued()).isTrue(); model = (TypedOption) find(command.getOptions(), "tree"); assertThat(model.getType()).isEqualTo(String.class); assertThat(model.isMultiValued()).isTrue(); model = (TypedOption) find(command.getOptions(), "al"); assertThat(model.getType()).isEqualTo(String.class); assertThat(model.isMultiValued()).isTrue(); model = (TypedOption) find(command.getOptions(), "array"); assertThat(model.getType()).isEqualTo(Integer.TYPE); assertThat(model.isMultiValued()).isTrue(); }
public static <T> List<T> createFromList(String raw, TypedOption<T> option) { if (raw == null) { return Collections.emptyList(); } final String[] segments = raw.split(option.getListSeparator()); return Arrays.stream(segments).map(s -> create(s.trim(), option)).collect(Collectors.toList()); }
private boolean isBoolean(TypedOption option) { Class type = option.getType(); return type == Boolean.TYPE || type == Boolean.class; }
@SuppressWarnings("unchecked") private static io.vertx.core.cli.Option createOption(Method method) { TypedOption opt = new TypedOption(); opt.setLongName(option.longName()) .setShortName(option.shortName()) .setMultiValued(option.acceptMultipleValues()) .setSingleValued(option.acceptValue()) .setArgName(option.argName()) .setFlag(option.flag()) .setHelp(option.help()) .setRequired(option.required()); opt.setDescription(description.value()); opt.setHidden(true); .setType(ReflectionUtils.getComponentType(method.getParameters()[0])) .setMultiValued(true); } else { final Class<?> type = method.getParameters()[0].getType(); opt.setType(type); if (type != Boolean.TYPE && type != Boolean.class) { opt.setSingleValued(true); opt.setConverter(ReflectionUtils.newInstance(convertedBy.value())); opt.setParsedAsList(true).setListSeparator(parsedAsList.separator());
CLI cli = new DefaultCLI().setName("test"); Option[] options = new Option[]{ new TypedOption<String>().setLongName("conf").setType(String.class) .setSingleValued(true), new TypedOption<Integer>().setLongName("instances").setType(Integer.class) .setSingleValued(true).setDefaultValue("1"), new TypedOption<Boolean>().setLongName("worker").setType(Boolean.class) .setFlag(true), new TypedOption<String>().setLongName("classpath").setShortName("cp") .setListSeparator(File.pathSeparator) .setType(String.class).setSingleValued(true), new TypedOption<Boolean>().setLongName("cluster").setType(Boolean.class) .setFlag(true), new TypedOption<Integer>().setLongName("cluster-port").setType(Integer.class) .setSingleValued(true), new TypedOption<String>().setLongName("cluster-host").setType(String.class) .setSingleValued(true), new TypedOption<Boolean>().setLongName("ha").setType(Boolean.class) .setFlag(true).setSingleValued(true), new TypedOption<Integer>().setLongName("quorum").setType(Integer.class) .setSingleValued(true), new TypedOption<String>().setLongName("ha-group").setType(String.class) .setDefaultValue("__DEFAULT__").setSingleValued(true) }; cli.addOptions(Arrays.asList(options));
@Test public void testWithDashD() throws CLIException { CLI cli = new DefaultCLI().setName("test"); Option[] options = new Option[]{ new TypedOption<String>().setShortName("D").setLongName("systemProperty") .setMultiValued(true).setType(String.class), new TypedOption<Boolean>().setShortName("F").setLongName("flag") .setFlag(true) .setType(Boolean.class) }; cli.addOptions(Arrays.asList(options)); CommandLine evaluated = cli.parse(Arrays.asList("-Dx=y", "-F")); assertThat(evaluated.cli().getOptions()).hasSize(2); assertThat(evaluated.getRawValueForOption(evaluated.cli().getOption("systemProperty"))) .isEqualTo("x=y"); assertThat((boolean) evaluated.getOptionValue("flag")).isTrue(); }