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

How to get Error message? #513

Closed
IB38 opened this issue Sep 25, 2019 · 4 comments
Closed

How to get Error message? #513

IB38 opened this issue Sep 25, 2019 · 4 comments
Labels

Comments

@IB38
Copy link

IB38 commented Sep 25, 2019

My snippet:

    class Program
    {
        
        public class Args
        {
            [Option('n', "name", Required = true)]
            public string Name { get; set; }

        }
        
        static void Main(string[] args)
        {

            Args parsedArgs;
            Parser.Default.ParseArguments<Args>(args).WithParsed(result => parsedArgs = result).WithNotParsed(ThrowOnParseError);
        }

        private static void ThrowOnParseError(IEnumerable<Error> errors)
        {
            var excList = new List<Exception>();
            foreach (var err in errors)
            {
                excList.Add(new ArgumentException(err.ToString()));
            }
            if (excList.Any())
                throw new AggregateException(excList);
        }
    }

I would like to throw errors as ArgumentException with message being the same message that gets printed when error occurs. For example, when option -n is missing, this text is printed:

CmdLineParserTest 1.0.0.0
Copyright c 2019

ERROR(S):
Required option 'n, name' is missing.

-n, --name Required.

--help Display this help screen.

--version Display version information.

I would like to throw ArgumentException with "Required option 'n, name' is missing." being its message.
I looked into HelpText, but im not sure if it's what i need.

@pha3z
Copy link

pha3z commented Sep 29, 2019

New guy here who is trying out library for first time! I also wanted to do the same thing. :)

err.Tag is an ErrorType Flags enum.
You can do the following to find out if an error flag is set:

if(err.Tag.HasFlag(ErrorType.BadVerbSelectedError))
//Do something for that type of error here

Unfortunately, it looks like you will have to enumerate every single possible ErrorType to handle all cases.

Also, it doesn't let you get the exact error details. Only the error type. The library seems a bit lacking in this regard. Seems weird to have an Errors collection and not have more details in them.

@IB38
Copy link
Author

IB38 commented Sep 30, 2019

Damn, it was really harder than it should have been.
Turns out HelpText was the way to go, but it's so obscure.

Had to do this:

        public class Args
        {
            [Option('n', "name", Required = true)]
            public string Name { get; set; }

        }
        
        static void Main(string[] args)
        {

            Args parsedArgs;
            var parseResult = Parser.Default.ParseArguments<Args>(args);
            parseResult.WithParsed(result => Console.WriteLine(result.Name));
            parseResult.WithNotParsed(errs => ThrowOnParseError(parseResult, errs));
        }

        private static void ThrowOnParseError<T>(ParserResult<T> result, IEnumerable<Error> errors)
        {
            var builder = SentenceBuilder.Create();
            var errorMessages = HelpText.RenderParsingErrorsTextAsLines(result, builder.FormatError, builder.FormatMutuallyExclusiveSetErrors, 1);
            
            var excList = errorMessages.Select(msg => new ArgumentException(msg)).ToList();

            if (excList.Any())
                throw new AggregateException(excList);
        }

@fernandreu
Copy link

fernandreu commented Jan 21, 2020

Nice approach that also worked for me, but I noticed that the error list is actually not needed inside the static method. Also, I think that an extension method would be cleaner in this case:

public static ParserResult<T> ThrowOnParseError<T>(this ParserResult<T> result)
{
    if (!(result is NotParsed<T>))
    {
        // Case with no errors needs to be detected explicitly, otherwise the .Select line will throw an InvalidCastException
        return result;
    }

    var builder = SentenceBuilder.Create();
    var errorMessages = HelpText.RenderParsingErrorsTextAsLines(result, builder.FormatError, builder.FormatMutuallyExclusiveSetErrors, 1);

    var excList = errorMessages.Select(msg => new ArgumentException(msg)).ToList();

    if (excList.Any())
    {
        throw new AggregateException(excList);
    }

    return result;
}

That way, you can keep using the fluent API:

Parser.Default.ParseArguments<Args>(args)
    .WithParsed(result => Console.WriteLine(result.Name))
    .ThrowOnParseError()
    .Etc()

@moh-hassan
Copy link
Collaborator

The [Pr #634) exposes the Errors to the base class, available in develop branch and will be released in v2.9.
You can:

var result = Parser.Default.ParseArguments<Options>(args);
var errors= result.Errors;

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

No branches or pull requests

4 participants