mirror of
https://github.com/Smaug123/WoofWare.Myriad
synced 2025-10-07 13:08:40 +00:00
Compare commits
2 Commits
WoofWare.M
...
WoofWare.M
Author | SHA1 | Date | |
---|---|---|---|
|
49ecfbf5e5 | ||
|
5748ac3d5b |
@@ -195,3 +195,19 @@ type ManyLongForms =
|
|||||||
type private IrrelevantDu =
|
type private IrrelevantDu =
|
||||||
| Foo
|
| Foo
|
||||||
| Bar
|
| Bar
|
||||||
|
|
||||||
|
[<ArgParser true>]
|
||||||
|
type FlagsIntoPositionalArgs =
|
||||||
|
{
|
||||||
|
A : string
|
||||||
|
[<PositionalArgs true>]
|
||||||
|
GrabEverything : string list
|
||||||
|
}
|
||||||
|
|
||||||
|
[<ArgParser true>]
|
||||||
|
type FlagsIntoPositionalArgs' =
|
||||||
|
{
|
||||||
|
A : string
|
||||||
|
[<PositionalArgs false>]
|
||||||
|
DontGrabEverything : string list
|
||||||
|
}
|
||||||
|
@@ -148,11 +148,13 @@ module BasicNoPositionals =
|
|||||||
|
|
||||||
match processKeyValue key value with
|
match processKeyValue key value with
|
||||||
| Ok () -> go ParseState_BasicNoPositionals.AwaitingKey args
|
| Ok () -> go ParseState_BasicNoPositionals.AwaitingKey args
|
||||||
| Error None ->
|
| Error x ->
|
||||||
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
match x with
|
||||||
| Error (Some msg) ->
|
| None ->
|
||||||
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
||||||
go ParseState_BasicNoPositionals.AwaitingKey args
|
| Some msg ->
|
||||||
|
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
||||||
|
go ParseState_BasicNoPositionals.AwaitingKey args
|
||||||
else
|
else
|
||||||
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
||||||
go ParseState_BasicNoPositionals.AwaitingKey args
|
go ParseState_BasicNoPositionals.AwaitingKey args
|
||||||
@@ -365,11 +367,13 @@ module Basic =
|
|||||||
|
|
||||||
match processKeyValue key value with
|
match processKeyValue key value with
|
||||||
| Ok () -> go ParseState_Basic.AwaitingKey args
|
| Ok () -> go ParseState_Basic.AwaitingKey args
|
||||||
| Error None ->
|
| Error x ->
|
||||||
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
match x with
|
||||||
| Error (Some msg) ->
|
| None ->
|
||||||
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
||||||
go ParseState_Basic.AwaitingKey args
|
| Some msg ->
|
||||||
|
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
||||||
|
go ParseState_Basic.AwaitingKey args
|
||||||
else
|
else
|
||||||
arg |> (fun x -> x) |> arg_3.Add
|
arg |> (fun x -> x) |> arg_3.Add
|
||||||
go ParseState_Basic.AwaitingKey args
|
go ParseState_Basic.AwaitingKey args
|
||||||
@@ -566,11 +570,13 @@ module BasicWithIntPositionals =
|
|||||||
|
|
||||||
match processKeyValue key value with
|
match processKeyValue key value with
|
||||||
| Ok () -> go ParseState_BasicWithIntPositionals.AwaitingKey args
|
| Ok () -> go ParseState_BasicWithIntPositionals.AwaitingKey args
|
||||||
| Error None ->
|
| Error x ->
|
||||||
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
match x with
|
||||||
| Error (Some msg) ->
|
| None ->
|
||||||
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
||||||
go ParseState_BasicWithIntPositionals.AwaitingKey args
|
| Some msg ->
|
||||||
|
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
||||||
|
go ParseState_BasicWithIntPositionals.AwaitingKey args
|
||||||
else
|
else
|
||||||
arg |> (fun x -> System.Int32.Parse x) |> arg_3.Add
|
arg |> (fun x -> System.Int32.Parse x) |> arg_3.Add
|
||||||
go ParseState_BasicWithIntPositionals.AwaitingKey args
|
go ParseState_BasicWithIntPositionals.AwaitingKey args
|
||||||
@@ -945,11 +951,13 @@ module LoadsOfTypes =
|
|||||||
|
|
||||||
match processKeyValue key value with
|
match processKeyValue key value with
|
||||||
| Ok () -> go ParseState_LoadsOfTypes.AwaitingKey args
|
| Ok () -> go ParseState_LoadsOfTypes.AwaitingKey args
|
||||||
| Error None ->
|
| Error x ->
|
||||||
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
match x with
|
||||||
| Error (Some msg) ->
|
| None ->
|
||||||
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
||||||
go ParseState_LoadsOfTypes.AwaitingKey args
|
| Some msg ->
|
||||||
|
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
||||||
|
go ParseState_LoadsOfTypes.AwaitingKey args
|
||||||
else
|
else
|
||||||
arg |> (fun x -> System.Int32.Parse x) |> arg_7.Add
|
arg |> (fun x -> System.Int32.Parse x) |> arg_7.Add
|
||||||
go ParseState_LoadsOfTypes.AwaitingKey args
|
go ParseState_LoadsOfTypes.AwaitingKey args
|
||||||
@@ -1371,11 +1379,13 @@ module LoadsOfTypesNoPositionals =
|
|||||||
|
|
||||||
match processKeyValue key value with
|
match processKeyValue key value with
|
||||||
| Ok () -> go ParseState_LoadsOfTypesNoPositionals.AwaitingKey args
|
| Ok () -> go ParseState_LoadsOfTypesNoPositionals.AwaitingKey args
|
||||||
| Error None ->
|
| Error x ->
|
||||||
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
match x with
|
||||||
| Error (Some msg) ->
|
| None ->
|
||||||
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
||||||
go ParseState_LoadsOfTypesNoPositionals.AwaitingKey args
|
| Some msg ->
|
||||||
|
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
||||||
|
go ParseState_LoadsOfTypesNoPositionals.AwaitingKey args
|
||||||
else
|
else
|
||||||
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
||||||
go ParseState_LoadsOfTypesNoPositionals.AwaitingKey args
|
go ParseState_LoadsOfTypesNoPositionals.AwaitingKey args
|
||||||
@@ -1688,11 +1698,17 @@ module DatesAndTimesArgParse =
|
|||||||
|
|
||||||
match processKeyValue key value with
|
match processKeyValue key value with
|
||||||
| Ok () -> go ParseState_DatesAndTimes.AwaitingKey args
|
| Ok () -> go ParseState_DatesAndTimes.AwaitingKey args
|
||||||
| Error None ->
|
| Error x ->
|
||||||
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
match x with
|
||||||
| Error (Some msg) ->
|
| None ->
|
||||||
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
failwithf
|
||||||
go ParseState_DatesAndTimes.AwaitingKey args
|
"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_DatesAndTimes.AwaitingKey args
|
||||||
else
|
else
|
||||||
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
||||||
go ParseState_DatesAndTimes.AwaitingKey args
|
go ParseState_DatesAndTimes.AwaitingKey args
|
||||||
@@ -1918,11 +1934,17 @@ module ParentRecordArgParse =
|
|||||||
|
|
||||||
match processKeyValue key value with
|
match processKeyValue key value with
|
||||||
| Ok () -> go ParseState_ParentRecord.AwaitingKey args
|
| Ok () -> go ParseState_ParentRecord.AwaitingKey args
|
||||||
| Error None ->
|
| Error x ->
|
||||||
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
match x with
|
||||||
| Error (Some msg) ->
|
| None ->
|
||||||
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
failwithf
|
||||||
go ParseState_ParentRecord.AwaitingKey args
|
"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_ParentRecord.AwaitingKey args
|
||||||
else
|
else
|
||||||
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
||||||
go ParseState_ParentRecord.AwaitingKey args
|
go ParseState_ParentRecord.AwaitingKey args
|
||||||
@@ -2124,11 +2146,17 @@ module ParentRecordChildPosArgParse =
|
|||||||
|
|
||||||
match processKeyValue key value with
|
match processKeyValue key value with
|
||||||
| Ok () -> go ParseState_ParentRecordChildPos.AwaitingKey args
|
| Ok () -> go ParseState_ParentRecordChildPos.AwaitingKey args
|
||||||
| Error None ->
|
| Error x ->
|
||||||
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
match x with
|
||||||
| Error (Some msg) ->
|
| None ->
|
||||||
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
failwithf
|
||||||
go ParseState_ParentRecordChildPos.AwaitingKey args
|
"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_ParentRecordChildPos.AwaitingKey args
|
||||||
else
|
else
|
||||||
arg |> (fun x -> System.Uri x) |> arg_1.Add
|
arg |> (fun x -> System.Uri x) |> arg_1.Add
|
||||||
go ParseState_ParentRecordChildPos.AwaitingKey args
|
go ParseState_ParentRecordChildPos.AwaitingKey args
|
||||||
@@ -2297,11 +2325,17 @@ module ParentRecordSelfPosArgParse =
|
|||||||
|
|
||||||
match processKeyValue key value with
|
match processKeyValue key value with
|
||||||
| Ok () -> go ParseState_ParentRecordSelfPos.AwaitingKey args
|
| Ok () -> go ParseState_ParentRecordSelfPos.AwaitingKey args
|
||||||
| Error None ->
|
| Error x ->
|
||||||
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
match x with
|
||||||
| Error (Some msg) ->
|
| None ->
|
||||||
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
failwithf
|
||||||
go ParseState_ParentRecordSelfPos.AwaitingKey args
|
"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_ParentRecordSelfPos.AwaitingKey args
|
||||||
else
|
else
|
||||||
arg |> (fun x -> System.Boolean.Parse x) |> arg_2.Add
|
arg |> (fun x -> System.Boolean.Parse x) |> arg_2.Add
|
||||||
go ParseState_ParentRecordSelfPos.AwaitingKey args
|
go ParseState_ParentRecordSelfPos.AwaitingKey args
|
||||||
@@ -2428,11 +2462,17 @@ module ChoicePositionalsArgParse =
|
|||||||
|
|
||||||
match processKeyValue key value with
|
match processKeyValue key value with
|
||||||
| Ok () -> go ParseState_ChoicePositionals.AwaitingKey args
|
| Ok () -> go ParseState_ChoicePositionals.AwaitingKey args
|
||||||
| Error None ->
|
| Error x ->
|
||||||
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
match x with
|
||||||
| Error (Some msg) ->
|
| None ->
|
||||||
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
failwithf
|
||||||
go ParseState_ChoicePositionals.AwaitingKey args
|
"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_ChoicePositionals.AwaitingKey args
|
||||||
else
|
else
|
||||||
arg |> (fun x -> x) |> Choice1Of2 |> arg_0.Add
|
arg |> (fun x -> x) |> Choice1Of2 |> arg_0.Add
|
||||||
go ParseState_ChoicePositionals.AwaitingKey args
|
go ParseState_ChoicePositionals.AwaitingKey args
|
||||||
@@ -2567,11 +2607,17 @@ module ContainsBoolEnvVarArgParse =
|
|||||||
|
|
||||||
match processKeyValue key value with
|
match processKeyValue key value with
|
||||||
| Ok () -> go ParseState_ContainsBoolEnvVar.AwaitingKey args
|
| Ok () -> go ParseState_ContainsBoolEnvVar.AwaitingKey args
|
||||||
| Error None ->
|
| Error x ->
|
||||||
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
match x with
|
||||||
| Error (Some msg) ->
|
| None ->
|
||||||
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
failwithf
|
||||||
go ParseState_ContainsBoolEnvVar.AwaitingKey args
|
"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_ContainsBoolEnvVar.AwaitingKey args
|
||||||
else
|
else
|
||||||
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
||||||
go ParseState_ContainsBoolEnvVar.AwaitingKey args
|
go ParseState_ContainsBoolEnvVar.AwaitingKey args
|
||||||
@@ -2747,11 +2793,17 @@ module WithFlagDuArgParse =
|
|||||||
|
|
||||||
match processKeyValue key value with
|
match processKeyValue key value with
|
||||||
| Ok () -> go ParseState_WithFlagDu.AwaitingKey args
|
| Ok () -> go ParseState_WithFlagDu.AwaitingKey args
|
||||||
| Error None ->
|
| Error x ->
|
||||||
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
match x with
|
||||||
| Error (Some msg) ->
|
| None ->
|
||||||
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
failwithf
|
||||||
go ParseState_WithFlagDu.AwaitingKey args
|
"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_WithFlagDu.AwaitingKey args
|
||||||
else
|
else
|
||||||
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
||||||
go ParseState_WithFlagDu.AwaitingKey args
|
go ParseState_WithFlagDu.AwaitingKey args
|
||||||
@@ -2920,11 +2972,17 @@ module ContainsFlagEnvVarArgParse =
|
|||||||
|
|
||||||
match processKeyValue key value with
|
match processKeyValue key value with
|
||||||
| Ok () -> go ParseState_ContainsFlagEnvVar.AwaitingKey args
|
| Ok () -> go ParseState_ContainsFlagEnvVar.AwaitingKey args
|
||||||
| Error None ->
|
| Error x ->
|
||||||
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
match x with
|
||||||
| Error (Some msg) ->
|
| None ->
|
||||||
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
failwithf
|
||||||
go ParseState_ContainsFlagEnvVar.AwaitingKey args
|
"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_ContainsFlagEnvVar.AwaitingKey args
|
||||||
else
|
else
|
||||||
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
||||||
go ParseState_ContainsFlagEnvVar.AwaitingKey args
|
go ParseState_ContainsFlagEnvVar.AwaitingKey args
|
||||||
@@ -3126,11 +3184,17 @@ module ContainsFlagDefaultValueArgParse =
|
|||||||
|
|
||||||
match processKeyValue key value with
|
match processKeyValue key value with
|
||||||
| Ok () -> go ParseState_ContainsFlagDefaultValue.AwaitingKey args
|
| Ok () -> go ParseState_ContainsFlagDefaultValue.AwaitingKey args
|
||||||
| Error None ->
|
| Error x ->
|
||||||
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
match x with
|
||||||
| Error (Some msg) ->
|
| None ->
|
||||||
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
failwithf
|
||||||
go ParseState_ContainsFlagDefaultValue.AwaitingKey args
|
"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_ContainsFlagDefaultValue.AwaitingKey args
|
||||||
else
|
else
|
||||||
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
||||||
go ParseState_ContainsFlagDefaultValue.AwaitingKey args
|
go ParseState_ContainsFlagDefaultValue.AwaitingKey args
|
||||||
@@ -3367,11 +3431,17 @@ module ManyLongFormsArgParse =
|
|||||||
|
|
||||||
match processKeyValue key value with
|
match processKeyValue key value with
|
||||||
| Ok () -> go ParseState_ManyLongForms.AwaitingKey args
|
| Ok () -> go ParseState_ManyLongForms.AwaitingKey args
|
||||||
| Error None ->
|
| Error x ->
|
||||||
failwithf "Unable to process argument %s as key %s and value %s" arg key value
|
match x with
|
||||||
| Error (Some msg) ->
|
| None ->
|
||||||
sprintf "%s (at arg %s)" msg arg |> ArgParser_errors.Add
|
failwithf
|
||||||
go ParseState_ManyLongForms.AwaitingKey args
|
"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_ManyLongForms.AwaitingKey args
|
||||||
else
|
else
|
||||||
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
arg |> (fun x -> x) |> parser_LeftoverArgs.Add
|
||||||
go ParseState_ManyLongForms.AwaitingKey args
|
go ParseState_ManyLongForms.AwaitingKey args
|
||||||
@@ -3435,3 +3505,331 @@ module ManyLongFormsArgParse =
|
|||||||
|
|
||||||
static member parse (args : string list) : ManyLongForms =
|
static member parse (args : string list) : ManyLongForms =
|
||||||
ManyLongForms.parse' System.Environment.GetEnvironmentVariable args
|
ManyLongForms.parse' System.Environment.GetEnvironmentVariable args
|
||||||
|
namespace ConsumePlugin
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.IO
|
||||||
|
open WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
/// Methods to parse arguments for the type FlagsIntoPositionalArgs
|
||||||
|
[<AutoOpen>]
|
||||||
|
module FlagsIntoPositionalArgsArgParse =
|
||||||
|
type private ParseState_FlagsIntoPositionalArgs =
|
||||||
|
/// 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 FlagsIntoPositionalArgs with
|
||||||
|
|
||||||
|
static member parse'
|
||||||
|
(getEnvironmentVariable : string -> string)
|
||||||
|
(args : string list)
|
||||||
|
: FlagsIntoPositionalArgs
|
||||||
|
=
|
||||||
|
let ArgParser_errors = ResizeArray ()
|
||||||
|
|
||||||
|
let helpText () =
|
||||||
|
[
|
||||||
|
(sprintf "%s string%s%s" (sprintf "--%s" "a") "" "")
|
||||||
|
(sprintf
|
||||||
|
"%s string%s%s"
|
||||||
|
(sprintf "--%s" "grab-everything")
|
||||||
|
" (positional args) (can be repeated)"
|
||||||
|
"")
|
||||||
|
]
|
||||||
|
|> String.concat "\n"
|
||||||
|
|
||||||
|
let arg_1 : string ResizeArray = ResizeArray ()
|
||||||
|
let mutable arg_0 : string 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" "a", System.StringComparison.OrdinalIgnoreCase) then
|
||||||
|
match arg_0 with
|
||||||
|
| Some x ->
|
||||||
|
sprintf
|
||||||
|
"Argument '%s' was supplied multiple times: %s and %s"
|
||||||
|
(sprintf "--%s" "a")
|
||||||
|
(x.ToString ())
|
||||||
|
(value.ToString ())
|
||||||
|
|> ArgParser_errors.Add
|
||||||
|
|
||||||
|
Ok ()
|
||||||
|
| None ->
|
||||||
|
try
|
||||||
|
arg_0 <- value |> (fun x -> x) |> Some
|
||||||
|
Ok ()
|
||||||
|
with _ as exc ->
|
||||||
|
exc.Message |> Some |> Error
|
||||||
|
else if
|
||||||
|
System.String.Equals (
|
||||||
|
key,
|
||||||
|
sprintf "--%s" "grab-everything",
|
||||||
|
System.StringComparison.OrdinalIgnoreCase
|
||||||
|
)
|
||||||
|
then
|
||||||
|
value |> (fun x -> x) |> arg_1.Add
|
||||||
|
() |> Ok
|
||||||
|
else
|
||||||
|
Error None
|
||||||
|
|
||||||
|
/// Returns false if we didn't set a value.
|
||||||
|
let setFlagValue (key : string) : bool = false
|
||||||
|
|
||||||
|
let rec go (state : ParseState_FlagsIntoPositionalArgs) (args : string list) =
|
||||||
|
match args with
|
||||||
|
| [] ->
|
||||||
|
match state with
|
||||||
|
| ParseState_FlagsIntoPositionalArgs.AwaitingKey -> ()
|
||||||
|
| ParseState_FlagsIntoPositionalArgs.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 -> arg_1.AddRange (rest |> Seq.map (fun x -> x))
|
||||||
|
| arg :: args ->
|
||||||
|
match state with
|
||||||
|
| ParseState_FlagsIntoPositionalArgs.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_FlagsIntoPositionalArgs.AwaitingValue arg)
|
||||||
|
else
|
||||||
|
let key = arg.[0 .. equals - 1]
|
||||||
|
let value = arg.[equals + 1 ..]
|
||||||
|
|
||||||
|
match processKeyValue key value with
|
||||||
|
| Ok () -> go ParseState_FlagsIntoPositionalArgs.AwaitingKey args
|
||||||
|
| Error x ->
|
||||||
|
if true then
|
||||||
|
arg |> (fun x -> x) |> arg_1.Add
|
||||||
|
go ParseState_FlagsIntoPositionalArgs.AwaitingKey args
|
||||||
|
else
|
||||||
|
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_FlagsIntoPositionalArgs.AwaitingKey args
|
||||||
|
else
|
||||||
|
arg |> (fun x -> x) |> arg_1.Add
|
||||||
|
go ParseState_FlagsIntoPositionalArgs.AwaitingKey args
|
||||||
|
| ParseState_FlagsIntoPositionalArgs.AwaitingValue key ->
|
||||||
|
match processKeyValue key arg with
|
||||||
|
| Ok () -> go ParseState_FlagsIntoPositionalArgs.AwaitingKey args
|
||||||
|
| Error exc ->
|
||||||
|
if setFlagValue key then
|
||||||
|
go ParseState_FlagsIntoPositionalArgs.AwaitingKey (arg :: args)
|
||||||
|
else if true then
|
||||||
|
key |> arg_1.Add
|
||||||
|
go ParseState_FlagsIntoPositionalArgs.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_FlagsIntoPositionalArgs.AwaitingKey args
|
||||||
|
let arg_1 = arg_1 |> Seq.toList
|
||||||
|
|
||||||
|
let arg_0 =
|
||||||
|
match arg_0 with
|
||||||
|
| None ->
|
||||||
|
sprintf "Required argument '%s' received no value" (sprintf "--%s" "a")
|
||||||
|
|> ArgParser_errors.Add
|
||||||
|
|
||||||
|
Unchecked.defaultof<_>
|
||||||
|
| Some x -> x
|
||||||
|
|
||||||
|
if 0 = ArgParser_errors.Count then
|
||||||
|
{
|
||||||
|
A = arg_0
|
||||||
|
GrabEverything = arg_1
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ArgParser_errors |> String.concat "\n" |> failwithf "Errors during parse!\n%s"
|
||||||
|
|
||||||
|
static member parse (args : string list) : FlagsIntoPositionalArgs =
|
||||||
|
FlagsIntoPositionalArgs.parse' System.Environment.GetEnvironmentVariable args
|
||||||
|
namespace ConsumePlugin
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.IO
|
||||||
|
open WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
/// Methods to parse arguments for the type FlagsIntoPositionalArgs'
|
||||||
|
[<AutoOpen>]
|
||||||
|
module FlagsIntoPositionalArgs'ArgParse =
|
||||||
|
type private ParseState_FlagsIntoPositionalArgs' =
|
||||||
|
/// 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 FlagsIntoPositionalArgs' with
|
||||||
|
|
||||||
|
static member parse'
|
||||||
|
(getEnvironmentVariable : string -> string)
|
||||||
|
(args : string list)
|
||||||
|
: FlagsIntoPositionalArgs'
|
||||||
|
=
|
||||||
|
let ArgParser_errors = ResizeArray ()
|
||||||
|
|
||||||
|
let helpText () =
|
||||||
|
[
|
||||||
|
(sprintf "%s string%s%s" (sprintf "--%s" "a") "" "")
|
||||||
|
(sprintf
|
||||||
|
"%s string%s%s"
|
||||||
|
(sprintf "--%s" "dont-grab-everything")
|
||||||
|
" (positional args) (can be repeated)"
|
||||||
|
"")
|
||||||
|
]
|
||||||
|
|> String.concat "\n"
|
||||||
|
|
||||||
|
let arg_1 : string ResizeArray = ResizeArray ()
|
||||||
|
let mutable arg_0 : string 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" "a", System.StringComparison.OrdinalIgnoreCase) then
|
||||||
|
match arg_0 with
|
||||||
|
| Some x ->
|
||||||
|
sprintf
|
||||||
|
"Argument '%s' was supplied multiple times: %s and %s"
|
||||||
|
(sprintf "--%s" "a")
|
||||||
|
(x.ToString ())
|
||||||
|
(value.ToString ())
|
||||||
|
|> ArgParser_errors.Add
|
||||||
|
|
||||||
|
Ok ()
|
||||||
|
| None ->
|
||||||
|
try
|
||||||
|
arg_0 <- value |> (fun x -> x) |> Some
|
||||||
|
Ok ()
|
||||||
|
with _ as exc ->
|
||||||
|
exc.Message |> Some |> Error
|
||||||
|
else if
|
||||||
|
System.String.Equals (
|
||||||
|
key,
|
||||||
|
sprintf "--%s" "dont-grab-everything",
|
||||||
|
System.StringComparison.OrdinalIgnoreCase
|
||||||
|
)
|
||||||
|
then
|
||||||
|
value |> (fun x -> x) |> arg_1.Add
|
||||||
|
() |> Ok
|
||||||
|
else
|
||||||
|
Error None
|
||||||
|
|
||||||
|
/// Returns false if we didn't set a value.
|
||||||
|
let setFlagValue (key : string) : bool = false
|
||||||
|
|
||||||
|
let rec go (state : ParseState_FlagsIntoPositionalArgs') (args : string list) =
|
||||||
|
match args with
|
||||||
|
| [] ->
|
||||||
|
match state with
|
||||||
|
| ParseState_FlagsIntoPositionalArgs'.AwaitingKey -> ()
|
||||||
|
| ParseState_FlagsIntoPositionalArgs'.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 -> arg_1.AddRange (rest |> Seq.map (fun x -> x))
|
||||||
|
| arg :: args ->
|
||||||
|
match state with
|
||||||
|
| ParseState_FlagsIntoPositionalArgs'.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_FlagsIntoPositionalArgs'.AwaitingValue arg)
|
||||||
|
else
|
||||||
|
let key = arg.[0 .. equals - 1]
|
||||||
|
let value = arg.[equals + 1 ..]
|
||||||
|
|
||||||
|
match processKeyValue key value with
|
||||||
|
| Ok () -> go ParseState_FlagsIntoPositionalArgs'.AwaitingKey args
|
||||||
|
| Error x ->
|
||||||
|
if false then
|
||||||
|
arg |> (fun x -> x) |> arg_1.Add
|
||||||
|
go ParseState_FlagsIntoPositionalArgs'.AwaitingKey args
|
||||||
|
else
|
||||||
|
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_FlagsIntoPositionalArgs'.AwaitingKey args
|
||||||
|
else
|
||||||
|
arg |> (fun x -> x) |> arg_1.Add
|
||||||
|
go ParseState_FlagsIntoPositionalArgs'.AwaitingKey args
|
||||||
|
| ParseState_FlagsIntoPositionalArgs'.AwaitingValue key ->
|
||||||
|
match processKeyValue key arg with
|
||||||
|
| Ok () -> go ParseState_FlagsIntoPositionalArgs'.AwaitingKey args
|
||||||
|
| Error exc ->
|
||||||
|
if setFlagValue key then
|
||||||
|
go ParseState_FlagsIntoPositionalArgs'.AwaitingKey (arg :: args)
|
||||||
|
else if false then
|
||||||
|
key |> arg_1.Add
|
||||||
|
go ParseState_FlagsIntoPositionalArgs'.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_FlagsIntoPositionalArgs'.AwaitingKey args
|
||||||
|
let arg_1 = arg_1 |> Seq.toList
|
||||||
|
|
||||||
|
let arg_0 =
|
||||||
|
match arg_0 with
|
||||||
|
| None ->
|
||||||
|
sprintf "Required argument '%s' received no value" (sprintf "--%s" "a")
|
||||||
|
|> ArgParser_errors.Add
|
||||||
|
|
||||||
|
Unchecked.defaultof<_>
|
||||||
|
| Some x -> x
|
||||||
|
|
||||||
|
if 0 = ArgParser_errors.Count then
|
||||||
|
{
|
||||||
|
A = arg_0
|
||||||
|
DontGrabEverything = arg_1
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ArgParser_errors |> String.concat "\n" |> failwithf "Errors during parse!\n%s"
|
||||||
|
|
||||||
|
static member parse (args : string list) : FlagsIntoPositionalArgs' =
|
||||||
|
FlagsIntoPositionalArgs'.parse' System.Environment.GetEnvironmentVariable args
|
||||||
|
@@ -19,9 +19,22 @@ type ArgParserAttribute (isExtensionMethod : bool) =
|
|||||||
|
|
||||||
/// Attribute indicating that this field shall accumulate all unmatched args,
|
/// Attribute indicating that this field shall accumulate all unmatched args,
|
||||||
/// as well as any that appear after a bare `--`.
|
/// as well as any that appear after a bare `--`.
|
||||||
type PositionalArgsAttribute () =
|
///
|
||||||
|
/// Set `includeFlagLike = true` to include args that begin `--` in the
|
||||||
|
/// positional args.
|
||||||
|
/// (By default, `includeFlagLike = false` and we throw when encountering
|
||||||
|
/// an argument which looks like a flag but which we don't recognise.)
|
||||||
|
/// We will still interpret `--help` as requesting help, unless it comes after
|
||||||
|
/// a standalone `--` separator.
|
||||||
|
type PositionalArgsAttribute (includeFlagLike : bool) =
|
||||||
inherit Attribute ()
|
inherit Attribute ()
|
||||||
|
|
||||||
|
/// The default value of `isExtensionMethod`, the optional argument to the ArgParserAttribute constructor.
|
||||||
|
static member DefaultIncludeFlagLike = false
|
||||||
|
|
||||||
|
/// Shorthand for the "includeFlagLike = false" constructor; see documentation there for details.
|
||||||
|
new () = PositionalArgsAttribute PositionalArgsAttribute.DefaultIncludeFlagLike
|
||||||
|
|
||||||
/// Attribute indicating that this field shall have a default value derived
|
/// Attribute indicating that this field shall have a default value derived
|
||||||
/// from calling an appropriately named static method on the type.
|
/// from calling an appropriately named static method on the type.
|
||||||
///
|
///
|
||||||
|
@@ -40,7 +40,10 @@ WoofWare.Myriad.Plugins.JsonSerializeAttribute.get_DefaultIsExtensionMethod [sta
|
|||||||
WoofWare.Myriad.Plugins.ParseExactAttribute inherit System.Attribute
|
WoofWare.Myriad.Plugins.ParseExactAttribute inherit System.Attribute
|
||||||
WoofWare.Myriad.Plugins.ParseExactAttribute..ctor [constructor]: string
|
WoofWare.Myriad.Plugins.ParseExactAttribute..ctor [constructor]: string
|
||||||
WoofWare.Myriad.Plugins.PositionalArgsAttribute inherit System.Attribute
|
WoofWare.Myriad.Plugins.PositionalArgsAttribute inherit System.Attribute
|
||||||
|
WoofWare.Myriad.Plugins.PositionalArgsAttribute..ctor [constructor]: bool
|
||||||
WoofWare.Myriad.Plugins.PositionalArgsAttribute..ctor [constructor]: unit
|
WoofWare.Myriad.Plugins.PositionalArgsAttribute..ctor [constructor]: unit
|
||||||
|
WoofWare.Myriad.Plugins.PositionalArgsAttribute.DefaultIncludeFlagLike [static property]: [read-only] bool
|
||||||
|
WoofWare.Myriad.Plugins.PositionalArgsAttribute.get_DefaultIncludeFlagLike [static method]: unit -> bool
|
||||||
WoofWare.Myriad.Plugins.RemoveOptionsAttribute inherit System.Attribute
|
WoofWare.Myriad.Plugins.RemoveOptionsAttribute inherit System.Attribute
|
||||||
WoofWare.Myriad.Plugins.RemoveOptionsAttribute..ctor [constructor]: unit
|
WoofWare.Myriad.Plugins.RemoveOptionsAttribute..ctor [constructor]: unit
|
||||||
WoofWare.Myriad.Plugins.RestEase inherit obj
|
WoofWare.Myriad.Plugins.RestEase inherit obj
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "3.4",
|
"version": "3.5",
|
||||||
"publicReleaseRefSpec": [
|
"publicReleaseRefSpec": [
|
||||||
"^refs/heads/main$"
|
"^refs/heads/main$"
|
||||||
],
|
],
|
||||||
|
@@ -618,3 +618,50 @@ Required argument '--exact' received no value"""
|
|||||||
"""Help text requested.
|
"""Help text requested.
|
||||||
--do-something-else / --anotherarg string
|
--do-something-else / --anotherarg string
|
||||||
--turn-it-on / --dont-turn-it-off bool"""
|
--turn-it-on / --dont-turn-it-off bool"""
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let ``Can collect *all* non-help args into positional args with includeFlagLike`` () =
|
||||||
|
let getEnvVar (_ : string) = failwith "do not call"
|
||||||
|
|
||||||
|
FlagsIntoPositionalArgs.parse' getEnvVar [ "--a" ; "foo" ; "--b=false" ; "--c" ; "hi" ; "--" ; "--help" ]
|
||||||
|
|> shouldEqual
|
||||||
|
{
|
||||||
|
A = "foo"
|
||||||
|
GrabEverything = [ "--b=false" ; "--c" ; "hi" ; "--help" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Users might consider this eccentric!
|
||||||
|
// But we're only a simple arg parser; we don't look around to see whether this is "almost"
|
||||||
|
// a valid parse.
|
||||||
|
FlagsIntoPositionalArgs.parse' getEnvVar [ "--a" ; "--b=false" ; "--c" ; "hi" ; "--" ; "--help" ]
|
||||||
|
|> shouldEqual
|
||||||
|
{
|
||||||
|
A = "--b=false"
|
||||||
|
GrabEverything = [ "--c" ; "hi" ; "--help" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let ``Can refuse to collect non-help args with PositionalArgs false`` () =
|
||||||
|
let getEnvVar (_ : string) = failwith "do not call"
|
||||||
|
|
||||||
|
let exc =
|
||||||
|
Assert.Throws<exn> (fun () ->
|
||||||
|
FlagsIntoPositionalArgs'.parse'
|
||||||
|
getEnvVar
|
||||||
|
[ "--a" ; "foo" ; "--b=false" ; "--c" ; "hi" ; "--" ; "--help" ]
|
||||||
|
|> ignore<FlagsIntoPositionalArgs'>
|
||||||
|
)
|
||||||
|
|
||||||
|
exc.Message
|
||||||
|
|> shouldEqual """Unable to process argument --b=false as key --b and value false"""
|
||||||
|
|
||||||
|
let exc =
|
||||||
|
Assert.Throws<exn> (fun () ->
|
||||||
|
FlagsIntoPositionalArgs'.parse' getEnvVar [ "--a" ; "--b=false" ; "--c=hi" ; "--" ; "--help" ]
|
||||||
|
|> ignore<FlagsIntoPositionalArgs'>
|
||||||
|
)
|
||||||
|
|
||||||
|
// Again perhaps eccentric!
|
||||||
|
// Again, we don't try to detect that the user has missed out the desired argument to `--a`.
|
||||||
|
exc.Message
|
||||||
|
|> shouldEqual """Unable to process argument --c=hi as key --c and value hi"""
|
||||||
|
@@ -85,8 +85,8 @@ type private ParseFunction<'acc> =
|
|||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
type private ChoicePositional =
|
type private ChoicePositional =
|
||||||
| Normal
|
| Normal of includeFlagLike : SynExpr option
|
||||||
| Choice
|
| Choice of includeFlagLike : SynExpr option
|
||||||
|
|
||||||
type private ParseFunctionPositional = ParseFunction<ChoicePositional>
|
type private ParseFunctionPositional = ParseFunction<ChoicePositional>
|
||||||
type private ParseFunctionNonPositional = ParseFunction<Accumulation<ArgumentDefaultSpec>>
|
type private ParseFunctionNonPositional = ParseFunction<Accumulation<ArgumentDefaultSpec>>
|
||||||
@@ -506,11 +506,14 @@ module internal ArgParserGenerator =
|
|||||||
|
|
||||||
let positionalArgAttr =
|
let positionalArgAttr =
|
||||||
attrs
|
attrs
|
||||||
|> List.tryFind (fun a ->
|
|> List.tryPick (fun a ->
|
||||||
match (List.last a.TypeName.LongIdent).idText with
|
match (List.last a.TypeName.LongIdent).idText with
|
||||||
| "PositionalArgsAttribute"
|
| "PositionalArgsAttribute"
|
||||||
| "PositionalArgs" -> true
|
| "PositionalArgs" ->
|
||||||
| _ -> false
|
match a.ArgExpr with
|
||||||
|
| SynExpr.Const (SynConst.Unit, _) -> Some None
|
||||||
|
| a -> Some (Some a)
|
||||||
|
| _ -> None
|
||||||
)
|
)
|
||||||
|
|
||||||
let parseExactModifier =
|
let parseExactModifier =
|
||||||
@@ -580,7 +583,7 @@ module internal ArgParserGenerator =
|
|||||||
| None ->
|
| None ->
|
||||||
|
|
||||||
match positionalArgAttr with
|
match positionalArgAttr with
|
||||||
| Some _ ->
|
| Some includeFlagLike ->
|
||||||
let getChoice (spec : ArgumentDefaultSpec option) : unit =
|
let getChoice (spec : ArgumentDefaultSpec option) : unit =
|
||||||
match spec with
|
match spec with
|
||||||
| Some _ ->
|
| Some _ ->
|
||||||
@@ -607,7 +610,7 @@ module internal ArgParserGenerator =
|
|||||||
FieldName = ident
|
FieldName = ident
|
||||||
Parser = parser
|
Parser = parser
|
||||||
TargetVariable = Ident.create $"arg_%i{counter}"
|
TargetVariable = Ident.create $"arg_%i{counter}"
|
||||||
Accumulation = ChoicePositional.Choice
|
Accumulation = ChoicePositional.Choice includeFlagLike
|
||||||
TargetType = parseTy
|
TargetType = parseTy
|
||||||
ArgForm = longForms
|
ArgForm = longForms
|
||||||
Help = helpText
|
Help = helpText
|
||||||
@@ -619,7 +622,7 @@ module internal ArgParserGenerator =
|
|||||||
FieldName = ident
|
FieldName = ident
|
||||||
Parser = parser
|
Parser = parser
|
||||||
TargetVariable = Ident.create $"arg_%i{counter}"
|
TargetVariable = Ident.create $"arg_%i{counter}"
|
||||||
Accumulation = ChoicePositional.Normal
|
Accumulation = ChoicePositional.Normal includeFlagLike
|
||||||
TargetType = parseTy
|
TargetType = parseTy
|
||||||
ArgForm = longForms
|
ArgForm = longForms
|
||||||
Help = helpText
|
Help = helpText
|
||||||
@@ -855,8 +858,9 @@ module internal ArgParserGenerator =
|
|||||||
|> SynExpr.pipeThroughFunction pos.Parser
|
|> SynExpr.pipeThroughFunction pos.Parser
|
||||||
|> fun p ->
|
|> fun p ->
|
||||||
match pos.Accumulation with
|
match pos.Accumulation with
|
||||||
| ChoicePositional.Choice -> p |> SynExpr.pipeThroughFunction (SynExpr.createIdent "Choice1Of2")
|
| ChoicePositional.Choice _ ->
|
||||||
| ChoicePositional.Normal -> p
|
p |> SynExpr.pipeThroughFunction (SynExpr.createIdent "Choice1Of2")
|
||||||
|
| ChoicePositional.Normal _ -> p
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.createLongIdent' [ pos.TargetVariable ; Ident.create "Add" ]
|
SynExpr.createLongIdent' [ pos.TargetVariable ; Ident.create "Add" ]
|
||||||
)
|
)
|
||||||
@@ -1000,6 +1004,50 @@ module internal ArgParserGenerator =
|
|||||||
|> SynExpr.applyTo (SynExpr.createIdent "key")
|
|> SynExpr.applyTo (SynExpr.createIdent "key")
|
||||||
|> SynExpr.applyTo (SynExpr.createIdent "value")
|
|> SynExpr.applyTo (SynExpr.createIdent "value")
|
||||||
|
|
||||||
|
let processAsPositional =
|
||||||
|
SynExpr.sequential
|
||||||
|
[
|
||||||
|
SynExpr.createIdent "arg"
|
||||||
|
|> SynExpr.pipeThroughFunction leftoverArgParser
|
||||||
|
|> fun p ->
|
||||||
|
match leftoverArgAcc with
|
||||||
|
| ChoicePositional.Normal _ -> p
|
||||||
|
| ChoicePositional.Choice _ ->
|
||||||
|
p |> SynExpr.pipeThroughFunction (SynExpr.createIdent "Choice1Of2")
|
||||||
|
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent' [ leftoverArgs ; Ident.create "Add" ])
|
||||||
|
|
||||||
|
recurseKey
|
||||||
|
]
|
||||||
|
|
||||||
|
let posAttr =
|
||||||
|
match leftoverArgAcc with
|
||||||
|
| ChoicePositional.Choice a
|
||||||
|
| ChoicePositional.Normal a -> a
|
||||||
|
|
||||||
|
let notMatched =
|
||||||
|
let handleFailure =
|
||||||
|
[
|
||||||
|
SynMatchClause.create (SynPat.named "None") fail
|
||||||
|
|
||||||
|
SynMatchClause.create
|
||||||
|
(SynPat.nameWithArgs "Some" [ SynPat.named "msg" ])
|
||||||
|
(SynExpr.sequential
|
||||||
|
[
|
||||||
|
SynExpr.createIdent "sprintf"
|
||||||
|
|> SynExpr.applyTo (SynExpr.CreateConst "%s (at arg %s)")
|
||||||
|
|> SynExpr.applyTo (SynExpr.createIdent "msg")
|
||||||
|
|> SynExpr.applyTo (SynExpr.createIdent "arg")
|
||||||
|
|> SynExpr.pipeThroughFunction (SynExpr.dotGet "Add" (SynExpr.createIdent' errorAcc))
|
||||||
|
|
||||||
|
recurseKey
|
||||||
|
])
|
||||||
|
]
|
||||||
|
|> SynExpr.createMatch (SynExpr.createIdent "x")
|
||||||
|
|
||||||
|
match posAttr with
|
||||||
|
| None -> handleFailure
|
||||||
|
| Some posAttr -> SynExpr.ifThenElse posAttr handleFailure processAsPositional
|
||||||
|
|
||||||
let argStartsWithDashes =
|
let argStartsWithDashes =
|
||||||
SynExpr.createIdent "arg"
|
SynExpr.createIdent "arg"
|
||||||
|> SynExpr.callMethodArg
|
|> SynExpr.callMethodArg
|
||||||
@@ -1013,19 +1061,7 @@ module internal ArgParserGenerator =
|
|||||||
let processKey =
|
let processKey =
|
||||||
SynExpr.ifThenElse
|
SynExpr.ifThenElse
|
||||||
argStartsWithDashes
|
argStartsWithDashes
|
||||||
(SynExpr.sequential
|
processAsPositional
|
||||||
[
|
|
||||||
SynExpr.createIdent "arg"
|
|
||||||
|> SynExpr.pipeThroughFunction leftoverArgParser
|
|
||||||
|> fun p ->
|
|
||||||
match leftoverArgAcc with
|
|
||||||
| ChoicePositional.Normal -> p
|
|
||||||
| ChoicePositional.Choice ->
|
|
||||||
p |> SynExpr.pipeThroughFunction (SynExpr.createIdent "Choice1Of2")
|
|
||||||
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent' [ leftoverArgs ; Ident.create "Add" ])
|
|
||||||
|
|
||||||
recurseKey
|
|
||||||
])
|
|
||||||
(SynExpr.ifThenElse
|
(SynExpr.ifThenElse
|
||||||
(SynExpr.equals (SynExpr.createIdent "arg") (SynExpr.CreateConst "--help"))
|
(SynExpr.equals (SynExpr.createIdent "arg") (SynExpr.CreateConst "--help"))
|
||||||
(SynExpr.createLet
|
(SynExpr.createLet
|
||||||
@@ -1061,23 +1097,9 @@ module internal ArgParserGenerator =
|
|||||||
[
|
[
|
||||||
SynMatchClause.create (SynPat.nameWithArgs "Ok" [ SynPat.unit ]) recurseKey
|
SynMatchClause.create (SynPat.nameWithArgs "Ok" [ SynPat.unit ]) recurseKey
|
||||||
|
|
||||||
SynMatchClause.create (SynPat.nameWithArgs "Error" [ SynPat.named "None" ]) fail
|
|
||||||
SynMatchClause.create
|
SynMatchClause.create
|
||||||
(SynPat.nameWithArgs
|
(SynPat.nameWithArgs "Error" [ SynPat.named "x" ])
|
||||||
"Error"
|
notMatched
|
||||||
[ SynPat.nameWithArgs "Some" [ SynPat.named "msg" ] |> SynPat.paren ])
|
|
||||||
(SynExpr.sequential
|
|
||||||
[
|
|
||||||
SynExpr.createIdent "sprintf"
|
|
||||||
|> SynExpr.applyTo (SynExpr.CreateConst "%s (at arg %s)")
|
|
||||||
|> SynExpr.applyTo (SynExpr.createIdent "msg")
|
|
||||||
|> SynExpr.applyTo (SynExpr.createIdent "arg")
|
|
||||||
|> SynExpr.pipeThroughFunction (
|
|
||||||
SynExpr.dotGet "Add" (SynExpr.createIdent' errorAcc)
|
|
||||||
)
|
|
||||||
|
|
||||||
recurseKey
|
|
||||||
])
|
|
||||||
]))
|
]))
|
||||||
(SynExpr.createIdent "args" |> SynExpr.pipeThroughFunction recurseValue)))
|
(SynExpr.createIdent "args" |> SynExpr.pipeThroughFunction recurseValue)))
|
||||||
(SynExpr.createIdent "helpText"
|
(SynExpr.createIdent "helpText"
|
||||||
@@ -1091,6 +1113,8 @@ module internal ArgParserGenerator =
|
|||||||
let processValue =
|
let processValue =
|
||||||
// During failure, we've received an optional exception message that happened when we tried to parse
|
// During failure, we've received an optional exception message that happened when we tried to parse
|
||||||
// the value; it's in the variable `exc`.
|
// the value; it's in the variable `exc`.
|
||||||
|
// `fail` is for the case where we're genuinely emitting an error.
|
||||||
|
// If we're in `PositionalArgs true` mode, though, we won't call `fail`.
|
||||||
let fail =
|
let fail =
|
||||||
[
|
[
|
||||||
SynExpr.createIdent "failwithf"
|
SynExpr.createIdent "failwithf"
|
||||||
@@ -1110,6 +1134,21 @@ module internal ArgParserGenerator =
|
|||||||
]
|
]
|
||||||
|> SynExpr.createMatch (SynExpr.createIdent "exc")
|
|> SynExpr.createMatch (SynExpr.createIdent "exc")
|
||||||
|
|
||||||
|
let onFailure =
|
||||||
|
match posAttr with
|
||||||
|
| None -> fail
|
||||||
|
| Some includeFlagLike ->
|
||||||
|
[
|
||||||
|
SynExpr.createIdent "key"
|
||||||
|
|> SynExpr.pipeThroughFunction (SynExpr.createLongIdent' [ leftoverArgs ; Ident.create "Add" ])
|
||||||
|
|
||||||
|
SynExpr.createIdent "go"
|
||||||
|
|> SynExpr.applyTo (SynExpr.createLongIdent' [ parseState ; Ident.create "AwaitingKey" ])
|
||||||
|
|> SynExpr.applyTo (SynExpr.listCons (SynExpr.createIdent "arg") (SynExpr.createIdent "args"))
|
||||||
|
]
|
||||||
|
|> SynExpr.sequential
|
||||||
|
|> SynExpr.ifThenElse includeFlagLike fail
|
||||||
|
|
||||||
[
|
[
|
||||||
SynMatchClause.create
|
SynMatchClause.create
|
||||||
(SynPat.nameWithArgs "Ok" [ SynPat.unit ])
|
(SynPat.nameWithArgs "Ok" [ SynPat.unit ])
|
||||||
@@ -1122,7 +1161,7 @@ module internal ArgParserGenerator =
|
|||||||
(SynPat.nameWithArgs "Error" [ SynPat.named "exc" ])
|
(SynPat.nameWithArgs "Error" [ SynPat.named "exc" ])
|
||||||
(SynExpr.ifThenElse
|
(SynExpr.ifThenElse
|
||||||
(SynExpr.applyFunction (SynExpr.createIdent "setFlagValue") (SynExpr.createIdent "key"))
|
(SynExpr.applyFunction (SynExpr.createIdent "setFlagValue") (SynExpr.createIdent "key"))
|
||||||
fail
|
onFailure
|
||||||
(SynExpr.createIdent "go"
|
(SynExpr.createIdent "go"
|
||||||
|> SynExpr.applyTo (SynExpr.createLongIdent' [ parseState ; Ident.create "AwaitingKey" ])
|
|> SynExpr.applyTo (SynExpr.createLongIdent' [ parseState ; Ident.create "AwaitingKey" ])
|
||||||
|> SynExpr.applyTo (SynExpr.listCons (SynExpr.createIdent "arg") (SynExpr.createIdent "args"))))
|
|> SynExpr.applyTo (SynExpr.listCons (SynExpr.createIdent "arg") (SynExpr.createIdent "args"))))
|
||||||
@@ -1189,8 +1228,8 @@ module internal ArgParserGenerator =
|
|||||||
)
|
)
|
||||||
|> fun p ->
|
|> fun p ->
|
||||||
match leftoverArgAcc with
|
match leftoverArgAcc with
|
||||||
| ChoicePositional.Normal -> p
|
| ChoicePositional.Normal _ -> p
|
||||||
| ChoicePositional.Choice ->
|
| ChoicePositional.Choice _ ->
|
||||||
p
|
p
|
||||||
|> SynExpr.pipeThroughFunction (
|
|> SynExpr.pipeThroughFunction (
|
||||||
SynExpr.applyFunction
|
SynExpr.applyFunction
|
||||||
@@ -1262,9 +1301,9 @@ module internal ArgParserGenerator =
|
|||||||
SynType.string
|
SynType.string
|
||||||
| Some pf ->
|
| Some pf ->
|
||||||
match pf.Accumulation with
|
match pf.Accumulation with
|
||||||
| ChoicePositional.Choice ->
|
| ChoicePositional.Choice _ ->
|
||||||
pf.TargetVariable, pf.Parser, SynType.app "Choice" [ pf.TargetType ; pf.TargetType ]
|
pf.TargetVariable, pf.Parser, SynType.app "Choice" [ pf.TargetType ; pf.TargetType ]
|
||||||
| ChoicePositional.Normal -> pf.TargetVariable, pf.Parser, pf.TargetType
|
| ChoicePositional.Normal _ -> pf.TargetVariable, pf.Parser, pf.TargetType
|
||||||
|
|
||||||
let bindings =
|
let bindings =
|
||||||
SynExpr.createIdent "ResizeArray"
|
SynExpr.createIdent "ResizeArray"
|
||||||
@@ -1492,7 +1531,7 @@ module internal ArgParserGenerator =
|
|||||||
|
|
||||||
let leftoverArgAcc =
|
let leftoverArgAcc =
|
||||||
match pos with
|
match pos with
|
||||||
| None -> ChoicePositional.Normal
|
| None -> ChoicePositional.Normal None
|
||||||
| Some pos -> pos.Accumulation
|
| Some pos -> pos.Accumulation
|
||||||
|
|
||||||
[
|
[
|
||||||
|
@@ -80,6 +80,11 @@ module internal SynExpr =
|
|||||||
let equals (a : SynExpr) (b : SynExpr) =
|
let equals (a : SynExpr) (b : SynExpr) =
|
||||||
SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.eq, a) |> applyTo b
|
SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.eq, a) |> applyTo b
|
||||||
|
|
||||||
|
/// {a} && {b}
|
||||||
|
let booleanAnd (a : SynExpr) (b : SynExpr) =
|
||||||
|
SynExpr.CreateAppInfix (SynExpr.CreateLongIdent SynLongIdent.booleanAnd, a)
|
||||||
|
|> applyTo b
|
||||||
|
|
||||||
/// {a} + {b}
|
/// {a} + {b}
|
||||||
let plus (a : SynExpr) (b : SynExpr) =
|
let plus (a : SynExpr) (b : SynExpr) =
|
||||||
SynExpr.CreateAppInfix (
|
SynExpr.CreateAppInfix (
|
||||||
|
@@ -33,6 +33,9 @@ module internal SynLongIdent =
|
|||||||
let eq =
|
let eq =
|
||||||
SynLongIdent.SynLongIdent ([ Ident.create "op_Equality" ], [], [ Some (IdentTrivia.OriginalNotation "=") ])
|
SynLongIdent.SynLongIdent ([ Ident.create "op_Equality" ], [], [ Some (IdentTrivia.OriginalNotation "=") ])
|
||||||
|
|
||||||
|
let booleanAnd =
|
||||||
|
SynLongIdent.SynLongIdent ([ Ident.create "op_BooleanAnd" ], [], [ Some (IdentTrivia.OriginalNotation "&&") ])
|
||||||
|
|
||||||
let pipe =
|
let pipe =
|
||||||
SynLongIdent.SynLongIdent ([ Ident.create "op_PipeRight" ], [], [ Some (IdentTrivia.OriginalNotation "|>") ])
|
SynLongIdent.SynLongIdent ([ Ident.create "op_PipeRight" ], [], [ Some (IdentTrivia.OriginalNotation "|>") ])
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user