fsprojects / Argu

A declarative CLI argument parser for F#
https://fsprojects.github.io/Argu
MIT License
453 stars 75 forks source link

Subcommands without options #164

Closed dgounaris closed 3 years ago

dgounaris commented 3 years ago

Description

I found myself wanting to use Argu due to its capabilities, particularly in contextual parsing. For my use case, I have 2 commands that can be part of the actual cli command, where one of them has extra arguments while the other one doesn't. This cannot be properly modeled since subcommands need to be of union type and conform to an interface, making it impossible to use an empty type. I opted for subcommands in the first place because the 2 nested commands are mutually exclusive. Is there a different way to implement this? If not, could this be a feature request of adding a a type alongside ParseResults<'Template> that allows simple types as the nested type? (perhaps with fewer operations permitted).

Expected behavior

Ideally, I'd want something like

type UA =
  | V1
  | V2

  interface IArgParserTemplate with
        member this.Usage = ""

type UB =
  interface IArgParserTemplate with
        member this.Usage = ""

type UC =
  | [<CliPrefix(CliPrefix.None)>] VA of ParseResults<UA>
  | [<CliPrefix(CliPrefix.None)>] VB of ParseResults<UB>

Actual behavior

In reality, and for good reason, simple types are not allowed, forcing me to go into something like

type UA =
  | V1
  | V2

  interface IArgParserTemplate with
        member this.Usage = ""

type UB =
  | [<Hidden>] V

  interface IArgParserTemplate with
        member this.Usage = ""

type UC =
  | [<CliPrefix(CliPrefix.None)>] VA of ParseResults<UA>
  | [<CliPrefix(CliPrefix.None)>] VB of ParseResults<UB>

Perhaps I'm missing an obvious solution here, sorry if that's the case, I'm still new to the F# territory.

eiriktsarpalis commented 3 years ago

Hi Dimitris,

Why would you need to define a subcommand if it cannot specify any options of its own? I would probably write it as follows:

type UC =
  | [<CliPrefix(CliPrefix.None)>] VA of ParseResults<UA>
  | [<CliPrefix(CliPrefix.None)>] VB
dgounaris commented 3 years ago

First of all, thank you for the super quick reply.

In that case, wouldn't one be able to write command VA VB? I want them to be mutually exclusive, as they specify different program flows.

eiriktsarpalis commented 3 years ago

command VA VB would not be valid, however it would still be possible to write command VB VA (since VB is just a switch in the root context). To make them mutually exclusive it would be necessary to follow the approach you described initially.

dgounaris commented 3 years ago

Indeed, command VB VA is what I meant, this was just me typing the command example hastily. I deduce from your responses that this isn't considered a usual use-case, so no need to keep the ticket open for implementing such a thing. Closing it, thanks for the response :)