Files
WoofWare.Myriad/ConsumePlugin/GeneratedArgParserNegationTests.fs
Patrick Stevens 67e051b6b3 Add --no- prefix for bools (#455)
Implements support for --no- prefix negation on boolean and flag DU fields
when marked with [<ArgumentNegateWithPrefix>]. This allows both --flag and
--no-flag forms to be accepted, with --no- variants negating the value.

Changes:
- Extend ArgParserGenerator to generate --no- prefix handling
- Add conflict detection for overlapping --no- prefixed arguments
- Update help text to display both forms (e.g., --verbose / --no-verbose)
- Add test examples in ArgParserNegationTests.fs demonstrating:
  - Boolean field negation
  - Flag DU negation
  - Multiple ArgumentLongForm with negation
  - Combined features (defaults, help text)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 07:53:15 +00:00

1030 lines
46 KiB
Forth

//------------------------------------------------------------------------------
// This code was generated by myriad.
// Changes to this file will be lost when the code is regenerated.
//------------------------------------------------------------------------------
namespace ConsumePlugin
open WoofWare.Myriad.Plugins
/// Methods to parse arguments for the type BoolNegation
[<AutoOpen>]
module BoolNegationArgParse =
type private ParseState_BoolNegation =
/// Ready to consume a key or positional arg
| AwaitingKey
/// Waiting to receive a value for the key we've already consumed
| AwaitingValue of key : string
/// Extension methods for argument parsing
type BoolNegation with
static member parse' (getEnvironmentVariable : string -> string option) (args : string list) : BoolNegation =
let ArgParser_errors = ResizeArray ()
let helpText () =
[
(sprintf "%s bool%s%s" (sprintf "--%s / --no-%s" "enable-feature" "enable-feature") "" "")
]
|> String.concat "\n"
let parser_LeftoverArgs : string ResizeArray = ResizeArray ()
let mutable arg_0 : bool option = None
/// Processes the key-value pair, returning Error if no key was matched.
/// If the key is an arg which can have 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,
sprintf "--no-%s" "enable-feature",
System.StringComparison.OrdinalIgnoreCase
)
then
match arg_0 with
| Some x ->
sprintf
"Argument '%s' was supplied multiple times: %s and %s"
(sprintf "--%s / --no-%s" "enable-feature" "enable-feature")
(x.ToString ())
(value.ToString ())
|> ArgParser_errors.Add
Ok ()
| None ->
try
arg_0 <- value |> (fun x -> not (System.Boolean.Parse x)) |> Some
Ok ()
with _ as exc ->
exc.Message |> Some |> Error
else if
System.String.Equals (
key,
sprintf "--%s" "enable-feature",
System.StringComparison.OrdinalIgnoreCase
)
then
match arg_0 with
| Some x ->
sprintf
"Argument '%s' was supplied multiple times: %s and %s"
(sprintf "--%s / --no-%s" "enable-feature" "enable-feature")
(x.ToString ())
(value.ToString ())
|> ArgParser_errors.Add
Ok ()
| None ->
try
arg_0 <- value |> (fun x -> System.Boolean.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,
sprintf "--no-%s" "enable-feature",
System.StringComparison.OrdinalIgnoreCase
)
then
match arg_0 with
| Some x ->
sprintf
"Flag '%s' was supplied multiple times"
(sprintf "--%s / --no-%s" "enable-feature" "enable-feature")
|> ArgParser_errors.Add
true
| None ->
arg_0 <- false |> Some
true
else if
System.String.Equals (
key,
sprintf "--%s" "enable-feature",
System.StringComparison.OrdinalIgnoreCase
)
then
match arg_0 with
| Some x ->
sprintf
"Flag '%s' was supplied multiple times"
(sprintf "--%s / --no-%s" "enable-feature" "enable-feature")
|> ArgParser_errors.Add
true
| None ->
arg_0 <- true |> Some
true
else
false
let rec go (state : ParseState_BoolNegation) (args : string list) =
match args with
| [] ->
match state with
| ParseState_BoolNegation.AwaitingKey -> ()
| ParseState_BoolNegation.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_BoolNegation.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_BoolNegation.AwaitingValue arg)
else
let key = arg.[0 .. equals - 1]
let value = arg.[equals + 1 ..]
match processKeyValue key value with
| Ok () -> go ParseState_BoolNegation.AwaitingKey args
| Error x ->
match x with
| None ->
failwithf
"Unable to process argument %s as key %s and value %s"
arg
key
value
| Some msg ->
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
go ParseState_BoolNegation.AwaitingKey args
else
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
go ParseState_BoolNegation.AwaitingKey args
| ParseState_BoolNegation.AwaitingValue key ->
match processKeyValue key arg with
| Ok () -> go ParseState_BoolNegation.AwaitingKey args
| Error exc ->
if setFlagValue key then
go ParseState_BoolNegation.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_BoolNegation.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 arg_0 =
match arg_0 with
| None ->
sprintf
"Required argument '%s' received no value"
(sprintf "--%s / --no-%s" "enable-feature" "enable-feature")
|> ArgParser_errors.Add
Unchecked.defaultof<_>
| Some x -> x
if 0 = ArgParser_errors.Count then
{
EnableFeature = arg_0
}
else
ArgParser_errors |> String.concat "\n" |> failwithf "Errors during parse!\n%s"
static member parse (args : string list) : BoolNegation =
BoolNegation.parse' (System.Environment.GetEnvironmentVariable >> Option.ofObj) args
namespace ConsumePlugin
open WoofWare.Myriad.Plugins
/// Methods to parse arguments for the type FlagNegation
[<AutoOpen>]
module FlagNegationArgParse =
type private ParseState_FlagNegation =
/// Ready to consume a key or positional arg
| AwaitingKey
/// Waiting to receive a value for the key we've already consumed
| AwaitingValue of key : string
/// Extension methods for argument parsing
type FlagNegation with
static member parse' (getEnvironmentVariable : string -> string option) (args : string list) : FlagNegation =
let ArgParser_errors = ResizeArray ()
let helpText () =
[
(sprintf "%s bool%s%s" (sprintf "--%s / --no-%s" "dry-run" "dry-run") "" "")
]
|> String.concat "\n"
let parser_LeftoverArgs : string ResizeArray = ResizeArray ()
let mutable arg_0 : TestDryRunMode option = None
/// Processes the key-value pair, returning Error if no key was matched.
/// If the key is an arg which can have 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, sprintf "--no-%s" "dry-run", System.StringComparison.OrdinalIgnoreCase)
then
match arg_0 with
| Some x ->
sprintf
"Argument '%s' was supplied multiple times: %s and %s"
(sprintf "--%s / --no-%s" "dry-run" "dry-run")
(x.ToString ())
(value.ToString ())
|> ArgParser_errors.Add
Ok ()
| None ->
try
arg_0 <-
value
|> (fun x ->
if not (System.Boolean.Parse x) = false then
TestDryRunMode.Wet
else
TestDryRunMode.Dry
)
|> Some
Ok ()
with _ as exc ->
exc.Message |> Some |> Error
else if
System.String.Equals (key, sprintf "--%s" "dry-run", System.StringComparison.OrdinalIgnoreCase)
then
match arg_0 with
| Some x ->
sprintf
"Argument '%s' was supplied multiple times: %s and %s"
(sprintf "--%s / --no-%s" "dry-run" "dry-run")
(x.ToString ())
(value.ToString ())
|> ArgParser_errors.Add
Ok ()
| None ->
try
arg_0 <-
value
|> (fun x ->
if System.Boolean.Parse x = false then
TestDryRunMode.Wet
else
TestDryRunMode.Dry
)
|> 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, sprintf "--no-%s" "dry-run", System.StringComparison.OrdinalIgnoreCase)
then
match arg_0 with
| Some x ->
sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s / --no-%s" "dry-run" "dry-run")
|> ArgParser_errors.Add
true
| None ->
arg_0 <- TestDryRunMode.Wet |> Some
true
else if
System.String.Equals (key, sprintf "--%s" "dry-run", System.StringComparison.OrdinalIgnoreCase)
then
match arg_0 with
| Some x ->
sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s / --no-%s" "dry-run" "dry-run")
|> ArgParser_errors.Add
true
| None ->
arg_0 <-
if true = false then
TestDryRunMode.Wet
else
TestDryRunMode.Dry
|> Some
true
else
false
let rec go (state : ParseState_FlagNegation) (args : string list) =
match args with
| [] ->
match state with
| ParseState_FlagNegation.AwaitingKey -> ()
| ParseState_FlagNegation.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_FlagNegation.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_FlagNegation.AwaitingValue arg)
else
let key = arg.[0 .. equals - 1]
let value = arg.[equals + 1 ..]
match processKeyValue key value with
| Ok () -> go ParseState_FlagNegation.AwaitingKey args
| Error x ->
match x with
| None ->
failwithf
"Unable to process argument %s as key %s and value %s"
arg
key
value
| Some msg ->
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
go ParseState_FlagNegation.AwaitingKey args
else
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
go ParseState_FlagNegation.AwaitingKey args
| ParseState_FlagNegation.AwaitingValue key ->
match processKeyValue key arg with
| Ok () -> go ParseState_FlagNegation.AwaitingKey args
| Error exc ->
if setFlagValue key then
go ParseState_FlagNegation.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_FlagNegation.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 arg_0 =
match arg_0 with
| None ->
sprintf "Required argument '%s' received no value" (sprintf "--%s / --no-%s" "dry-run" "dry-run")
|> ArgParser_errors.Add
Unchecked.defaultof<_>
| Some x -> x
if 0 = ArgParser_errors.Count then
{
DryRun = arg_0
}
else
ArgParser_errors |> String.concat "\n" |> failwithf "Errors during parse!\n%s"
static member parse (args : string list) : FlagNegation =
FlagNegation.parse' (System.Environment.GetEnvironmentVariable >> Option.ofObj) args
namespace ConsumePlugin
open WoofWare.Myriad.Plugins
/// Methods to parse arguments for the type MultipleFormsNegation
[<AutoOpen>]
module MultipleFormsNegationArgParse =
type private ParseState_MultipleFormsNegation =
/// Ready to consume a key or positional arg
| AwaitingKey
/// Waiting to receive a value for the key we've already consumed
| AwaitingValue of key : string
/// Extension methods for argument parsing
type MultipleFormsNegation with
static member parse'
(getEnvironmentVariable : string -> string option)
(args : string list)
: MultipleFormsNegation
=
let ArgParser_errors = ResizeArray ()
let helpText () =
[
(sprintf
"%s bool%s%s"
(sprintf "--%s / --%s / --no-%s / --no-%s" "verbose" "v" "verbose" "v")
""
"")
]
|> String.concat "\n"
let parser_LeftoverArgs : string ResizeArray = ResizeArray ()
let mutable arg_0 : bool option = None
/// Processes the key-value pair, returning Error if no key was matched.
/// If the key is an arg which can have 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, sprintf "--no-%s" "v", System.StringComparison.OrdinalIgnoreCase) then
match arg_0 with
| Some x ->
sprintf
"Argument '%s' was supplied multiple times: %s and %s"
(sprintf "--%s / --%s / --no-%s / --no-%s" "verbose" "v" "verbose" "v")
(x.ToString ())
(value.ToString ())
|> ArgParser_errors.Add
Ok ()
| None ->
try
arg_0 <- value |> (fun x -> not (System.Boolean.Parse x)) |> Some
Ok ()
with _ as exc ->
exc.Message |> Some |> Error
else if System.String.Equals (key, sprintf "--%s" "v", System.StringComparison.OrdinalIgnoreCase) then
match arg_0 with
| Some x ->
sprintf
"Argument '%s' was supplied multiple times: %s and %s"
(sprintf "--%s / --%s / --no-%s / --no-%s" "verbose" "v" "verbose" "v")
(x.ToString ())
(value.ToString ())
|> ArgParser_errors.Add
Ok ()
| None ->
try
arg_0 <- value |> (fun x -> System.Boolean.Parse x) |> Some
Ok ()
with _ as exc ->
exc.Message |> Some |> Error
else if
System.String.Equals (key, sprintf "--no-%s" "verbose", System.StringComparison.OrdinalIgnoreCase)
then
match arg_0 with
| Some x ->
sprintf
"Argument '%s' was supplied multiple times: %s and %s"
(sprintf "--%s / --%s / --no-%s / --no-%s" "verbose" "v" "verbose" "v")
(x.ToString ())
(value.ToString ())
|> ArgParser_errors.Add
Ok ()
| None ->
try
arg_0 <- value |> (fun x -> not (System.Boolean.Parse x)) |> Some
Ok ()
with _ as exc ->
exc.Message |> Some |> Error
else if
System.String.Equals (key, sprintf "--%s" "verbose", System.StringComparison.OrdinalIgnoreCase)
then
match arg_0 with
| Some x ->
sprintf
"Argument '%s' was supplied multiple times: %s and %s"
(sprintf "--%s / --%s / --no-%s / --no-%s" "verbose" "v" "verbose" "v")
(x.ToString ())
(value.ToString ())
|> ArgParser_errors.Add
Ok ()
| None ->
try
arg_0 <- value |> (fun x -> System.Boolean.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, sprintf "--no-%s" "v", System.StringComparison.OrdinalIgnoreCase) then
match arg_0 with
| Some x ->
sprintf
"Flag '%s' was supplied multiple times"
(sprintf "--%s / --%s / --no-%s / --no-%s" "verbose" "v" "verbose" "v")
|> ArgParser_errors.Add
true
| None ->
arg_0 <- false |> Some
true
else if System.String.Equals (key, sprintf "--%s" "v", System.StringComparison.OrdinalIgnoreCase) then
match arg_0 with
| Some x ->
sprintf
"Flag '%s' was supplied multiple times"
(sprintf "--%s / --%s / --no-%s / --no-%s" "verbose" "v" "verbose" "v")
|> ArgParser_errors.Add
true
| None ->
arg_0 <- true |> Some
true
else if
System.String.Equals (key, sprintf "--no-%s" "verbose", System.StringComparison.OrdinalIgnoreCase)
then
match arg_0 with
| Some x ->
sprintf
"Flag '%s' was supplied multiple times"
(sprintf "--%s / --%s / --no-%s / --no-%s" "verbose" "v" "verbose" "v")
|> ArgParser_errors.Add
true
| None ->
arg_0 <- false |> Some
true
else if
System.String.Equals (key, sprintf "--%s" "verbose", System.StringComparison.OrdinalIgnoreCase)
then
match arg_0 with
| Some x ->
sprintf
"Flag '%s' was supplied multiple times"
(sprintf "--%s / --%s / --no-%s / --no-%s" "verbose" "v" "verbose" "v")
|> ArgParser_errors.Add
true
| None ->
arg_0 <- true |> Some
true
else
false
let rec go (state : ParseState_MultipleFormsNegation) (args : string list) =
match args with
| [] ->
match state with
| ParseState_MultipleFormsNegation.AwaitingKey -> ()
| ParseState_MultipleFormsNegation.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_MultipleFormsNegation.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_MultipleFormsNegation.AwaitingValue arg)
else
let key = arg.[0 .. equals - 1]
let value = arg.[equals + 1 ..]
match processKeyValue key value with
| Ok () -> go ParseState_MultipleFormsNegation.AwaitingKey args
| Error x ->
match x with
| None ->
failwithf
"Unable to process argument %s as key %s and value %s"
arg
key
value
| Some msg ->
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
go ParseState_MultipleFormsNegation.AwaitingKey args
else
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
go ParseState_MultipleFormsNegation.AwaitingKey args
| ParseState_MultipleFormsNegation.AwaitingValue key ->
match processKeyValue key arg with
| Ok () -> go ParseState_MultipleFormsNegation.AwaitingKey args
| Error exc ->
if setFlagValue key then
go ParseState_MultipleFormsNegation.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_MultipleFormsNegation.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 arg_0 =
match arg_0 with
| None ->
sprintf
"Required argument '%s' received no value"
(sprintf "--%s / --%s / --no-%s / --no-%s" "verbose" "v" "verbose" "v")
|> ArgParser_errors.Add
Unchecked.defaultof<_>
| Some x -> x
if 0 = ArgParser_errors.Count then
{
VerboseMode = arg_0
}
else
ArgParser_errors |> String.concat "\n" |> failwithf "Errors during parse!\n%s"
static member parse (args : string list) : MultipleFormsNegation =
MultipleFormsNegation.parse' (System.Environment.GetEnvironmentVariable >> Option.ofObj) args
namespace ConsumePlugin
open WoofWare.Myriad.Plugins
/// Methods to parse arguments for the type CombinedFeatures
[<AutoOpen>]
module CombinedFeaturesArgParse =
type private ParseState_CombinedFeatures =
/// Ready to consume a key or positional arg
| AwaitingKey
/// Waiting to receive a value for the key we've already consumed
| AwaitingValue of key : string
/// Extension methods for argument parsing
type CombinedFeatures with
static member parse'
(getEnvironmentVariable : string -> string option)
(args : string list)
: CombinedFeatures
=
let ArgParser_errors = ResizeArray ()
let helpText () =
[
(sprintf
"%s bool%s%s"
(sprintf "--%s / --no-%s" "verbose" "verbose")
(CombinedFeatures.DefaultVerbose ()
|> (fun x -> x.ToString ())
|> sprintf " (default value: %s)")
"")
(sprintf
"%s bool%s%s"
(sprintf "--%s / --no-%s" "debug" "debug")
""
(sprintf " : %s" ("Enable debug mode")))
(sprintf "%s bool%s%s" (sprintf "--%s" "normal-bool") "" "")
]
|> String.concat "\n"
let parser_LeftoverArgs : string ResizeArray = ResizeArray ()
let mutable arg_0 : bool option = None
let mutable arg_1 : bool option = None
let mutable arg_2 : bool option = None
/// Processes the key-value pair, returning Error if no key was matched.
/// If the key is an arg which can have 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, sprintf "--%s" "normal-bool", System.StringComparison.OrdinalIgnoreCase)
then
match arg_2 with
| Some x ->
sprintf
"Argument '%s' was supplied multiple times: %s and %s"
(sprintf "--%s" "normal-bool")
(x.ToString ())
(value.ToString ())
|> ArgParser_errors.Add
Ok ()
| None ->
try
arg_2 <- value |> (fun x -> System.Boolean.Parse x) |> Some
Ok ()
with _ as exc ->
exc.Message |> Some |> Error
else if
System.String.Equals (key, sprintf "--no-%s" "debug", System.StringComparison.OrdinalIgnoreCase)
then
match arg_1 with
| Some x ->
sprintf
"Argument '%s' was supplied multiple times: %s and %s"
(sprintf "--%s / --no-%s" "debug" "debug")
(x.ToString ())
(value.ToString ())
|> ArgParser_errors.Add
Ok ()
| None ->
try
arg_1 <- value |> (fun x -> not (System.Boolean.Parse x)) |> Some
Ok ()
with _ as exc ->
exc.Message |> Some |> Error
else if
System.String.Equals (key, sprintf "--%s" "debug", System.StringComparison.OrdinalIgnoreCase)
then
match arg_1 with
| Some x ->
sprintf
"Argument '%s' was supplied multiple times: %s and %s"
(sprintf "--%s / --no-%s" "debug" "debug")
(x.ToString ())
(value.ToString ())
|> ArgParser_errors.Add
Ok ()
| None ->
try
arg_1 <- value |> (fun x -> System.Boolean.Parse x) |> Some
Ok ()
with _ as exc ->
exc.Message |> Some |> Error
else if
System.String.Equals (key, sprintf "--no-%s" "verbose", System.StringComparison.OrdinalIgnoreCase)
then
match arg_0 with
| Some x ->
sprintf
"Argument '%s' was supplied multiple times: %s and %s"
(sprintf "--%s / --no-%s" "verbose" "verbose")
(x.ToString ())
(value.ToString ())
|> ArgParser_errors.Add
Ok ()
| None ->
try
arg_0 <- value |> (fun x -> not (System.Boolean.Parse x)) |> Some
Ok ()
with _ as exc ->
exc.Message |> Some |> Error
else if
System.String.Equals (key, sprintf "--%s" "verbose", System.StringComparison.OrdinalIgnoreCase)
then
match arg_0 with
| Some x ->
sprintf
"Argument '%s' was supplied multiple times: %s and %s"
(sprintf "--%s / --no-%s" "verbose" "verbose")
(x.ToString ())
(value.ToString ())
|> ArgParser_errors.Add
Ok ()
| None ->
try
arg_0 <- value |> (fun x -> System.Boolean.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, sprintf "--%s" "normal-bool", System.StringComparison.OrdinalIgnoreCase)
then
match arg_2 with
| Some x ->
sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s" "normal-bool")
|> ArgParser_errors.Add
true
| None ->
arg_2 <- true |> Some
true
else if
System.String.Equals (key, sprintf "--no-%s" "debug", System.StringComparison.OrdinalIgnoreCase)
then
match arg_1 with
| Some x ->
sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s / --no-%s" "debug" "debug")
|> ArgParser_errors.Add
true
| None ->
arg_1 <- false |> Some
true
else if
System.String.Equals (key, sprintf "--%s" "debug", System.StringComparison.OrdinalIgnoreCase)
then
match arg_1 with
| Some x ->
sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s / --no-%s" "debug" "debug")
|> ArgParser_errors.Add
true
| None ->
arg_1 <- true |> Some
true
else if
System.String.Equals (key, sprintf "--no-%s" "verbose", System.StringComparison.OrdinalIgnoreCase)
then
match arg_0 with
| Some x ->
sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s / --no-%s" "verbose" "verbose")
|> ArgParser_errors.Add
true
| None ->
arg_0 <- false |> Some
true
else if
System.String.Equals (key, sprintf "--%s" "verbose", System.StringComparison.OrdinalIgnoreCase)
then
match arg_0 with
| Some x ->
sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s / --no-%s" "verbose" "verbose")
|> ArgParser_errors.Add
true
| None ->
arg_0 <- true |> Some
true
else
false
let rec go (state : ParseState_CombinedFeatures) (args : string list) =
match args with
| [] ->
match state with
| ParseState_CombinedFeatures.AwaitingKey -> ()
| ParseState_CombinedFeatures.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_CombinedFeatures.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_CombinedFeatures.AwaitingValue arg)
else
let key = arg.[0 .. equals - 1]
let value = arg.[equals + 1 ..]
match processKeyValue key value with
| Ok () -> go ParseState_CombinedFeatures.AwaitingKey args
| Error x ->
match x with
| None ->
failwithf
"Unable to process argument %s as key %s and value %s"
arg
key
value
| Some msg ->
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
go ParseState_CombinedFeatures.AwaitingKey args
else
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
go ParseState_CombinedFeatures.AwaitingKey args
| ParseState_CombinedFeatures.AwaitingValue key ->
match processKeyValue key arg with
| Ok () -> go ParseState_CombinedFeatures.AwaitingKey args
| Error exc ->
if setFlagValue key then
go ParseState_CombinedFeatures.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_CombinedFeatures.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 arg_0 =
match arg_0 with
| None -> CombinedFeatures.DefaultVerbose () |> Choice2Of2
| Some x -> Choice1Of2 x
let arg_1 =
match arg_1 with
| None ->
sprintf "Required argument '%s' received no value" (sprintf "--%s / --no-%s" "debug" "debug")
|> ArgParser_errors.Add
Unchecked.defaultof<_>
| Some x -> x
let arg_2 =
match arg_2 with
| None ->
sprintf "Required argument '%s' received no value" (sprintf "--%s" "normal-bool")
|> ArgParser_errors.Add
Unchecked.defaultof<_>
| Some x -> x
if 0 = ArgParser_errors.Count then
{
Debug = arg_1
NormalBool = arg_2
Verbose = arg_0
}
else
ArgParser_errors |> String.concat "\n" |> failwithf "Errors during parse!\n%s"
static member parse (args : string list) : CombinedFeatures =
CombinedFeatures.parse' (System.Environment.GetEnvironmentVariable >> Option.ofObj) args