commander-cli icon indicating copy to clipboard operation
commander-cli copied to clipboard

Generics for Records

Open BebeSparkelSparkel opened this issue 2 years ago • 5 comments

I find to be filling in a lot of record fields from the cli parameters and it would be much faster to have some generic way of generating parser code.

data AB f = AB {a :: f Int, b :: f String}

type ProgramType :: Type -> Type
type family ProgramType a

genericOptions :: forall (mkOption :: Symbol -> Symbol) (mkName :: Symbol -> Symbol) p b m a. Generic a => (a -> ParserT p m b) -> ParserT (ProgramType (Rep a) & p) m b)

Which genericOptions @("--" ++) @ID @(AB Maybe) would generate something like

\f ->
  opt @"--a" @"a" $ \a ->
  opt @"--b" @"b" $ \b ->
  f AB {..}

There seems like there could be several versions for Opt Arg Flag. Does this make sense or is there a better way?

BebeSparkelSparkel avatar May 10 '23 16:05 BebeSparkelSparkel

I think this makes sense, seems like a reasonable approach.

SamuelSchlesinger avatar May 10 '23 17:05 SamuelSchlesinger

I have created a simplistic working example https://github.com/BebeSparkelSparkel/commander-cli/blob/generics/src/Options/Commander/Generics.hs

What do you think?

BebeSparkelSparkel avatar May 10 '23 19:05 BebeSparkelSparkel

One problem I am having is how to allow for descriptions.

Perhaps there could be a type like newtype Description (d :: Symbol) a = Description a, but that seems invasive.

Or a type family Description (datatype :: Symbol) (module :: Symbol) (package :: Symbol) (fieldName :: Symbol) :: Symbol that would resolve to the description.

BebeSparkelSparkel avatar May 10 '23 19:05 BebeSparkelSparkel

I honestly wouldn't mind the newtype at all, I think that's quite helpful. Looks like it's on the right track, but I'm concerned about all of them being arguments rather than options and so on. Another thing to keep in mind is that this functionality is already very easily implemented by optparse-generic and I'm not so sure I want to encourage people to use this package for this functionality when its (arguably) better implemented in that package.

I'd be happy to help plug away at a patch which implemented this functionality well, but I'd be more likely to push it up to hackage if we:

  • allow options, flags, and arguments in the record fields
  • support sum types to have a fully alternative approach to defining CLIs
  • provide extensive documentation Once all that stuff is included, then I'd be totally down to push to Hackage.

Looks pretty doable from your code though, appreciate the example.

SamuelSchlesinger avatar May 29 '23 18:05 SamuelSchlesinger

Thanks for the optparse-generic link. I'll look at that carefully. It might be the better option.

BebeSparkelSparkel avatar Jun 02 '23 16:06 BebeSparkelSparkel