Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Support options of types without (String) constructor #40

Open
okorz001 opened this issue Mar 31, 2018 · 0 comments
Open

Feature: Support options of types without (String) constructor #40

okorz001 opened this issue Mar 31, 2018 · 0 comments

Comments

@okorz001
Copy link

JewelCli 0.8.9 requires that the type of an option has a (String) constructor, but many value types do not meet this requirement.

Exception in thread "main" java.lang.ClassCastException: cannot convert class java.lang.String to interface java.nio.file.Path
	at com.lexicalscope.jewel.cli.ConvertTypeOfObject.convertValueTo(ConvertTypeOfObject.java:159)
	at com.lexicalscope.jewel.cli.ConvertTypeOfObject.convert(ConvertTypeOfObject.java:98)
	at com.lexicalscope.jewel.cli.ArgumentPresenterImpl.putValuesInMap(ArgumentPresenterImpl.java:79)
	at com.lexicalscope.jewel.cli.ArgumentPresenterImpl.presentArguments(ArgumentPresenterImpl.java:40)
	at com.lexicalscope.jewel.cli.AbstractCliImpl.parseArguments(AbstractCliImpl.java:42)

The workaround is to build an intermediate type that parses a String into the desired type, but since JewelCli also does not support Java 8 default methods (#38), this cannot be done transparently.

Other option libraries such as jopt-simple (see withValuesConvertedBy) allow a factory method to be registered in case a constructor is not available or is otherwise undesirable.

Here's two different ways to do this:

  1. Add a parser attribute to @Option that accepts a Class<? extends Function<String, ?>>. The main downside of this approach is that, as far as I know, we cannot guarantee the function return type matches the annotated method's return type at compile time. :( It can also cause some duplication if there are multiple arguments of the same type, but on the other hand it has the flexibility of allowing different parsers (or validators) for each argument as well.

  2. Add a method to either Cli or CliFactory to register a parser, e.g. <T> Cli<O> withParser(Class<T>, Function<String, T>). The downside of this is that it is not aligned with the rest of JewelCli's annotation-centric API.

I think the first approach is more desirable since it maintains API consistency and option parsing tends to happen very early in the application, lessening the pain of errors at runtime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant