Argu
Argu copied to clipboard
Mandatory arguments in nested subcommands
I am trying to parse something like this:
./esp device status
./esp device status $myId
./esp device add $myId
./esp device remove $myId
To do so I am using this definition:
type DeviceIdArgs =
| [<Mandatory>] [<MainCommand>] Id of string
with
interface IArgParserTemplate with
member this.Usage =
match this with
| Id _ -> "Id of the device to remove"
[<RequireSubcommand>]
type DeviceArgs =
| [<CliPrefix(CliPrefix.None)>] Status of ParseResults<DeviceIdArgs>
| [<CliPrefix(CliPrefix.None)>] Remove of ParseResults<DeviceIdArgs>
| [<CliPrefix(CliPrefix.None)>] Add of ParseResults<DeviceIdArgs>
with
interface IArgParserTemplate with
member this.Usage =
match this with
| Status _ -> "lists all devices currently associated with your account"
| Remove _ -> "removes the device with the given id from your account, use * to remove all"
| Add _ -> "adds a new device with the given id, will return a registration token"
[<RequireSubcommand>]
type EspArgs =
| Version
| [<CliPrefix(CliPrefix.None)>] [<First>] Account of ParseResults<AccountArgs>
| [<CliPrefix(CliPrefix.None)>] [<First>] Device of ParseResults<DeviceArgs>
| [<CliPrefix(CliPrefix.None)>] [<First>] Firmware of ParseResults<FirmwareArgs>
with
interface IArgParserTemplate with
member this.Usage =
match this with
| Version -> "echos the version of this tool"
| Account _ -> "create a backend account, or login to one"
| Device _ -> "list/remove/... devices from your account"
| Firmware _ -> "upload and apply firmware"
This almost works like I want it to. I want to make sure that the user needs to supply an id with the commands. That why I used the MandatoryArgument
for the id
in the DeviceIdArgs
.
Currently ./esp device add
is a valid command.
I am seeing this too:
type Direction =
| Forward
| Backward
| Random
type SequenceArguments =
| [<Mandatory>] Direction of Direction
| Other of string
with
interface IArgParserTemplate with
member this.Usage =
match this with
| Direction _ -> "Specify the direction to use"
| Other _ -> "Added only to test behavior when more than one arg supplied"
type MainArguments =
| [<CliPrefix(CliPrefix.None)>] Sequence of ParseResults<SequenceArguments>
| Version
with
interface IArgParserTemplate with
member this.Usage =
match this with
| Version _ -> "Prints the version of this program."
| Sequence _ -> "Runs sequence subcommand."
[<EntryPoint>]
let main args =
let argumentParser = ArgumentParser.Create<MainArguments>()
try
let arguments = argumentParser.Parse(inputs = args, raiseOnUsage = true)
printfn "%A" arguments
with e ->
printfn "%s" e.Message
I expect these to throw and write out the help:
> my.exe sequence
[Sequence []]
> my.exe sequence --other test
[Sequence [Other "test"]]
Note that no arguments , --help, --version, sequence --help, and sequence --direction all work as expected:
> my.exe
[]
> my.exe --help
USAGE: ......
> my.exe --version
[Version]
> my.exe sequence --help
USAGE: ......
> my.exe sequence --direction
ERROR: argument '--direction' must be followed by <forward|backward|random>.
USAGE: ....
> my.exe sequence --direction forward
[Sequence [Direction Forward]]
Am I missing something in how I should be using the library? Or is this a bug?
I tried adding [<Mandatory>]
to a few subcommands today and noticed it wasn't working, so I'd say this is still a bug. Using PostProcessResult
makes an argument mandatory, so it's not too hard to work around.
@jcmrva the chances are #192 will ship the fix (AFAICT it is the first nuget release that includes #127)
@jcmrva FYI 6.1.2 is on nuget
Thank you!