//------------------------------------------------------------------------------ // This code was generated by myriad. // Changes to this file will be lost when the code is regenerated. //------------------------------------------------------------------------------ namespace ConsumePlugin open System open System.IO open WoofWare.Myriad.Plugins /// Methods to parse arguments for the type BasicNoPositionals [] module BasicNoPositionals = type private ParseState_BasicNoPositionals = | AwaitingKey | AwaitingValue of key : string let parse' (getEnvironmentVariable : string -> string) (args : string list) : BasicNoPositionals = let ArgParser_errors = ResizeArray () let helpText () = [ (sprintf "--foo int32%s%s" "" "") (sprintf "--bar string%s%s" "" "") (sprintf "--baz bool%s%s" "" "") (sprintf "--rest int32%s%s" " (can be repeated)" "") ] |> String.concat "\n" let parser_LeftoverArgs : string ResizeArray = ResizeArray () let mutable Foo : int option = None let mutable Bar : string option = None let mutable Baz : bool option = None let Rest : int ResizeArray = ResizeArray () /// Processes the key-value pair, returning Error if no key was matched. /// If the key is an arg which can arity 1, but throws when consuming that arg, we return Error(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. let processKeyValue (key : string) (value : string) : Result = if System.String.Equals (key, "--rest", System.StringComparison.OrdinalIgnoreCase) then (fun x -> System.Int32.Parse x) value |> Rest.Add () |> Ok else if System.String.Equals (key, "--baz", System.StringComparison.OrdinalIgnoreCase) then match Baz with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--baz" x value |> ArgParser_errors.Add Ok () | None -> try Baz <- value |> (fun x -> System.Boolean.Parse x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--bar", System.StringComparison.OrdinalIgnoreCase) then match Bar with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--bar" x value |> ArgParser_errors.Add Ok () | None -> try Bar <- value |> (fun x -> x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--foo", System.StringComparison.OrdinalIgnoreCase) then match Foo with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--foo" x value |> ArgParser_errors.Add Ok () | None -> try Foo <- value |> (fun x -> System.Int32.Parse x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else Error None /// Returns false if we didn't set a value. let setFlagValue (key : string) : bool = if System.String.Equals (key, "--baz", System.StringComparison.OrdinalIgnoreCase) then match Baz with | Some x -> sprintf "Flag '%s' was supplied multiple times" "--baz" |> ArgParser_errors.Add true | None -> Baz <- Some true true else false let rec go (state : ParseState_BasicNoPositionals) (args : string list) = match args with | [] -> match state with | ParseState_BasicNoPositionals.AwaitingKey -> () | ParseState_BasicNoPositionals.AwaitingValue key -> if setFlagValue key then () else sprintf "Trailing argument %s had no value. Use a double-dash to separate positional args from key-value args." key |> ArgParser_errors.Add | "--" :: rest -> parser_LeftoverArgs.AddRange (rest |> Seq.map (fun x -> x)) | arg :: args -> match state with | ParseState_BasicNoPositionals.AwaitingKey -> if arg.StartsWith ("--", System.StringComparison.Ordinal) then if arg = "--help" then helpText () |> failwithf "Help text requested.\n%s" else let equals = arg.IndexOf (char 61) if equals < 0 then args |> go (ParseState_BasicNoPositionals.AwaitingValue arg) else let key = arg.[0 .. equals - 1] let value = arg.[equals + 1 ..] match processKeyValue key value with | Ok () -> go ParseState_BasicNoPositionals.AwaitingKey args | Error None -> failwithf "Unable to process argument %s as key %s and value %s" arg key value | Error (Some msg) -> sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add go ParseState_BasicNoPositionals.AwaitingKey args else arg |> (fun x -> x) |> parser_LeftoverArgs.Add go ParseState_BasicNoPositionals.AwaitingKey args | ParseState_BasicNoPositionals.AwaitingValue key -> match processKeyValue key arg with | Ok () -> go ParseState_BasicNoPositionals.AwaitingKey args | Error exc -> if setFlagValue key then go ParseState_BasicNoPositionals.AwaitingKey (arg :: args) else match exc with | None -> failwithf "Unable to process supplied arg %s. Help text follows.\n%s" key (helpText ()) | Some msg -> msg |> ArgParser_errors.Add go ParseState_BasicNoPositionals.AwaitingKey args let parser_LeftoverArgs = if 0 = parser_LeftoverArgs.Count then () else parser_LeftoverArgs |> String.concat " " |> sprintf "There were leftover args: %s" |> ArgParser_errors.Add Unchecked.defaultof<_> let Foo = match Foo with | None -> sprintf "Required argument '%s' received no value" "--foo" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let Bar = match Bar with | None -> sprintf "Required argument '%s' received no value" "--bar" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let Baz = match Baz with | None -> sprintf "Required argument '%s' received no value" "--baz" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let Rest = Rest |> Seq.toList if 0 = ArgParser_errors.Count then { Foo = Foo Bar = Bar Baz = Baz Rest = Rest } else ArgParser_errors |> String.concat "\n" |> failwithf "Errors during parse!\n%s" let parse (args : string list) : BasicNoPositionals = parse' System.Environment.GetEnvironmentVariable args namespace ConsumePlugin open System open System.IO open WoofWare.Myriad.Plugins /// Methods to parse arguments for the type Basic [] module Basic = type private ParseState_Basic = | AwaitingKey | AwaitingValue of key : string let parse' (getEnvironmentVariable : string -> string) (args : string list) : Basic = let ArgParser_errors = ResizeArray () let helpText () = [ (sprintf "--foo int32%s%s" "" (sprintf " : %s" ("This is a foo!"))) (sprintf "--bar string%s%s" "" "") (sprintf "--baz bool%s%s" "" "") (sprintf "--rest string (positional args)%s%s" " (can be repeated)" (sprintf " : %s" ("Here's where the rest of the args go"))) ] |> String.concat "\n" let Rest : string ResizeArray = ResizeArray () let mutable Foo : int option = None let mutable Bar : string option = None let mutable Baz : bool option = None /// Processes the key-value pair, returning Error if no key was matched. /// If the key is an arg which can arity 1, but throws when consuming that arg, we return Error(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. let processKeyValue (key : string) (value : string) : Result = if System.String.Equals (key, "--baz", System.StringComparison.OrdinalIgnoreCase) then match Baz with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--baz" x value |> ArgParser_errors.Add Ok () | None -> try Baz <- value |> (fun x -> System.Boolean.Parse x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--bar", System.StringComparison.OrdinalIgnoreCase) then match Bar with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--bar" x value |> ArgParser_errors.Add Ok () | None -> try Bar <- value |> (fun x -> x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--foo", System.StringComparison.OrdinalIgnoreCase) then match Foo with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--foo" x value |> ArgParser_errors.Add Ok () | None -> try Foo <- value |> (fun x -> System.Int32.Parse x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--rest", System.StringComparison.OrdinalIgnoreCase) then (fun x -> x) value |> Rest.Add () |> Ok else Error None /// Returns false if we didn't set a value. let setFlagValue (key : string) : bool = if System.String.Equals (key, "--baz", System.StringComparison.OrdinalIgnoreCase) then match Baz with | Some x -> sprintf "Flag '%s' was supplied multiple times" "--baz" |> ArgParser_errors.Add true | None -> Baz <- Some true true else false let rec go (state : ParseState_Basic) (args : string list) = match args with | [] -> match state with | ParseState_Basic.AwaitingKey -> () | ParseState_Basic.AwaitingValue key -> if setFlagValue key then () else sprintf "Trailing argument %s had no value. Use a double-dash to separate positional args from key-value args." key |> ArgParser_errors.Add | "--" :: rest -> Rest.AddRange (rest |> Seq.map (fun x -> x)) | arg :: args -> match state with | ParseState_Basic.AwaitingKey -> if arg.StartsWith ("--", System.StringComparison.Ordinal) then if arg = "--help" then helpText () |> failwithf "Help text requested.\n%s" else let equals = arg.IndexOf (char 61) if equals < 0 then args |> go (ParseState_Basic.AwaitingValue arg) else let key = arg.[0 .. equals - 1] let value = arg.[equals + 1 ..] match processKeyValue key value with | Ok () -> go ParseState_Basic.AwaitingKey args | Error None -> failwithf "Unable to process argument %s as key %s and value %s" arg key value | Error (Some msg) -> sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add go ParseState_Basic.AwaitingKey args else arg |> (fun x -> x) |> Rest.Add go ParseState_Basic.AwaitingKey args | ParseState_Basic.AwaitingValue key -> match processKeyValue key arg with | Ok () -> go ParseState_Basic.AwaitingKey args | Error exc -> if setFlagValue key then go ParseState_Basic.AwaitingKey (arg :: args) else match exc with | None -> failwithf "Unable to process supplied arg %s. Help text follows.\n%s" key (helpText ()) | Some msg -> msg |> ArgParser_errors.Add go ParseState_Basic.AwaitingKey args let Rest = Rest |> Seq.toList let Foo = match Foo with | None -> sprintf "Required argument '%s' received no value" "--foo" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let Bar = match Bar with | None -> sprintf "Required argument '%s' received no value" "--bar" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let Baz = match Baz with | None -> sprintf "Required argument '%s' received no value" "--baz" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x if 0 = ArgParser_errors.Count then { Rest = Rest Foo = Foo Bar = Bar Baz = Baz } else ArgParser_errors |> String.concat "\n" |> failwithf "Errors during parse!\n%s" let parse (args : string list) : Basic = parse' System.Environment.GetEnvironmentVariable args namespace ConsumePlugin open System open System.IO open WoofWare.Myriad.Plugins /// Methods to parse arguments for the type BasicWithIntPositionals [] module BasicWithIntPositionals = type private ParseState_BasicWithIntPositionals = | AwaitingKey | AwaitingValue of key : string let parse' (getEnvironmentVariable : string -> string) (args : string list) : BasicWithIntPositionals = let ArgParser_errors = ResizeArray () let helpText () = [ (sprintf "--foo int32%s%s" "" "") (sprintf "--bar string%s%s" "" "") (sprintf "--baz bool%s%s" "" "") (sprintf "--rest int32 (positional args)%s%s" " (can be repeated)" "") ] |> String.concat "\n" let Rest : int ResizeArray = ResizeArray () let mutable Foo : int option = None let mutable Bar : string option = None let mutable Baz : bool option = None /// Processes the key-value pair, returning Error if no key was matched. /// If the key is an arg which can arity 1, but throws when consuming that arg, we return Error(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. let processKeyValue (key : string) (value : string) : Result = if System.String.Equals (key, "--baz", System.StringComparison.OrdinalIgnoreCase) then match Baz with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--baz" x value |> ArgParser_errors.Add Ok () | None -> try Baz <- value |> (fun x -> System.Boolean.Parse x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--bar", System.StringComparison.OrdinalIgnoreCase) then match Bar with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--bar" x value |> ArgParser_errors.Add Ok () | None -> try Bar <- value |> (fun x -> x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--foo", System.StringComparison.OrdinalIgnoreCase) then match Foo with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--foo" x value |> ArgParser_errors.Add Ok () | None -> try Foo <- value |> (fun x -> System.Int32.Parse x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--rest", System.StringComparison.OrdinalIgnoreCase) then (fun x -> System.Int32.Parse x) value |> Rest.Add () |> Ok else Error None /// Returns false if we didn't set a value. let setFlagValue (key : string) : bool = if System.String.Equals (key, "--baz", System.StringComparison.OrdinalIgnoreCase) then match Baz with | Some x -> sprintf "Flag '%s' was supplied multiple times" "--baz" |> ArgParser_errors.Add true | None -> Baz <- Some true true else false let rec go (state : ParseState_BasicWithIntPositionals) (args : string list) = match args with | [] -> match state with | ParseState_BasicWithIntPositionals.AwaitingKey -> () | ParseState_BasicWithIntPositionals.AwaitingValue key -> if setFlagValue key then () else sprintf "Trailing argument %s had no value. Use a double-dash to separate positional args from key-value args." key |> ArgParser_errors.Add | "--" :: rest -> Rest.AddRange (rest |> Seq.map (fun x -> System.Int32.Parse x)) | arg :: args -> match state with | ParseState_BasicWithIntPositionals.AwaitingKey -> if arg.StartsWith ("--", System.StringComparison.Ordinal) then if arg = "--help" then helpText () |> failwithf "Help text requested.\n%s" else let equals = arg.IndexOf (char 61) if equals < 0 then args |> go (ParseState_BasicWithIntPositionals.AwaitingValue arg) else let key = arg.[0 .. equals - 1] let value = arg.[equals + 1 ..] match processKeyValue key value with | Ok () -> go ParseState_BasicWithIntPositionals.AwaitingKey args | Error None -> failwithf "Unable to process argument %s as key %s and value %s" arg key value | Error (Some msg) -> sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add go ParseState_BasicWithIntPositionals.AwaitingKey args else arg |> (fun x -> System.Int32.Parse x) |> Rest.Add go ParseState_BasicWithIntPositionals.AwaitingKey args | ParseState_BasicWithIntPositionals.AwaitingValue key -> match processKeyValue key arg with | Ok () -> go ParseState_BasicWithIntPositionals.AwaitingKey args | Error exc -> if setFlagValue key then go ParseState_BasicWithIntPositionals.AwaitingKey (arg :: args) else match exc with | None -> failwithf "Unable to process supplied arg %s. Help text follows.\n%s" key (helpText ()) | Some msg -> msg |> ArgParser_errors.Add go ParseState_BasicWithIntPositionals.AwaitingKey args let Rest = Rest |> Seq.toList let Foo = match Foo with | None -> sprintf "Required argument '%s' received no value" "--foo" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let Bar = match Bar with | None -> sprintf "Required argument '%s' received no value" "--bar" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let Baz = match Baz with | None -> sprintf "Required argument '%s' received no value" "--baz" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x if 0 = ArgParser_errors.Count then { Rest = Rest Foo = Foo Bar = Bar Baz = Baz } else ArgParser_errors |> String.concat "\n" |> failwithf "Errors during parse!\n%s" let parse (args : string list) : BasicWithIntPositionals = parse' System.Environment.GetEnvironmentVariable args namespace ConsumePlugin open System open System.IO open WoofWare.Myriad.Plugins /// Methods to parse arguments for the type LoadsOfTypes [] module LoadsOfTypes = type private ParseState_LoadsOfTypes = | AwaitingKey | AwaitingValue of key : string let parse' (getEnvironmentVariable : string -> string) (args : string list) : LoadsOfTypes = let ArgParser_errors = ResizeArray () let helpText () = [ (sprintf "--foo int32%s%s" "" "") (sprintf "--bar string%s%s" "" "") (sprintf "--baz bool%s%s" "" "") (sprintf "--some-file FileInfo%s%s" "" "") (sprintf "--some-directory DirectoryInfo%s%s" "" "") (sprintf "--some-list DirectoryInfo%s%s" " (can be repeated)" "") (sprintf "--optional-thing-with-no-default int32%s%s" " (optional)" "") (sprintf "--optional-thing bool%s%s" (LoadsOfTypes.DefaultOptionalThing () |> sprintf " (default value: %O)") "") (sprintf "--another-optional-thing int32%s%s" (LoadsOfTypes.DefaultAnotherOptionalThing () |> sprintf " (default value: %O)") "") (sprintf "--yet-another-optional-thing string%s%s" ("CONSUMEPLUGIN_THINGS" |> sprintf " (default value populated from env var %s)") "") (sprintf "--positionals int32 (positional args)%s%s" " (can be repeated)" "") ] |> String.concat "\n" let Positionals : int ResizeArray = ResizeArray () let mutable Foo : int option = None let mutable Bar : string option = None let mutable Baz : bool option = None let mutable SomeFile : FileInfo option = None let mutable SomeDirectory : DirectoryInfo option = None let SomeList : DirectoryInfo ResizeArray = ResizeArray () let mutable OptionalThingWithNoDefault : int option = None let mutable OptionalThing : bool option = None let mutable AnotherOptionalThing : int option = None let mutable YetAnotherOptionalThing : string option = None /// Processes the key-value pair, returning Error if no key was matched. /// If the key is an arg which can arity 1, but throws when consuming that arg, we return Error(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. let processKeyValue (key : string) (value : string) : Result = if System.String.Equals (key, "--yet-another-optional-thing", System.StringComparison.OrdinalIgnoreCase) then match YetAnotherOptionalThing with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--yet-another-optional-thing" x value |> ArgParser_errors.Add Ok () | None -> try YetAnotherOptionalThing <- value |> (fun x -> x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--another-optional-thing", System.StringComparison.OrdinalIgnoreCase) then match AnotherOptionalThing with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--another-optional-thing" x value |> ArgParser_errors.Add Ok () | None -> try AnotherOptionalThing <- value |> (fun x -> System.Int32.Parse x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--optional-thing", System.StringComparison.OrdinalIgnoreCase) then match OptionalThing with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--optional-thing" x value |> ArgParser_errors.Add Ok () | None -> try OptionalThing <- value |> (fun x -> System.Boolean.Parse x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals ( key, "--optional-thing-with-no-default", System.StringComparison.OrdinalIgnoreCase ) then match OptionalThingWithNoDefault with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--optional-thing-with-no-default" x value |> ArgParser_errors.Add Ok () | None -> try OptionalThingWithNoDefault <- value |> (fun x -> System.Int32.Parse x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--some-list", System.StringComparison.OrdinalIgnoreCase) then (fun x -> System.IO.DirectoryInfo x) value |> SomeList.Add () |> Ok else if System.String.Equals (key, "--some-directory", System.StringComparison.OrdinalIgnoreCase) then match SomeDirectory with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--some-directory" x value |> ArgParser_errors.Add Ok () | None -> try SomeDirectory <- value |> (fun x -> System.IO.DirectoryInfo x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--some-file", System.StringComparison.OrdinalIgnoreCase) then match SomeFile with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--some-file" x value |> ArgParser_errors.Add Ok () | None -> try SomeFile <- value |> (fun x -> System.IO.FileInfo x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--baz", System.StringComparison.OrdinalIgnoreCase) then match Baz with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--baz" x value |> ArgParser_errors.Add Ok () | None -> try Baz <- value |> (fun x -> System.Boolean.Parse x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--bar", System.StringComparison.OrdinalIgnoreCase) then match Bar with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--bar" x value |> ArgParser_errors.Add Ok () | None -> try Bar <- value |> (fun x -> x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--foo", System.StringComparison.OrdinalIgnoreCase) then match Foo with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--foo" x value |> ArgParser_errors.Add Ok () | None -> try Foo <- value |> (fun x -> System.Int32.Parse x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--positionals", System.StringComparison.OrdinalIgnoreCase) then (fun x -> System.Int32.Parse x) value |> Positionals.Add () |> Ok else Error None /// Returns false if we didn't set a value. let setFlagValue (key : string) : bool = if System.String.Equals (key, "--optional-thing", System.StringComparison.OrdinalIgnoreCase) then match OptionalThing with | Some x -> sprintf "Flag '%s' was supplied multiple times" "--optional-thing" |> ArgParser_errors.Add true | None -> OptionalThing <- Some true true else if System.String.Equals (key, "--baz", System.StringComparison.OrdinalIgnoreCase) then match Baz with | Some x -> sprintf "Flag '%s' was supplied multiple times" "--baz" |> ArgParser_errors.Add true | None -> Baz <- Some true true else false let rec go (state : ParseState_LoadsOfTypes) (args : string list) = match args with | [] -> match state with | ParseState_LoadsOfTypes.AwaitingKey -> () | ParseState_LoadsOfTypes.AwaitingValue key -> if setFlagValue key then () else sprintf "Trailing argument %s had no value. Use a double-dash to separate positional args from key-value args." key |> ArgParser_errors.Add | "--" :: rest -> Positionals.AddRange (rest |> Seq.map (fun x -> System.Int32.Parse x)) | arg :: args -> match state with | ParseState_LoadsOfTypes.AwaitingKey -> if arg.StartsWith ("--", System.StringComparison.Ordinal) then if arg = "--help" then helpText () |> failwithf "Help text requested.\n%s" else let equals = arg.IndexOf (char 61) if equals < 0 then args |> go (ParseState_LoadsOfTypes.AwaitingValue arg) else let key = arg.[0 .. equals - 1] let value = arg.[equals + 1 ..] match processKeyValue key value with | Ok () -> go ParseState_LoadsOfTypes.AwaitingKey args | Error None -> failwithf "Unable to process argument %s as key %s and value %s" arg key value | Error (Some msg) -> sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add go ParseState_LoadsOfTypes.AwaitingKey args else arg |> (fun x -> System.Int32.Parse x) |> Positionals.Add go ParseState_LoadsOfTypes.AwaitingKey args | ParseState_LoadsOfTypes.AwaitingValue key -> match processKeyValue key arg with | Ok () -> go ParseState_LoadsOfTypes.AwaitingKey args | Error exc -> if setFlagValue key then go ParseState_LoadsOfTypes.AwaitingKey (arg :: args) else match exc with | None -> failwithf "Unable to process supplied arg %s. Help text follows.\n%s" key (helpText ()) | Some msg -> msg |> ArgParser_errors.Add go ParseState_LoadsOfTypes.AwaitingKey args let Positionals = Positionals |> Seq.toList let Foo = match Foo with | None -> sprintf "Required argument '%s' received no value" "--foo" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let Bar = match Bar with | None -> sprintf "Required argument '%s' received no value" "--bar" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let Baz = match Baz with | None -> sprintf "Required argument '%s' received no value" "--baz" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let SomeFile = match SomeFile with | None -> sprintf "Required argument '%s' received no value" "--some-file" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let SomeDirectory = match SomeDirectory with | None -> sprintf "Required argument '%s' received no value" "--some-directory" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let SomeList = SomeList |> Seq.toList let OptionalThingWithNoDefault = OptionalThingWithNoDefault let OptionalThing = match OptionalThing with | None -> LoadsOfTypes.DefaultOptionalThing () |> Choice2Of2 | Some x -> Choice1Of2 x let AnotherOptionalThing = match AnotherOptionalThing with | None -> LoadsOfTypes.DefaultAnotherOptionalThing () |> Choice2Of2 | Some x -> Choice1Of2 x let YetAnotherOptionalThing = match YetAnotherOptionalThing with | None -> match "CONSUMEPLUGIN_THINGS" |> getEnvironmentVariable with | null -> sprintf "No value was supplied for %s, nor was environment variable %s set" "--yet-another-optional-thing" "CONSUMEPLUGIN_THINGS" |> ArgParser_errors.Add Unchecked.defaultof<_> | x -> x |> (fun x -> x) |> Choice2Of2 | Some x -> Choice1Of2 x if 0 = ArgParser_errors.Count then { Positionals = Positionals Foo = Foo Bar = Bar Baz = Baz SomeFile = SomeFile SomeDirectory = SomeDirectory SomeList = SomeList OptionalThingWithNoDefault = OptionalThingWithNoDefault OptionalThing = OptionalThing AnotherOptionalThing = AnotherOptionalThing YetAnotherOptionalThing = YetAnotherOptionalThing } else ArgParser_errors |> String.concat "\n" |> failwithf "Errors during parse!\n%s" let parse (args : string list) : LoadsOfTypes = parse' System.Environment.GetEnvironmentVariable args namespace ConsumePlugin open System open System.IO open WoofWare.Myriad.Plugins /// Methods to parse arguments for the type LoadsOfTypesNoPositionals [] module LoadsOfTypesNoPositionals = type private ParseState_LoadsOfTypesNoPositionals = | AwaitingKey | AwaitingValue of key : string let parse' (getEnvironmentVariable : string -> string) (args : string list) : LoadsOfTypesNoPositionals = let ArgParser_errors = ResizeArray () let helpText () = [ (sprintf "--foo int32%s%s" "" "") (sprintf "--bar string%s%s" "" "") (sprintf "--baz bool%s%s" "" "") (sprintf "--some-file FileInfo%s%s" "" "") (sprintf "--some-directory DirectoryInfo%s%s" "" "") (sprintf "--some-list DirectoryInfo%s%s" " (can be repeated)" "") (sprintf "--optional-thing-with-no-default int32%s%s" " (optional)" "") (sprintf "--optional-thing bool%s%s" (LoadsOfTypesNoPositionals.DefaultOptionalThing () |> sprintf " (default value: %O)") "") (sprintf "--another-optional-thing int32%s%s" (LoadsOfTypesNoPositionals.DefaultAnotherOptionalThing () |> sprintf " (default value: %O)") "") (sprintf "--yet-another-optional-thing string%s%s" ("CONSUMEPLUGIN_THINGS" |> sprintf " (default value populated from env var %s)") "") ] |> String.concat "\n" let parser_LeftoverArgs : string ResizeArray = ResizeArray () let mutable Foo : int option = None let mutable Bar : string option = None let mutable Baz : bool option = None let mutable SomeFile : FileInfo option = None let mutable SomeDirectory : DirectoryInfo option = None let SomeList : DirectoryInfo ResizeArray = ResizeArray () let mutable OptionalThingWithNoDefault : int option = None let mutable OptionalThing : bool option = None let mutable AnotherOptionalThing : int option = None let mutable YetAnotherOptionalThing : string option = None /// Processes the key-value pair, returning Error if no key was matched. /// If the key is an arg which can arity 1, but throws when consuming that arg, we return Error(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. let processKeyValue (key : string) (value : string) : Result = if System.String.Equals (key, "--yet-another-optional-thing", System.StringComparison.OrdinalIgnoreCase) then match YetAnotherOptionalThing with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--yet-another-optional-thing" x value |> ArgParser_errors.Add Ok () | None -> try YetAnotherOptionalThing <- value |> (fun x -> x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--another-optional-thing", System.StringComparison.OrdinalIgnoreCase) then match AnotherOptionalThing with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--another-optional-thing" x value |> ArgParser_errors.Add Ok () | None -> try AnotherOptionalThing <- value |> (fun x -> System.Int32.Parse x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--optional-thing", System.StringComparison.OrdinalIgnoreCase) then match OptionalThing with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--optional-thing" x value |> ArgParser_errors.Add Ok () | None -> try OptionalThing <- value |> (fun x -> System.Boolean.Parse x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals ( key, "--optional-thing-with-no-default", System.StringComparison.OrdinalIgnoreCase ) then match OptionalThingWithNoDefault with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--optional-thing-with-no-default" x value |> ArgParser_errors.Add Ok () | None -> try OptionalThingWithNoDefault <- value |> (fun x -> System.Int32.Parse x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--some-list", System.StringComparison.OrdinalIgnoreCase) then (fun x -> System.IO.DirectoryInfo x) value |> SomeList.Add () |> Ok else if System.String.Equals (key, "--some-directory", System.StringComparison.OrdinalIgnoreCase) then match SomeDirectory with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--some-directory" x value |> ArgParser_errors.Add Ok () | None -> try SomeDirectory <- value |> (fun x -> System.IO.DirectoryInfo x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--some-file", System.StringComparison.OrdinalIgnoreCase) then match SomeFile with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--some-file" x value |> ArgParser_errors.Add Ok () | None -> try SomeFile <- value |> (fun x -> System.IO.FileInfo x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--baz", System.StringComparison.OrdinalIgnoreCase) then match Baz with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--baz" x value |> ArgParser_errors.Add Ok () | None -> try Baz <- value |> (fun x -> System.Boolean.Parse x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--bar", System.StringComparison.OrdinalIgnoreCase) then match Bar with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--bar" x value |> ArgParser_errors.Add Ok () | None -> try Bar <- value |> (fun x -> x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--foo", System.StringComparison.OrdinalIgnoreCase) then match Foo with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--foo" x value |> ArgParser_errors.Add Ok () | None -> try Foo <- value |> (fun x -> System.Int32.Parse x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else Error None /// Returns false if we didn't set a value. let setFlagValue (key : string) : bool = if System.String.Equals (key, "--optional-thing", System.StringComparison.OrdinalIgnoreCase) then match OptionalThing with | Some x -> sprintf "Flag '%s' was supplied multiple times" "--optional-thing" |> ArgParser_errors.Add true | None -> OptionalThing <- Some true true else if System.String.Equals (key, "--baz", System.StringComparison.OrdinalIgnoreCase) then match Baz with | Some x -> sprintf "Flag '%s' was supplied multiple times" "--baz" |> ArgParser_errors.Add true | None -> Baz <- Some true true else false let rec go (state : ParseState_LoadsOfTypesNoPositionals) (args : string list) = match args with | [] -> match state with | ParseState_LoadsOfTypesNoPositionals.AwaitingKey -> () | ParseState_LoadsOfTypesNoPositionals.AwaitingValue key -> if setFlagValue key then () else sprintf "Trailing argument %s had no value. Use a double-dash to separate positional args from key-value args." key |> ArgParser_errors.Add | "--" :: rest -> parser_LeftoverArgs.AddRange (rest |> Seq.map (fun x -> x)) | arg :: args -> match state with | ParseState_LoadsOfTypesNoPositionals.AwaitingKey -> if arg.StartsWith ("--", System.StringComparison.Ordinal) then if arg = "--help" then helpText () |> failwithf "Help text requested.\n%s" else let equals = arg.IndexOf (char 61) if equals < 0 then args |> go (ParseState_LoadsOfTypesNoPositionals.AwaitingValue arg) else let key = arg.[0 .. equals - 1] let value = arg.[equals + 1 ..] match processKeyValue key value with | Ok () -> go ParseState_LoadsOfTypesNoPositionals.AwaitingKey args | Error None -> failwithf "Unable to process argument %s as key %s and value %s" arg key value | Error (Some msg) -> sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add go ParseState_LoadsOfTypesNoPositionals.AwaitingKey args else arg |> (fun x -> x) |> parser_LeftoverArgs.Add go ParseState_LoadsOfTypesNoPositionals.AwaitingKey args | ParseState_LoadsOfTypesNoPositionals.AwaitingValue key -> match processKeyValue key arg with | Ok () -> go ParseState_LoadsOfTypesNoPositionals.AwaitingKey args | Error exc -> if setFlagValue key then go ParseState_LoadsOfTypesNoPositionals.AwaitingKey (arg :: args) else match exc with | None -> failwithf "Unable to process supplied arg %s. Help text follows.\n%s" key (helpText ()) | Some msg -> msg |> ArgParser_errors.Add go ParseState_LoadsOfTypesNoPositionals.AwaitingKey args let parser_LeftoverArgs = if 0 = parser_LeftoverArgs.Count then () else parser_LeftoverArgs |> String.concat " " |> sprintf "There were leftover args: %s" |> ArgParser_errors.Add Unchecked.defaultof<_> let Foo = match Foo with | None -> sprintf "Required argument '%s' received no value" "--foo" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let Bar = match Bar with | None -> sprintf "Required argument '%s' received no value" "--bar" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let Baz = match Baz with | None -> sprintf "Required argument '%s' received no value" "--baz" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let SomeFile = match SomeFile with | None -> sprintf "Required argument '%s' received no value" "--some-file" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let SomeDirectory = match SomeDirectory with | None -> sprintf "Required argument '%s' received no value" "--some-directory" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let SomeList = SomeList |> Seq.toList let OptionalThingWithNoDefault = OptionalThingWithNoDefault let OptionalThing = match OptionalThing with | None -> LoadsOfTypesNoPositionals.DefaultOptionalThing () |> Choice2Of2 | Some x -> Choice1Of2 x let AnotherOptionalThing = match AnotherOptionalThing with | None -> LoadsOfTypesNoPositionals.DefaultAnotherOptionalThing () |> Choice2Of2 | Some x -> Choice1Of2 x let YetAnotherOptionalThing = match YetAnotherOptionalThing with | None -> match "CONSUMEPLUGIN_THINGS" |> getEnvironmentVariable with | null -> sprintf "No value was supplied for %s, nor was environment variable %s set" "--yet-another-optional-thing" "CONSUMEPLUGIN_THINGS" |> ArgParser_errors.Add Unchecked.defaultof<_> | x -> x |> (fun x -> x) |> Choice2Of2 | Some x -> Choice1Of2 x if 0 = ArgParser_errors.Count then { Foo = Foo Bar = Bar Baz = Baz SomeFile = SomeFile SomeDirectory = SomeDirectory SomeList = SomeList OptionalThingWithNoDefault = OptionalThingWithNoDefault OptionalThing = OptionalThing AnotherOptionalThing = AnotherOptionalThing YetAnotherOptionalThing = YetAnotherOptionalThing } else ArgParser_errors |> String.concat "\n" |> failwithf "Errors during parse!\n%s" let parse (args : string list) : LoadsOfTypesNoPositionals = parse' System.Environment.GetEnvironmentVariable args namespace ConsumePlugin open System open System.IO open WoofWare.Myriad.Plugins /// Methods to parse arguments for the type DatesAndTimes [] module DatesAndTimesArgParse = type private ParseState_DatesAndTimes = | AwaitingKey | AwaitingValue of key : string /// Extension methods for argument parsing type DatesAndTimes with static member parse' (getEnvironmentVariable : string -> string) (args : string list) : DatesAndTimes = let ArgParser_errors = ResizeArray () let helpText () = [ (sprintf "--plain TimeSpan%s%s" "" "") (sprintf "--invariant TimeSpan%s%s" "" "") (sprintf "--exact TimeSpan%s%s" "" (sprintf " : %s" (sprintf "%s [Parse format (.NET): %s]" "An exact time please" @"hh\:mm\:ss"))) (sprintf "--invariant-exact TimeSpan%s%s" "" (sprintf " : %s" (sprintf "[Parse format (.NET): %s]" @"hh\:mm\:ss"))) ] |> String.concat "\n" let parser_LeftoverArgs : string ResizeArray = ResizeArray () let mutable Plain : TimeSpan option = None let mutable Invariant : TimeSpan option = None let mutable Exact : TimeSpan option = None let mutable InvariantExact : TimeSpan option = None /// Processes the key-value pair, returning Error if no key was matched. /// If the key is an arg which can arity 1, but throws when consuming that arg, we return Error(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. let processKeyValue (key : string) (value : string) : Result = if System.String.Equals (key, "--invariant-exact", System.StringComparison.OrdinalIgnoreCase) then match InvariantExact with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--invariant-exact" x value |> ArgParser_errors.Add Ok () | None -> try InvariantExact <- value |> (fun x -> System.TimeSpan.ParseExact ( x, @"hh\:mm\:ss", System.Globalization.CultureInfo.InvariantCulture ) ) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--exact", System.StringComparison.OrdinalIgnoreCase) then match Exact with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--exact" x value |> ArgParser_errors.Add Ok () | None -> try Exact <- value |> (fun x -> System.TimeSpan.ParseExact ( x, @"hh\:mm\:ss", System.Globalization.CultureInfo.CurrentCulture ) ) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--invariant", System.StringComparison.OrdinalIgnoreCase) then match Invariant with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--invariant" x value |> ArgParser_errors.Add Ok () | None -> try Invariant <- value |> (fun x -> System.TimeSpan.Parse (x, System.Globalization.CultureInfo.InvariantCulture) ) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else if System.String.Equals (key, "--plain", System.StringComparison.OrdinalIgnoreCase) then match Plain with | Some x -> sprintf "Argument '%s' was supplied multiple times: %O and %O" "--plain" x value |> ArgParser_errors.Add Ok () | None -> try Plain <- value |> (fun x -> System.TimeSpan.Parse x) |> Some Ok () with _ as exc -> exc.Message |> Some |> Error else Error None /// Returns false if we didn't set a value. let setFlagValue (key : string) : bool = false let rec go (state : ParseState_DatesAndTimes) (args : string list) = match args with | [] -> match state with | ParseState_DatesAndTimes.AwaitingKey -> () | ParseState_DatesAndTimes.AwaitingValue key -> if setFlagValue key then () else sprintf "Trailing argument %s had no value. Use a double-dash to separate positional args from key-value args." key |> ArgParser_errors.Add | "--" :: rest -> parser_LeftoverArgs.AddRange (rest |> Seq.map (fun x -> x)) | arg :: args -> match state with | ParseState_DatesAndTimes.AwaitingKey -> if arg.StartsWith ("--", System.StringComparison.Ordinal) then if arg = "--help" then helpText () |> failwithf "Help text requested.\n%s" else let equals = arg.IndexOf (char 61) if equals < 0 then args |> go (ParseState_DatesAndTimes.AwaitingValue arg) else let key = arg.[0 .. equals - 1] let value = arg.[equals + 1 ..] match processKeyValue key value with | Ok () -> go ParseState_DatesAndTimes.AwaitingKey args | Error None -> failwithf "Unable to process argument %s as key %s and value %s" arg key value | Error (Some msg) -> sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add go ParseState_DatesAndTimes.AwaitingKey args else arg |> (fun x -> x) |> parser_LeftoverArgs.Add go ParseState_DatesAndTimes.AwaitingKey args | ParseState_DatesAndTimes.AwaitingValue key -> match processKeyValue key arg with | Ok () -> go ParseState_DatesAndTimes.AwaitingKey args | Error exc -> if setFlagValue key then go ParseState_DatesAndTimes.AwaitingKey (arg :: args) else match exc with | None -> failwithf "Unable to process supplied arg %s. Help text follows.\n%s" key (helpText ()) | Some msg -> msg |> ArgParser_errors.Add go ParseState_DatesAndTimes.AwaitingKey args let parser_LeftoverArgs = if 0 = parser_LeftoverArgs.Count then () else parser_LeftoverArgs |> String.concat " " |> sprintf "There were leftover args: %s" |> ArgParser_errors.Add Unchecked.defaultof<_> let Plain = match Plain with | None -> sprintf "Required argument '%s' received no value" "--plain" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let Invariant = match Invariant with | None -> sprintf "Required argument '%s' received no value" "--invariant" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let Exact = match Exact with | None -> sprintf "Required argument '%s' received no value" "--exact" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x let InvariantExact = match InvariantExact with | None -> sprintf "Required argument '%s' received no value" "--invariant-exact" |> ArgParser_errors.Add Unchecked.defaultof<_> | Some x -> x if 0 = ArgParser_errors.Count then { Plain = Plain Invariant = Invariant Exact = Exact InvariantExact = InvariantExact } else ArgParser_errors |> String.concat "\n" |> failwithf "Errors during parse!\n%s" static member parse (args : string list) : DatesAndTimes = DatesAndTimes.parse' System.Environment.GetEnvironmentVariable args