From aa2ef830c326f57af100d2ea4902cf3e23396da6 Mon Sep 17 00:00:00 2001 From: Smaug123 <3138005+Smaug123@users.noreply.github.com> Date: Wed, 16 Apr 2025 21:26:30 +0100 Subject: [PATCH] Add flags --- ConsumePlugin/GeneratedArgs.fs | 364 +++++++++++++++++++--- WoofWare.Myriad.Plugins/ShibaGenerator.fs | 108 ++++++- 2 files changed, 420 insertions(+), 52 deletions(-) diff --git a/ConsumePlugin/GeneratedArgs.fs b/ConsumePlugin/GeneratedArgs.fs index cb7d60c..24122bd 100644 --- a/ConsumePlugin/GeneratedArgs.fs +++ b/ConsumePlugin/GeneratedArgs.fs @@ -27,7 +27,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -88,7 +88,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -151,6 +151,21 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = + if System.String.Equals (key, sprintf "--%s" "baz", System.StringComparison.OrdinalIgnoreCase) then + match this.Baz with + | Some x -> + sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s" "baz") + |> errors_.Add + + true + | None -> + this.Baz <- true |> Some + true + else + false + /// A partially-parsed Basic. type internal Basic_InProgress = { @@ -161,7 +176,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -229,7 +244,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -292,6 +307,21 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = + if System.String.Equals (key, sprintf "--%s" "baz", System.StringComparison.OrdinalIgnoreCase) then + match this.Baz with + | Some x -> + sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s" "baz") + |> errors_.Add + + true + | None -> + this.Baz <- true |> Some + true + else + false + /// A partially-parsed BasicWithIntPositionals. type internal BasicWithIntPositionals_InProgress = { @@ -302,7 +332,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -370,7 +400,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -433,6 +463,21 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = + if System.String.Equals (key, sprintf "--%s" "baz", System.StringComparison.OrdinalIgnoreCase) then + match this.Baz with + | Some x -> + sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s" "baz") + |> errors_.Add + + true + | None -> + this.Baz <- true |> Some + true + else + false + /// A partially-parsed LoadsOfTypes. type internal LoadsOfTypes_InProgress = { @@ -450,7 +495,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -564,7 +609,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -760,6 +805,33 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = + if + System.String.Equals (key, sprintf "--%s" "optional-thing", System.StringComparison.OrdinalIgnoreCase) + then + match this.OptionalThing with + | Some x -> + sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s" "optional-thing") + |> errors_.Add + + true + | None -> + this.OptionalThing <- true |> Some + true + else if System.String.Equals (key, sprintf "--%s" "baz", System.StringComparison.OrdinalIgnoreCase) then + match this.Baz with + | Some x -> + sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s" "baz") + |> errors_.Add + + true + | None -> + this.Baz <- true |> Some + true + else + false + /// A partially-parsed LoadsOfTypesNoPositionals. type internal LoadsOfTypesNoPositionals_InProgress = { @@ -776,7 +848,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -879,7 +951,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -1070,6 +1142,33 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = + if + System.String.Equals (key, sprintf "--%s" "optional-thing", System.StringComparison.OrdinalIgnoreCase) + then + match this.OptionalThing with + | Some x -> + sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s" "optional-thing") + |> errors_.Add + + true + | None -> + this.OptionalThing <- true |> Some + true + else if System.String.Equals (key, sprintf "--%s" "baz", System.StringComparison.OrdinalIgnoreCase) then + match this.Baz with + | Some x -> + sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s" "baz") + |> errors_.Add + + true + | None -> + this.Baz <- true |> Some + true + else + false + /// A partially-parsed DatesAndTimes. type internal DatesAndTimes_InProgress = { @@ -1080,7 +1179,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -1146,7 +1245,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -1251,6 +1350,9 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = false + /// A partially-parsed ChildRecord. type internal ChildRecord_InProgress = { @@ -1259,7 +1361,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -1307,7 +1409,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -1350,6 +1452,9 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = false + /// A partially-parsed ParentRecord. type internal ParentRecord_InProgress = { @@ -1358,7 +1463,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -1367,7 +1472,7 @@ module internal ArgParseHelpers_ConsumePlugin = let positionalConsumers = ResizeArray () let arg0 : ChildRecord = - match this.Child.Assemble getEnvironmentVariable positionals with + match this.Child.Assemble_ getEnvironmentVariable positionals with | Ok (result, consumedPositional) -> match consumedPositional with | None -> () @@ -1411,7 +1516,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -1437,6 +1542,21 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = + if System.String.Equals (key, sprintf "--%s" "and-another", System.StringComparison.OrdinalIgnoreCase) then + match this.AndAnother with + | Some x -> + sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s" "and-another") + |> errors_.Add + + true + | None -> + this.AndAnother <- true |> Some + true + else + false + /// A partially-parsed ChildRecordWithPositional. type internal ChildRecordWithPositional_InProgress = { @@ -1445,7 +1565,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -1495,7 +1615,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -1524,6 +1644,9 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = false + /// A partially-parsed ParentRecordChildPos. type internal ParentRecordChildPos_InProgress = { @@ -1532,7 +1655,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -1541,7 +1664,7 @@ module internal ArgParseHelpers_ConsumePlugin = let positionalConsumers = ResizeArray () let arg0 : ChildRecordWithPositional = - match this.Child.Assemble getEnvironmentVariable positionals with + match this.Child.Assemble_ getEnvironmentVariable positionals with | Ok (result, consumedPositional) -> match consumedPositional with | None -> () @@ -1585,7 +1708,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -1611,6 +1734,21 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = + if System.String.Equals (key, sprintf "--%s" "and-another", System.StringComparison.OrdinalIgnoreCase) then + match this.AndAnother with + | Some x -> + sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s" "and-another") + |> errors_.Add + + true + | None -> + this.AndAnother <- true |> Some + true + else + false + /// A partially-parsed ParentRecordSelfPos. type internal ParentRecordSelfPos_InProgress = { @@ -1619,7 +1757,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -1628,7 +1766,7 @@ module internal ArgParseHelpers_ConsumePlugin = let positionalConsumers = ResizeArray () let arg0 : ChildRecord = - match this.Child.Assemble getEnvironmentVariable positionals with + match this.Child.Assemble_ getEnvironmentVariable positionals with | Ok (result, consumedPositional) -> match consumedPositional with | None -> () @@ -1674,7 +1812,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -1686,6 +1824,9 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = false + /// A partially-parsed ChoicePositionals. type internal ChoicePositionals_InProgress = { @@ -1693,7 +1834,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -1733,7 +1874,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -1745,6 +1886,9 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = false + /// A partially-parsed ContainsBoolEnvVar. type internal ContainsBoolEnvVar_InProgress = { @@ -1752,7 +1896,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -1794,7 +1938,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -1820,6 +1964,21 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = + if System.String.Equals (key, sprintf "--%s" "bool-var", System.StringComparison.OrdinalIgnoreCase) then + match this.BoolVar with + | Some x -> + sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s" "bool-var") + |> errors_.Add + + true + | None -> + this.BoolVar <- true |> Some + true + else + false + /// A partially-parsed WithFlagDu. type internal WithFlagDu_InProgress = { @@ -1827,7 +1986,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -1866,7 +2025,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -1901,6 +2060,27 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = + if System.String.Equals (key, sprintf "--%s" "dry-run", System.StringComparison.OrdinalIgnoreCase) then + match this.DryRun with + | Some x -> + sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s" "dry-run") + |> errors_.Add + + true + | None -> + this.DryRun <- + if true = Consts.FALSE then + DryRunMode.Wet + else + DryRunMode.Dry + |> Some + + true + else + false + /// A partially-parsed ContainsFlagEnvVar. type internal ContainsFlagEnvVar_InProgress = { @@ -1908,7 +2088,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -1955,7 +2135,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -1990,6 +2170,27 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = + if System.String.Equals (key, sprintf "--%s" "dry-run", System.StringComparison.OrdinalIgnoreCase) then + match this.DryRun with + | Some x -> + sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s" "dry-run") + |> errors_.Add + + true + | None -> + this.DryRun <- + if true = Consts.FALSE then + DryRunMode.Wet + else + DryRunMode.Dry + |> Some + + true + else + false + /// A partially-parsed ContainsFlagDefaultValue. type internal ContainsFlagDefaultValue_InProgress = { @@ -1997,7 +2198,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -2034,7 +2235,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -2069,6 +2270,27 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = + if System.String.Equals (key, sprintf "--%s" "dry-run", System.StringComparison.OrdinalIgnoreCase) then + match this.DryRun with + | Some x -> + sprintf "Flag '%s' was supplied multiple times" (sprintf "--%s" "dry-run") + |> errors_.Add + + true + | None -> + this.DryRun <- + if true = Consts.FALSE then + DryRunMode.Wet + else + DryRunMode.Dry + |> Some + + true + else + false + /// A partially-parsed ManyLongForms. type internal ManyLongForms_InProgress = { @@ -2077,7 +2299,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -2125,7 +2347,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -2214,6 +2436,39 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = + if + System.String.Equals (key, sprintf "--%s" "dont-turn-it-off", System.StringComparison.OrdinalIgnoreCase) + then + match this.SomeFlag with + | Some x -> + sprintf + "Flag '%s' was supplied multiple times" + (sprintf "--%s / --%s" "turn-it-on" "dont-turn-it-off") + |> errors_.Add + + true + | None -> + this.SomeFlag <- true |> Some + true + else if + System.String.Equals (key, sprintf "--%s" "turn-it-on", System.StringComparison.OrdinalIgnoreCase) + then + match this.SomeFlag with + | Some x -> + sprintf + "Flag '%s' was supplied multiple times" + (sprintf "--%s / --%s" "turn-it-on" "dont-turn-it-off") + |> errors_.Add + + true + | None -> + this.SomeFlag <- true |> Some + true + else + false + /// A partially-parsed FlagsIntoPositionalArgs. type internal FlagsIntoPositionalArgs_InProgress = { @@ -2222,7 +2477,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -2272,7 +2527,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -2303,6 +2558,9 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = false + /// A partially-parsed FlagsIntoPositionalArgsChoice. type internal FlagsIntoPositionalArgsChoice_InProgress = { @@ -2311,7 +2569,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -2360,7 +2618,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -2391,6 +2649,9 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = false + /// A partially-parsed FlagsIntoPositionalArgsInt. type internal FlagsIntoPositionalArgsInt_InProgress = { @@ -2399,7 +2660,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -2449,7 +2710,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -2480,6 +2741,9 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = false + /// A partially-parsed FlagsIntoPositionalArgsIntChoice. type internal FlagsIntoPositionalArgsIntChoice_InProgress = { @@ -2488,7 +2752,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -2537,7 +2801,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -2568,6 +2832,9 @@ module internal ArgParseHelpers_ConsumePlugin = else Error None + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = false + /// A partially-parsed FlagsIntoPositionalArgs'. type internal FlagsIntoPositionalArgs'_InProgress = { @@ -2576,7 +2843,7 @@ module internal ArgParseHelpers_ConsumePlugin = } /// Freeze this in-progress type. On success, returns the frozen type and the arg (if any) which consumed the input positional args. - member this.Assemble + member this.Assemble_ (getEnvironmentVariable : string -> string) (positionals : Choice list) : Result @@ -2626,7 +2893,7 @@ module internal ArgParseHelpers_ConsumePlugin = /// 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(). /// This can nevertheless be a successful parse, e.g. when the key may have arity 0. - member this.ProcessKeyValue + member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) @@ -2660,6 +2927,9 @@ module internal ArgParseHelpers_ConsumePlugin = exc.Message |> Some |> Error else Error None + + /// Returns false if we didn't set a value. + member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = false namespace ConsumePlugin open ArgParserHelpers diff --git a/WoofWare.Myriad.Plugins/ShibaGenerator.fs b/WoofWare.Myriad.Plugins/ShibaGenerator.fs index a2c5bca..0c15a12 100644 --- a/WoofWare.Myriad.Plugins/ShibaGenerator.fs +++ b/WoofWare.Myriad.Plugins/ShibaGenerator.fs @@ -517,6 +517,7 @@ module internal ShibaGenerator = LeafNodes : Map> Records : Map> Unions : Map> + FlagDus : FlagDu list } and internal ParsedUnionStructure<'choice> = @@ -525,7 +526,74 @@ module internal ShibaGenerator = Cases : Map> } - /// `member this.ProcessKeyValue (errors_ : ResizeArray) (key : string) (value : string) : Result = ...` + /// `member this.SetFlagValue_ (errors_ : ResizeArray) (key : string) : bool = ...` + /// The second member of the `flags` list tuple is the constant "true" with which we will interpret the + /// arity-0 `--foo`. So in the case of a boolean-typed field, this is `true`; in the case of a Flag-typed field, + /// this is `FlagType.WhicheverCaseHadTrue`. + let private setFlagValue (flags : (LeafData<'choice> * SynExpr) list) : SynBinding = + (SynExpr.CreateConst false, flags) + ||> List.fold (fun finalExpr (flag, trueCase) -> + let multipleErrorMessage = + SynExpr.createIdent "sprintf" + |> SynExpr.applyTo (SynExpr.CreateConst "Flag '%s' was supplied multiple times") + |> SynExpr.applyTo flag.HumanReadableArgForm + + let matchFlag = + [ + SynMatchClause.create + (SynPat.nameWithArgs "Some" [ SynPat.anon ]) + // This is an error, but it's one we can gracefully report at the end. + (SynExpr.sequential + [ + multipleErrorMessage + |> SynExpr.pipeThroughFunction (SynExpr.dotGet "Add" (SynExpr.createIdent "errors_")) + SynExpr.CreateConst true + ]) + + SynMatchClause.create + (SynPat.named "None") + ([ + SynExpr.assign + (SynLongIdent.create [ Ident.create "this" ; flag.TargetConstructionField ]) + (SynExpr.pipeThroughFunction (SynExpr.createIdent "Some") trueCase) + SynExpr.CreateConst true + ] + |> SynExpr.sequential) + ] + |> SynExpr.createMatch ( + SynExpr.createLongIdent' [ Ident.create "this" ; flag.TargetConstructionField ] + ) + + (finalExpr, flag.ArgForm) + ||> List.fold (fun finalExpr argForm -> + SynExpr.ifThenElse + (SynExpr.applyFunction + (SynExpr.createLongIdent [ "System" ; "String" ; "Equals" ]) + (SynExpr.tuple + [ + SynExpr.createIdent "key" + SynExpr.applyFunction + (SynExpr.applyFunction + (SynExpr.createIdent "sprintf") + (SynExpr.CreateConst "--%s")) + argForm + SynExpr.createLongIdent [ "System" ; "StringComparison" ; "OrdinalIgnoreCase" ] + ])) + finalExpr + matchFlag + ) + ) + |> SynBinding.basic + [ Ident.create "this" ; Ident.create "SetFlagValue_" ] + [ + SynPat.annotateType (SynType.app "ResizeArray" [ SynType.string ]) (SynPat.named "errors_") + SynPat.annotateType SynType.string (SynPat.named "key") + ] + |> SynBinding.withReturnAnnotation (SynType.named "bool") + |> SynBinding.withXmlDoc (PreXmlDoc.create "Returns false if we didn't set a value.") + |> SynBinding.makeInstanceMember + + /// `member this.ProcessKeyValue_ (errors_ : ResizeArray) (key : string) (value : string) : Result = ...` /// Returns a possible error. /// A parse failure might not be fatal (e.g. maybe the input was optionally of arity 0, and we failed to do /// the parse because in fact the key decided not to take this argument); in that case we return Error None. @@ -632,7 +700,7 @@ module internal ShibaGenerator = ) ) |> SynBinding.basic - [ Ident.create "this" ; Ident.create "ProcessKeyValue" ] + [ Ident.create "this" ; Ident.create "ProcessKeyValue_" ] [ SynPat.annotateType (SynType.app "ResizeArray" [ SynType.string ]) (SynPat.named "errors_") SynPat.annotateType SynType.string (SynPat.named "key") @@ -649,6 +717,7 @@ module internal ShibaGenerator = ] |> PreXmlDoc.create' ) + |> SynBinding.makeInstanceMember /// Build the "in-progress record" which is basically "the input record, but with all fields mutable and optional". let private inProgressRecordType (record : ParsedRecordStructure) : RecordType = @@ -751,7 +820,7 @@ module internal ShibaGenerator = // This was a record; defer to its parser. let subAssembleCall = SynExpr.dotGet ident.idText (SynExpr.createIdent "this") - |> SynExpr.callMethodArg "Assemble" (SynExpr.createIdent "getEnvironmentVariable") + |> SynExpr.callMethodArg "Assemble_" (SynExpr.createIdent "getEnvironmentVariable") |> SynExpr.applyTo (SynExpr.createIdent "positionals") // TODO: need to know if it has positionals @@ -983,7 +1052,7 @@ module internal ShibaGenerator = (SynExpr.CreateConst ())) ] |> SynBinding.basic - [ Ident.create "this" ; Ident.create "Assemble" ] + [ Ident.create "this" ; Ident.create "Assemble_" ] [ SynPat.annotateType (SynType.funFromDomain SynType.string SynType.string) @@ -1044,10 +1113,38 @@ module internal ShibaGenerator = |> processKeyValue |> SynMemberDefn.memberImplementation + let flags = + record.LeafNodes + |> Map.toSeq + |> Seq.choose (fun (_, pf) -> + match pf.Acc with + | Required + | Optional + | Accumulation.Choice _ -> Some pf + // We don't allow flags to be passed multiple times and accumulated into a list. + | Accumulation.List _ + | Accumulation.ChoicePositional _ -> None + ) + |> Seq.choose (fun pf -> + match pf.TypeAfterParse with + | PrimitiveType pt -> + if (pt |> List.map _.idText) = [ "System" ; "Boolean" ] then + Some (pf, SynExpr.CreateConst true) + else + None + | ty -> + match identifyAsFlag record.FlagDus ty with + | Some flag -> (pf, FlagDu.FromBoolean flag (SynExpr.CreateConst true)) |> Some + | _ -> None + ) + |> Seq.toList + + let setFlagValue = setFlagValue flags |> SynMemberDefn.memberImplementation + { Name = record.NameOfInProgressType Fields = fields - Members = [ assembleMethod ; emptyConstructor ; processKeyValue ] |> Some + Members = [ assembleMethod ; emptyConstructor ; processKeyValue ; setFlagValue ] |> Some XmlDoc = PreXmlDoc.create $"A partially-parsed %s{record.Original.Name.idText}." |> Some Generics = match record.Original.Generics with @@ -1132,6 +1229,7 @@ module internal ShibaGenerator = LeafNodes = leaf |> Map.ofList Records = records |> Map.ofList Unions = unions |> Map.ofList + FlagDus = flagDus } |> Some