natemcmaster / CommandLineUtils

Command line parsing and utilities for .NET

Home Page:https://natemcmaster.github.io/CommandLineUtils/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Question] Best way to implement not required Enum-based option

akulich opened this issue Β· comments

Hello.
I'm trying to implement not required ("optional" πŸ˜„) option backed by Enum using Attribute API.
It's working as expected with this code:

  public class Program
  {
    [Option(CommandOptionType.SingleValue, Description = "Fruit")]
    public FruitEnum Fruit { get; set; }

    private void OnExecute()
    {
      Console.WriteLine(Fruit);
    }
  }

  public enum FruitEnum
  {
    Apple,
    Orange
  }

Help output:

Options:
  -f|--fruit <FRUIT>  Fruit
                      Allowed values are: Apple, Orange

But if I try to make Fruit nullable (e.g. public FruitEnum? Fruit { get; set; }) it doesn't work anymore (because it's no longer Enum but Nullable).

The goal is to preserve the same functionality but not add artificial value to Enum (like Unknown). What would be the best approach?

Thanks!

I encountered the same issue. As a work around you can specify your own help text to display the same values. If requires you to maintain the list of enum value in a string field, which is not ideal if your enums change over time.

Ideally you are correct that a nullable enum should still all the enum values.

Came up with another solution. Keeping option property non-nullable (public FruitEnum Fruit { get; set; }) and getting option value from CommandLineApplication:

    private void OnExecute(CommandLineApplication app)
    {
      Console.WriteLine(GetFruit(app, nameof(Fruit).ToUpper()));
    }

    private static FruitEnum? GetFruit(CommandLineApplication app, string optionValueName)
    {
      FruitEnum? result = null;
      var option = app.Options.SingleOrDefault(x => x.ValueName == optionValueName);
      if (option?.HasValue() == true && Enum.TryParse(option.Values.First(), true, out FruitEnum outValue))
        result = outValue;
      return result;
    }

Would appreciate comments or any other suggestions.

@akulich Would you mind sharing your help text when you use ValueTuple? just out of curiosity.

Is it

Options:
  -f|--fruit[:<FRUIT>]  Fruit
                        Allowed values are: Apple, Orange

or

Options:
  -f|--fruit[:<FRUIT>]  Fruit

From my test, it is the later one which is still an issue for the help text.

I haven't tried it yet, but I don't think I'll get results different from yours.
I'll let you know if I would.

Options:
  -f|--fruit[:<FRUIT>]  Fruit

From my test, it is the later one which is still an issue for the help text.

Allowed values indeed won't be shown in case of ValueTuple, but you can still add them to the description manually (less convenient for my use case, but still doable).

Thanks for your info. I've made a PR for it. Hope @natemcmaster could give a review when he is free.

But if I try to make Fruit nullable (e.g. public FruitEnum? Fruit { get; set; }) it doesn't work anymore (because it's no longer Enum but Nullable).

I'm assuming that by "it doesn't work anymore" you mean that the help text doesn't list available values automatically, right? If that's the only thing you meant, then @scott-xu's PR #390 will resolve this.

But if I try to make Fruit nullable (e.g. public FruitEnum? Fruit { get; set; }) it doesn't work anymore (because it's no longer Enum but Nullable).

I'm assuming that by "it doesn't work anymore" you mean that the help text doesn't list available values automatically, right? If that's the only thing you meant, then @scott-xu's PR #390 will resolve this.

That's correct. Thanks for you feedback @natemcmaster and thanks @scott-xu for the PR!