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

Is it possible to support ./a, ./a -f and ./a -f 3 at the same time? (i.e. optional flags with optional values) #46

Open
Wizek opened this issue Dec 26, 2017 · 3 comments

Comments

@Wizek
Copy link

Wizek commented Dec 26, 2017

I'm in the process of getting to know this library. It's quite nice so far, thanks for writing it!


I tried using Maybe (Maybe Int)

and I got:

No instance for (ParseField (Maybe Int))
    arising from a use of ‘Options.Generic.$dmparseRecord’
• In the expression: Options.Generic.$dmparseRecord @MainOptions

I also thought to model this via:

data OptFlagOptValue a
  = NoFlag
  | Flag
  | FlagValue a

But not sure how I could translate using the above data type into a clean API that supports the following:

$ command
$ command --flag
$ command --flag 123

Am I missing something? Or is this not supported (yet) perhaps?

@Gabriella439
Copy link
Owner

Yeah, this is not supported. The way to understand each class is:

  • ParseRecord: a data type that can be parsed from the command line
  • ParseFields: a data type that can be parsed from zero or more options/arguments
  • ParseField: a data type that can be parsed from a exactly one option/argument

So, for example, the instance for Maybe is:

instance ParseField a => ParseField (Maybe a)

... which says that if you can parse the type a from exactly one option or argument then then you can parse Maybe a from zero or more options/arguments (in this case zero or one occurrences, using Nothing for zero occurrences)

So if you were to add support for this it would require adding a fourth type class to the hierarchy in order to be able to distinguish between types parsed by adding or removing entire options/arguments and types parsed by adding or removing the field to an option argument.

However, there is another issue, which is that your proposal would only work for options (i.e. flags) and not arguments. For example, supposed you had the following option data type:

data Option = Option (Maybe (Maybe Integer)) deriving (Generic, ParseRecord)

How would you parse that on the command line? It doesn't have a field name that can be used as a label for the intermediate case where the flag is present but the field is absent.

@Wizek
Copy link
Author

Wizek commented Dec 28, 2017

data Option = Option (Maybe (Maybe Integer)) deriving (Generic, ParseRecord)

How would you parse that on the command line?

From an API-design standpoint, the following could perhaps make sense:

$ command 123  # --> Just (Just 123)
$ command      # --> Nothing

Or we could allow Maybe (Maybe a) for only named flags and not for positional arguments.

Or we could go with leaving the double maybes unsupported just like now, and only supporting a more specific ADT like the OptFlagOptValue I mentioned above. And perhaps that's easier to add in a way that's only supported for named flags.

@Gabriella439
Copy link
Owner

Yeah, I think a new data type like you mentioned would work well

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

2 participants