-
Notifications
You must be signed in to change notification settings - Fork 434
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
How to programmatically set a value when an @Option wasn't specified to the console? #1915
Comments
Hi David! |
|
The initial value is assigned to the field by the Java runtime, not by picocli. The alternative way to assign default values is via the annotation API , and that won’t work either because it requires compile-time constants. So in short, no, there’s no way to tell picocli that You could of course leave the |
So perhaps you can add such a functionality? I don't see why the IDefaultValueProvider interface can't be used here as well. |
Good point! That should just work with the current version of picocli! |
Thank you, but I think we have a misunderstanding. |
Also, another issue I just figured, does picoli support returning custom objects as default values that aren't Strings? |
Oh I see what you mean now. That would require picocli to manage default provider objects for each option and positional parameter but I don't see what value it would add over the current per-command default provider. |
The |
To be honest, I never touched picoli's commands because my program doesn't offer any commands. So should I switch to working with just 1 command? That would solve my problem, but conceptually that would be wrong in my opinion. |
In my view, any CLI program or utility is a command, whether it has a The It is also where the command's default provider is configured so, yes, that is how I would approach your use case. |
The example application in the user manual is a simple command without subcommands and demonstrates how the |
Hey, I actually got lost... Can I only define just 1 default value provider per command that should handle every missing Option? This doesn't sound ideal, but even if I take this approach, I got completely lost with the implementation... @Override
public String defaultValue(ArgSpec argSpec) throws Exception
{
if(argSpec.isOption() && argSpec.isValueGettable() && argSpec.paramLabel().contains("gameFolder"))
return argSpec.getValue();
else
return GameUtils.getGameFolder().getPath();
} |
Yes that is correct.
I see some code you posted with that observation, but can you clarify what the problem is exactly? |
After reading the code in more detail I think I get it. I would do: @Override
public String defaultValue(ArgSpec argSpec) throws Exception
{
if (argSpec.isOption() && "--gameFolder".equals(((OptionSpec) argSpec).longestName()))
return GameUtils.getGameFolder().getPath(); // the default value for the --gameFolder option
}
} |
This discussion made me realize that the manual does not have an implementation example for |
Hello, if I understand you correctly: (by "value" I mean Parameter/Option)
If my understanding is correct, I do think a provider per value is better because:
I really hope you can consider this ^.^ Edit: Based on the code you provided, I made this possible using this class, do you think I should PR it if you decide to reject the per-value-provider suggestion? |
I agree the provider-per-option design would be simpler/clearer for your use case, but is it really a good idea to add API to the library just for that reason? The existing provider-per-command design covers your use case, and many other use cases. Isn't that what a library's API is supposed to look like: to be generic enough to cover many use cases? There are some use cases that do not yet have a solution, and those take priority. (For example, #1595) Thanks for the offer to provide a PR! I did improve the examples, especially https://github.com/remkop/picocli/blob/main/picocli-examples/src/main/java/picocli/examples/defaultprovider/SimpleDefaultProviderDemo.java, hopefully that helps others get up and running quickly. Interesting discussion, many thanks! |
Alright, first of all I really appreciate the elaborate replies and your will to help me :) I too agree that a library should provide the most generic API in order to cover all use cases, but on the other hand it's worthwhile to consider simplifications if most use cases are implemented a specific way. Consider an unrelated example: public class ExceptionHandlerFactory
{
public static ExceptionHandler logToConsole(String errorMessage)
{
return exception -> System.err.println(String.format(errorMessage, exception));
}
}
//Somewhere in your code: Fluent API + Static import magic:
new FileDownloader("www.coolphotos.com/download/abcde")
.onFinish(file -> ...)
.onError(logToConsole("Cannot download the file because of %s!"))
.download(); The factory here is a facade for the commonly used logging handler, which in reality would be complicated for different scenarios. Back to our discussion: The class doesn't have to be prefixed with "Abstract", but I guess I will have to carry one extra class for every picoli project I will have. |
Glad you were able to get it working! |
After I couldn't find an answer on the docs, I'm opening this issue.
I have been looking for a programmatical alternative for defaultValue, and after trial and error I discovered this is possible:
Which works, but AgeUtils.inferUserAge is called even if the user's age was supplied - so I assume it's an incorrect use of the API.
The text was updated successfully, but these errors were encountered: