mirror of
https://github.com/Smaug123/WoofWare.Myriad
synced 2025-10-10 14:38:39 +00:00
1580 lines
67 KiB
Forth
1580 lines
67 KiB
Forth
//------------------------------------------------------------------------------
|
|
// 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
|
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
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(<the message>).
|
|
/// This can nevertheless be a successful parse, e.g. when the key may have arity 0.
|
|
let processKeyValue (key : string) (value : string) : Result<unit, string option> =
|
|
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
|
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
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(<the message>).
|
|
/// This can nevertheless be a successful parse, e.g. when the key may have arity 0.
|
|
let processKeyValue (key : string) (value : string) : Result<unit, string option> =
|
|
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
|
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
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(<the message>).
|
|
/// This can nevertheless be a successful parse, e.g. when the key may have arity 0.
|
|
let processKeyValue (key : string) (value : string) : Result<unit, string option> =
|
|
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
|
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
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(<the message>).
|
|
/// This can nevertheless be a successful parse, e.g. when the key may have arity 0.
|
|
let processKeyValue (key : string) (value : string) : Result<unit, string option> =
|
|
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
|
|
[<RequireQualifiedAccess ; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
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(<the message>).
|
|
/// This can nevertheless be a successful parse, e.g. when the key may have arity 0.
|
|
let processKeyValue (key : string) (value : string) : Result<unit, string option> =
|
|
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
|
|
[<AutoOpen>]
|
|
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(<the message>).
|
|
/// This can nevertheless be a successful parse, e.g. when the key may have arity 0.
|
|
let processKeyValue (key : string) (value : string) : Result<unit, string option> =
|
|
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
|