-
Notifications
You must be signed in to change notification settings - Fork 480
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
Expose parsed options object in ParserResult #543
Comments
You can access
|
@moh-hassan That's good to know, I'll use that. I think it would still be nice to have a property available neatly. Are there any specific challenges preventing that? |
- Following update at commandlineparser/commandline#543.
having a simple option to get the parsed options value back would be great. Currently with the callback options, it makes it very difficult to use the // doesn't work...
public static async Task<int> Main(params string[] args)
{
Parser.Default.ParseArguments<Options>(args)
.WithParsed(await RunMyActualProg)
.WithNotParsed(ShowSomeError);
// how to get my return value from `RunMyActualProg` without some weird hacks?
} // works but is ugly...
public static async Task<int> Main(params string[] args)
{
Options options = null;
Parser.Default.ParseArguments<Options>(args)
.WithParsed(o => options = o;)
.WithNotParsed(ShowSomeError);
if ( options !=null )
{
return await RunMyActualProg(options);
}
return 15; // some error code. Arg issues should have been printed from above
} It would be nice to just do something like this instead: // much cleaner than above
public static async Task<int> Main(params string[] args)
{
(Options options, IEnumerable<CommandLine.Error> errors) result =
Parser.Default.ParseArguments<Options>(args).Result;
if (result.options != null)
{
return await RunMyActualProg(result.options);
}
if (result.errors != null)
{
foreach (var err in result.errors) { /* do something with errors */ }
return 1; // command line error
}
return 15; // some error code. Arg issues should have been printed from above
} I think having 3 properties available directly on the ParserResult would be great:
I think this makes the API much more flexible and readable to people who don't, or can't use the callbacks to run the application. I could live without the 3rd option, and just store off the ParserResult using that directly as well. // much cleaner than above
public static async Task<int> Main(params string[] args)
{
ParserResult<Options> result = Parser.Default.ParseArguments<Options>(args);
if (result.Options != null)
{
return await RunMyActualProg(result.Options);
}
if (result.Errors?.Count > 0)
{
foreach (var err in result.Errors) { /* do something with errors */ }
return 1; // command line error
}
return 15; // some error code. Arg issues should have been printed from above
} |
@johnjaylward |
The new methods don't really solve the issue here |
Can you provide the use case that is not working by example. |
From the original above:
The main issue was not having to use the The Async was just a concrete example of how those methods didn't help. It also still doesn't solve the issue with return values from Can we just move the |
If you need to return value to Main, use MapResult |
No offense, but I find using the Something simple like this is optimal for me from a command line parsing perspective: public static async Task<int> Main(params string[] args)
{
Options options = Parser.Default.ParseArguments<Options>(args)?.Value;
if (options == null)
{
return 15; // some error code. Arg issues should have been printed from above
}
return await RunMyActualProg(options);
} This to me shows a clear separation of concerns (command line parsing vs running the program) and I don't have random LINQ type statements making tracing my program take longer than needed. Having |
Good casting to get option. |
I don't agree that that's a good way. It requires the developer to know the implementation that is returned. If an update to the library changes which implementation of the base class is used, the cast will return Would you consider a PR for this if I put one together?
Not needed for simple cases where a developer just wants to parse some simple options and use them right away.
That puts an onus on a consumer of the library to do something that should be fairly out-of-the-box
I would disagree. The |
|
@moh-hassan I've ended up coming back to this issue 2 or 3 times when I add When you say use var parseResult = Parser.Default.ParseArguments<Options>(args);
Options opts;
List<Error> errors = null;
int res = parseResult.MapResult(o => { opts = o; return 0; }, e => { errors = e.ToList(); return 0; });
if(errors?.Count > 0)
{
Console.WriteLine($"Parsing failed: {String.Join('\n', errors)}");
} |
@sipsorcery , I believe that pattern should work. The one I've been using is to just ignore the errors as the default parser generally prints them to stderr anyway. It looks like this: Options? options = (Parser.Default.ParseArguments<Options>(args) as Parsed<Options>)?.Value;
if (options == null)
{
// usage is automatically shown if options == null, which will be true if there is ANY problem parsing the args
return 2; // or whatever your args-parse error code is.
}
// my options got parsed. run my program As long as I don't need to log the argument errors somewhere, I find this is the simplest form to use (at least until v2.9 gets released). |
This is also a decent way if you do want the errors: ParserResult<Options> parserResult = Parser.Default.ParseArguments<Options>(args);
if (parserResult is NotParsed<Options> errors)
// also works by checking the `Tag` property parserResult.Tag==ParserResultType.NotParsed
{
// do something with errors
}
else if (parserResult is Parsed<Options> opts)
// also works by checking the `Tag` property parserResult.Tag==ParserResultType.Parsed
{
// do something with opts
}
else
{
//somehow the result was null or something else completely unexpected
} |
I tried using this library in my project today. I'm able to parse the command line from the examples just fine, but found no way to access the parsed options object directly from
ParserResult
.By my coding style, I prefer not use callbacks here (i.e.
WithParsed
andWithNotParsed
). I'm already able to use theTag
property to check if parsing succeeded. Am I just missing something here or can a property exposing the parsed object be added?The text was updated successfully, but these errors were encountered: