mirror of
https://github.com/Smaug123/WoofWare.Myriad
synced 2025-10-08 05:28:39 +00:00
Compare commits
3 Commits
WoofWare.M
...
WoofWare.M
Author | SHA1 | Date | |
---|---|---|---|
|
09b7109c84 | ||
|
693b95106a | ||
|
49ecfbf5e5 |
@@ -204,6 +204,30 @@ type FlagsIntoPositionalArgs =
|
||||
GrabEverything : string list
|
||||
}
|
||||
|
||||
[<ArgParser true>]
|
||||
type FlagsIntoPositionalArgsChoice =
|
||||
{
|
||||
A : string
|
||||
[<PositionalArgs true>]
|
||||
GrabEverything : Choice<string, string> list
|
||||
}
|
||||
|
||||
[<ArgParser true>]
|
||||
type FlagsIntoPositionalArgsInt =
|
||||
{
|
||||
A : string
|
||||
[<PositionalArgs true>]
|
||||
GrabEverything : int list
|
||||
}
|
||||
|
||||
[<ArgParser true>]
|
||||
type FlagsIntoPositionalArgsIntChoice =
|
||||
{
|
||||
A : string
|
||||
[<PositionalArgs true>]
|
||||
GrabEverything : Choice<int, int> list
|
||||
}
|
||||
|
||||
[<ArgParser true>]
|
||||
type FlagsIntoPositionalArgs' =
|
||||
{
|
||||
|
@@ -3635,6 +3635,9 @@ module FlagsIntoPositionalArgsArgParse =
|
||||
| Error exc ->
|
||||
if setFlagValue key then
|
||||
go ParseState_FlagsIntoPositionalArgs.AwaitingKey (arg :: args)
|
||||
else if true then
|
||||
key |> (fun x -> x) |> arg_1.Add
|
||||
go ParseState_FlagsIntoPositionalArgs.AwaitingKey (arg :: args)
|
||||
else
|
||||
match exc with
|
||||
| None ->
|
||||
@@ -3672,6 +3675,498 @@ open System
|
||||
open System.IO
|
||||
open WoofWare.Myriad.Plugins
|
||||
|
||||
/// Methods to parse arguments for the type FlagsIntoPositionalArgsChoice
|
||||
[<AutoOpen>]
|
||||
module FlagsIntoPositionalArgsChoiceArgParse =
|
||||
type private ParseState_FlagsIntoPositionalArgsChoice =
|
||||
/// 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 FlagsIntoPositionalArgsChoice with
|
||||
|
||||
static member parse'
|
||||
(getEnvironmentVariable : string -> string)
|
||||
(args : string list)
|
||||
: FlagsIntoPositionalArgsChoice
|
||||
=
|
||||
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 : Choice<string, 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) |> Choice1Of2 |> 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_FlagsIntoPositionalArgsChoice) (args : string list) =
|
||||
match args with
|
||||
| [] ->
|
||||
match state with
|
||||
| ParseState_FlagsIntoPositionalArgsChoice.AwaitingKey -> ()
|
||||
| ParseState_FlagsIntoPositionalArgsChoice.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) |> Seq.map Choice2Of2)
|
||||
| arg :: args ->
|
||||
match state with
|
||||
| ParseState_FlagsIntoPositionalArgsChoice.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_FlagsIntoPositionalArgsChoice.AwaitingValue arg)
|
||||
else
|
||||
let key = arg.[0 .. equals - 1]
|
||||
let value = arg.[equals + 1 ..]
|
||||
|
||||
match processKeyValue key value with
|
||||
| Ok () -> go ParseState_FlagsIntoPositionalArgsChoice.AwaitingKey args
|
||||
| Error x ->
|
||||
if true then
|
||||
arg |> (fun x -> x) |> Choice1Of2 |> arg_1.Add
|
||||
go ParseState_FlagsIntoPositionalArgsChoice.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_FlagsIntoPositionalArgsChoice.AwaitingKey args
|
||||
else
|
||||
arg |> (fun x -> x) |> Choice1Of2 |> arg_1.Add
|
||||
go ParseState_FlagsIntoPositionalArgsChoice.AwaitingKey args
|
||||
| ParseState_FlagsIntoPositionalArgsChoice.AwaitingValue key ->
|
||||
match processKeyValue key arg with
|
||||
| Ok () -> go ParseState_FlagsIntoPositionalArgsChoice.AwaitingKey args
|
||||
| Error exc ->
|
||||
if setFlagValue key then
|
||||
go ParseState_FlagsIntoPositionalArgsChoice.AwaitingKey (arg :: args)
|
||||
else if true then
|
||||
key |> (fun x -> x) |> Choice1Of2 |> arg_1.Add
|
||||
go ParseState_FlagsIntoPositionalArgsChoice.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_FlagsIntoPositionalArgsChoice.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) : FlagsIntoPositionalArgsChoice =
|
||||
FlagsIntoPositionalArgsChoice.parse' System.Environment.GetEnvironmentVariable args
|
||||
namespace ConsumePlugin
|
||||
|
||||
open System
|
||||
open System.IO
|
||||
open WoofWare.Myriad.Plugins
|
||||
|
||||
/// Methods to parse arguments for the type FlagsIntoPositionalArgsInt
|
||||
[<AutoOpen>]
|
||||
module FlagsIntoPositionalArgsIntArgParse =
|
||||
type private ParseState_FlagsIntoPositionalArgsInt =
|
||||
/// 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 FlagsIntoPositionalArgsInt with
|
||||
|
||||
static member parse'
|
||||
(getEnvironmentVariable : string -> string)
|
||||
(args : string list)
|
||||
: FlagsIntoPositionalArgsInt
|
||||
=
|
||||
let ArgParser_errors = ResizeArray ()
|
||||
|
||||
let helpText () =
|
||||
[
|
||||
(sprintf "%s string%s%s" (sprintf "--%s" "a") "" "")
|
||||
(sprintf
|
||||
"%s int32%s%s"
|
||||
(sprintf "--%s" "grab-everything")
|
||||
" (positional args) (can be repeated)"
|
||||
"")
|
||||
]
|
||||
|> String.concat "\n"
|
||||
|
||||
let arg_1 : int 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 -> System.Int32.Parse 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_FlagsIntoPositionalArgsInt) (args : string list) =
|
||||
match args with
|
||||
| [] ->
|
||||
match state with
|
||||
| ParseState_FlagsIntoPositionalArgsInt.AwaitingKey -> ()
|
||||
| ParseState_FlagsIntoPositionalArgsInt.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 -> System.Int32.Parse x))
|
||||
| arg :: args ->
|
||||
match state with
|
||||
| ParseState_FlagsIntoPositionalArgsInt.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_FlagsIntoPositionalArgsInt.AwaitingValue arg)
|
||||
else
|
||||
let key = arg.[0 .. equals - 1]
|
||||
let value = arg.[equals + 1 ..]
|
||||
|
||||
match processKeyValue key value with
|
||||
| Ok () -> go ParseState_FlagsIntoPositionalArgsInt.AwaitingKey args
|
||||
| Error x ->
|
||||
if true then
|
||||
arg |> (fun x -> System.Int32.Parse x) |> arg_1.Add
|
||||
go ParseState_FlagsIntoPositionalArgsInt.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_FlagsIntoPositionalArgsInt.AwaitingKey args
|
||||
else
|
||||
arg |> (fun x -> System.Int32.Parse x) |> arg_1.Add
|
||||
go ParseState_FlagsIntoPositionalArgsInt.AwaitingKey args
|
||||
| ParseState_FlagsIntoPositionalArgsInt.AwaitingValue key ->
|
||||
match processKeyValue key arg with
|
||||
| Ok () -> go ParseState_FlagsIntoPositionalArgsInt.AwaitingKey args
|
||||
| Error exc ->
|
||||
if setFlagValue key then
|
||||
go ParseState_FlagsIntoPositionalArgsInt.AwaitingKey (arg :: args)
|
||||
else if true then
|
||||
key |> (fun x -> System.Int32.Parse x) |> arg_1.Add
|
||||
go ParseState_FlagsIntoPositionalArgsInt.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_FlagsIntoPositionalArgsInt.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) : FlagsIntoPositionalArgsInt =
|
||||
FlagsIntoPositionalArgsInt.parse' System.Environment.GetEnvironmentVariable args
|
||||
namespace ConsumePlugin
|
||||
|
||||
open System
|
||||
open System.IO
|
||||
open WoofWare.Myriad.Plugins
|
||||
|
||||
/// Methods to parse arguments for the type FlagsIntoPositionalArgsIntChoice
|
||||
[<AutoOpen>]
|
||||
module FlagsIntoPositionalArgsIntChoiceArgParse =
|
||||
type private ParseState_FlagsIntoPositionalArgsIntChoice =
|
||||
/// 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 FlagsIntoPositionalArgsIntChoice with
|
||||
|
||||
static member parse'
|
||||
(getEnvironmentVariable : string -> string)
|
||||
(args : string list)
|
||||
: FlagsIntoPositionalArgsIntChoice
|
||||
=
|
||||
let ArgParser_errors = ResizeArray ()
|
||||
|
||||
let helpText () =
|
||||
[
|
||||
(sprintf "%s string%s%s" (sprintf "--%s" "a") "" "")
|
||||
(sprintf
|
||||
"%s int32%s%s"
|
||||
(sprintf "--%s" "grab-everything")
|
||||
" (positional args) (can be repeated)"
|
||||
"")
|
||||
]
|
||||
|> String.concat "\n"
|
||||
|
||||
let arg_1 : Choice<int, int> 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 -> System.Int32.Parse x) |> Choice1Of2 |> 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_FlagsIntoPositionalArgsIntChoice) (args : string list) =
|
||||
match args with
|
||||
| [] ->
|
||||
match state with
|
||||
| ParseState_FlagsIntoPositionalArgsIntChoice.AwaitingKey -> ()
|
||||
| ParseState_FlagsIntoPositionalArgsIntChoice.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 -> System.Int32.Parse x) |> Seq.map Choice2Of2)
|
||||
| arg :: args ->
|
||||
match state with
|
||||
| ParseState_FlagsIntoPositionalArgsIntChoice.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_FlagsIntoPositionalArgsIntChoice.AwaitingValue arg)
|
||||
else
|
||||
let key = arg.[0 .. equals - 1]
|
||||
let value = arg.[equals + 1 ..]
|
||||
|
||||
match processKeyValue key value with
|
||||
| Ok () -> go ParseState_FlagsIntoPositionalArgsIntChoice.AwaitingKey args
|
||||
| Error x ->
|
||||
if true then
|
||||
arg |> (fun x -> System.Int32.Parse x) |> Choice1Of2 |> arg_1.Add
|
||||
go ParseState_FlagsIntoPositionalArgsIntChoice.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_FlagsIntoPositionalArgsIntChoice.AwaitingKey args
|
||||
else
|
||||
arg |> (fun x -> System.Int32.Parse x) |> Choice1Of2 |> arg_1.Add
|
||||
go ParseState_FlagsIntoPositionalArgsIntChoice.AwaitingKey args
|
||||
| ParseState_FlagsIntoPositionalArgsIntChoice.AwaitingValue key ->
|
||||
match processKeyValue key arg with
|
||||
| Ok () -> go ParseState_FlagsIntoPositionalArgsIntChoice.AwaitingKey args
|
||||
| Error exc ->
|
||||
if setFlagValue key then
|
||||
go ParseState_FlagsIntoPositionalArgsIntChoice.AwaitingKey (arg :: args)
|
||||
else if true then
|
||||
key |> (fun x -> System.Int32.Parse x) |> Choice1Of2 |> arg_1.Add
|
||||
go ParseState_FlagsIntoPositionalArgsIntChoice.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_FlagsIntoPositionalArgsIntChoice.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) : FlagsIntoPositionalArgsIntChoice =
|
||||
FlagsIntoPositionalArgsIntChoice.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 =
|
||||
@@ -3796,6 +4291,9 @@ module FlagsIntoPositionalArgs'ArgParse =
|
||||
| Error exc ->
|
||||
if setFlagValue key then
|
||||
go ParseState_FlagsIntoPositionalArgs'.AwaitingKey (arg :: args)
|
||||
else if false then
|
||||
key |> (fun x -> x) |> arg_1.Add
|
||||
go ParseState_FlagsIntoPositionalArgs'.AwaitingKey (arg :: args)
|
||||
else
|
||||
match exc with
|
||||
| None ->
|
||||
|
@@ -623,30 +623,71 @@ Required argument '--exact' received no value"""
|
||||
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" ]
|
||||
FlagsIntoPositionalArgs.parse' getEnvVar [ "--a" ; "foo" ; "--b=false" ; "--c" ; "hi" ; "--" ; "--help" ]
|
||||
|> shouldEqual
|
||||
{
|
||||
A = "foo"
|
||||
GrabEverything = [ "--b=false" ; "--c=hi" ; "--help" ]
|
||||
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" ]
|
||||
FlagsIntoPositionalArgs.parse' getEnvVar [ "--a" ; "--b=false" ; "--c" ; "hi" ; "--" ; "--help" ]
|
||||
|> shouldEqual
|
||||
{
|
||||
A = "--b=false"
|
||||
GrabEverything = [ "--c=hi" ; "--help" ]
|
||||
GrabEverything = [ "--c" ; "hi" ; "--help" ]
|
||||
}
|
||||
|
||||
[<Test>]
|
||||
let ``Can refuse to collect non-help args`` () =
|
||||
let ``Can collect non-help args into positional args with Choice`` () =
|
||||
let getEnvVar (_ : string) = failwith "do not call"
|
||||
|
||||
FlagsIntoPositionalArgsChoice.parse' getEnvVar [ "--a" ; "foo" ; "--b=false" ; "--c" ; "hi" ; "--" ; "--help" ]
|
||||
|> shouldEqual
|
||||
{
|
||||
A = "foo"
|
||||
GrabEverything =
|
||||
[
|
||||
Choice1Of2 "--b=false"
|
||||
Choice1Of2 "--c"
|
||||
Choice1Of2 "hi"
|
||||
Choice2Of2 "--help"
|
||||
]
|
||||
}
|
||||
|
||||
[<Test>]
|
||||
let ``Can collect non-help args into positional args, and we parse on the way`` () =
|
||||
let getEnvVar (_ : string) = failwith "do not call"
|
||||
|
||||
FlagsIntoPositionalArgsInt.parse' getEnvVar [ "3" ; "--a" ; "foo" ; "5" ; "--" ; "98" ]
|
||||
|> shouldEqual
|
||||
{
|
||||
A = "foo"
|
||||
GrabEverything = [ 3 ; 5 ; 98 ]
|
||||
}
|
||||
|
||||
[<Test>]
|
||||
let ``Can collect non-help args into positional args with Choice, and we parse on the way`` () =
|
||||
let getEnvVar (_ : string) = failwith "do not call"
|
||||
|
||||
FlagsIntoPositionalArgsIntChoice.parse' getEnvVar [ "3" ; "--a" ; "foo" ; "5" ; "--" ; "98" ]
|
||||
|> shouldEqual
|
||||
{
|
||||
A = "foo"
|
||||
GrabEverything = [ Choice1Of2 3 ; Choice1Of2 5 ; Choice2Of2 98 ]
|
||||
}
|
||||
|
||||
[<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" ]
|
||||
FlagsIntoPositionalArgs'.parse'
|
||||
getEnvVar
|
||||
[ "--a" ; "foo" ; "--b=false" ; "--c" ; "hi" ; "--" ; "--help" ]
|
||||
|> ignore<FlagsIntoPositionalArgs'>
|
||||
)
|
||||
|
||||
|
@@ -1019,12 +1019,12 @@ module internal ArgParserGenerator =
|
||||
recurseKey
|
||||
]
|
||||
|
||||
let notMatched =
|
||||
let posAttr =
|
||||
match leftoverArgAcc with
|
||||
| ChoicePositional.Choice a
|
||||
| ChoicePositional.Normal a -> a
|
||||
let posAttr =
|
||||
match leftoverArgAcc with
|
||||
| ChoicePositional.Choice a
|
||||
| ChoicePositional.Normal a -> a
|
||||
|
||||
let notMatched =
|
||||
let handleFailure =
|
||||
[
|
||||
SynMatchClause.create (SynPat.named "None") fail
|
||||
@@ -1113,6 +1113,8 @@ module internal ArgParserGenerator =
|
||||
let processValue =
|
||||
// During failure, we've received an optional exception message that happened when we tried to parse
|
||||
// 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 =
|
||||
[
|
||||
SynExpr.createIdent "failwithf"
|
||||
@@ -1132,6 +1134,27 @@ module internal ArgParserGenerator =
|
||||
]
|
||||
|> SynExpr.createMatch (SynExpr.createIdent "exc")
|
||||
|
||||
let onFailure =
|
||||
match posAttr with
|
||||
| None -> fail
|
||||
| Some includeFlagLike ->
|
||||
[
|
||||
SynExpr.createIdent "key"
|
||||
|> SynExpr.pipeThroughFunction leftoverArgParser
|
||||
|> fun i ->
|
||||
match leftoverArgAcc with
|
||||
| ChoicePositional.Choice _ ->
|
||||
i |> SynExpr.pipeThroughFunction (SynExpr.createIdent "Choice1Of2")
|
||||
| ChoicePositional.Normal _ -> i
|
||||
|> 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
|
||||
(SynPat.nameWithArgs "Ok" [ SynPat.unit ])
|
||||
@@ -1144,7 +1167,7 @@ module internal ArgParserGenerator =
|
||||
(SynPat.nameWithArgs "Error" [ SynPat.named "exc" ])
|
||||
(SynExpr.ifThenElse
|
||||
(SynExpr.applyFunction (SynExpr.createIdent "setFlagValue") (SynExpr.createIdent "key"))
|
||||
fail
|
||||
onFailure
|
||||
(SynExpr.createIdent "go"
|
||||
|> SynExpr.applyTo (SynExpr.createLongIdent' [ parseState ; Ident.create "AwaitingKey" ])
|
||||
|> SynExpr.applyTo (SynExpr.listCons (SynExpr.createIdent "arg") (SynExpr.createIdent "args"))))
|
||||
|
@@ -564,11 +564,12 @@ module internal CataGenerator =
|
||||
let domain =
|
||||
field.FieldName
|
||||
|> Option.map Ident.lowerFirstLetter
|
||||
|> SynType.signatureParamOfType place
|
||||
|> SynType.signatureParamOfType [] place false
|
||||
|
||||
acc |> SynType.funFromDomain domain
|
||||
)
|
||||
|> SynMemberDefn.abstractMember
|
||||
[]
|
||||
case.CataMethodIdent
|
||||
None
|
||||
arity
|
||||
|
@@ -228,14 +228,11 @@ module internal InterfaceMockGenerator =
|
||||
x.Type
|
||||
|
||||
let private constructMemberSinglePlace (tuple : TupledArg) : SynType =
|
||||
match tuple.Args |> List.rev |> List.map buildType with
|
||||
| [] -> failwith "no-arg functions not supported yet"
|
||||
| [ x ] -> x
|
||||
| last :: rest ->
|
||||
([ SynTupleTypeSegment.Type last ], rest)
|
||||
||> List.fold (fun ty nextArg -> SynTupleTypeSegment.Type nextArg :: SynTupleTypeSegment.Star range0 :: ty)
|
||||
|> fun segs -> SynType.Tuple (false, segs, range0)
|
||||
|> fun ty -> if tuple.HasParen then SynType.Paren (ty, range0) else ty
|
||||
tuple.Args
|
||||
|> List.map buildType
|
||||
|> SynType.tupleNoParen
|
||||
|> Option.defaultWith (fun () -> failwith "no-arg functions not supported yet")
|
||||
|> if tuple.HasParen then SynType.paren else id
|
||||
|
||||
let constructMember (mem : MemberInfo) : SynField =
|
||||
let inputType = mem.Args |> List.map constructMemberSinglePlace
|
||||
|
@@ -2,6 +2,7 @@ namespace WoofWare.Myriad.Plugins
|
||||
|
||||
open System
|
||||
open System.Text
|
||||
open System.Text.RegularExpressions
|
||||
open Fantomas.FCS.Syntax
|
||||
open Fantomas.FCS.Text.Range
|
||||
|
||||
@@ -9,6 +10,53 @@ open Fantomas.FCS.Text.Range
|
||||
module internal Ident =
|
||||
let inline create (s : string) = Ident (s, range0)
|
||||
|
||||
/// Fantomas bug, perhaps? "type" is not rendered as ``type``, although the ASTs are identical
|
||||
/// apart from the ranges?
|
||||
/// Awful hack: here is a function that does this sort of thing.
|
||||
let createSanitisedParamName (s : string) =
|
||||
match s with
|
||||
| "type" -> create "type'"
|
||||
| _ ->
|
||||
|
||||
let result = StringBuilder ()
|
||||
|
||||
for i = 0 to s.Length - 1 do
|
||||
if Char.IsLetter s.[i] then
|
||||
result.Append s.[i] |> ignore<StringBuilder>
|
||||
elif Char.IsNumber s.[i] then
|
||||
if result.Length > 0 then
|
||||
result.Append s.[i] |> ignore<StringBuilder>
|
||||
elif s.[i] = '_' || s.[i] = '-' then
|
||||
result.Append '_' |> ignore<StringBuilder>
|
||||
else
|
||||
failwith $"could not convert to ident: %s{s}"
|
||||
|
||||
create (result.ToString ())
|
||||
|
||||
let private alnum = Regex @"^[a-zA-Z][a-zA-Z0-9]*$"
|
||||
|
||||
let createSanitisedTypeName (s : string) =
|
||||
let result = StringBuilder ()
|
||||
let mutable capitalize = true
|
||||
|
||||
for i = 0 to s.Length - 1 do
|
||||
if Char.IsLetter s.[i] then
|
||||
if capitalize then
|
||||
result.Append (Char.ToUpperInvariant s.[i]) |> ignore<StringBuilder>
|
||||
capitalize <- false
|
||||
else
|
||||
result.Append s.[i] |> ignore<StringBuilder>
|
||||
elif Char.IsNumber s.[i] then
|
||||
if result.Length > 0 then
|
||||
result.Append s.[i] |> ignore<StringBuilder>
|
||||
elif s.[i] = '_' then
|
||||
capitalize <- true
|
||||
|
||||
if result.Length = 0 then
|
||||
failwith $"String %s{s} was not suitable as a type identifier"
|
||||
|
||||
Ident (result.ToString (), range0)
|
||||
|
||||
let lowerFirstLetter (x : Ident) : Ident =
|
||||
let result = StringBuilder x.idText.Length
|
||||
result.Append (Char.ToLowerInvariant x.idText.[0]) |> ignore
|
||||
|
@@ -6,7 +6,12 @@ open Fantomas.FCS.Text.Range
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal PreXmlDoc =
|
||||
let create (s : string) : PreXmlDoc =
|
||||
PreXmlDoc.Create ([| " " + s |], range0)
|
||||
let s = s.Split "\n"
|
||||
|
||||
for i = 0 to s.Length - 1 do
|
||||
s.[i] <- " " + s.[i]
|
||||
|
||||
PreXmlDoc.Create (s, range0)
|
||||
|
||||
let create' (s : string seq) : PreXmlDoc =
|
||||
PreXmlDoc.Create (Array.ofSeq s, range0)
|
||||
|
@@ -9,12 +9,12 @@ module internal SynArgPats =
|
||||
match caseNames.Length with
|
||||
| 0 -> SynArgPats.Pats []
|
||||
| 1 ->
|
||||
SynPat.Named (SynIdent.SynIdent (Ident.create caseNames.[0], None), false, None, range0)
|
||||
SynPat.Named (SynIdent.createS caseNames.[0], false, None, range0)
|
||||
|> List.singleton
|
||||
|> SynArgPats.Pats
|
||||
| len ->
|
||||
caseNames
|
||||
|> List.map (fun name -> SynPat.Named (SynIdent.SynIdent (Ident.create name, None), false, None, range0))
|
||||
|> List.map (fun name -> SynPat.Named (SynIdent.createS name, false, None, range0))
|
||||
|> fun t -> SynPat.Tuple (false, t, List.replicate (len - 1) range0, range0)
|
||||
|> fun t -> SynPat.Paren (t, range0)
|
||||
|> List.singleton
|
||||
|
@@ -5,32 +5,23 @@ open Fantomas.FCS.Text.Range
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal SynAttribute =
|
||||
let internal compilationRepresentation : SynAttribute =
|
||||
let inline create (typeName : SynLongIdent) (arg : SynExpr) : SynAttribute =
|
||||
{
|
||||
TypeName = SynLongIdent.createS "CompilationRepresentation"
|
||||
ArgExpr =
|
||||
[ "CompilationRepresentationFlags" ; "ModuleSuffix" ]
|
||||
|> SynExpr.createLongIdent
|
||||
|> SynExpr.paren
|
||||
TypeName = typeName
|
||||
ArgExpr = arg
|
||||
Target = None
|
||||
AppliesToGetterAndSetter = false
|
||||
Range = range0
|
||||
}
|
||||
|
||||
let internal compilationRepresentation : SynAttribute =
|
||||
[ "CompilationRepresentationFlags" ; "ModuleSuffix" ]
|
||||
|> SynExpr.createLongIdent
|
||||
|> SynExpr.paren
|
||||
|> create (SynLongIdent.createS "CompilationRepresentation")
|
||||
|
||||
let internal requireQualifiedAccess : SynAttribute =
|
||||
{
|
||||
TypeName = SynLongIdent.createS "RequireQualifiedAccess"
|
||||
ArgExpr = SynExpr.CreateConst ()
|
||||
Target = None
|
||||
AppliesToGetterAndSetter = false
|
||||
Range = range0
|
||||
}
|
||||
create (SynLongIdent.createS "RequireQualifiedAccess") (SynExpr.CreateConst ())
|
||||
|
||||
let internal autoOpen : SynAttribute =
|
||||
{
|
||||
TypeName = SynLongIdent.createS "AutoOpen"
|
||||
ArgExpr = SynExpr.CreateConst ()
|
||||
Target = None
|
||||
AppliesToGetterAndSetter = false
|
||||
Range = range0
|
||||
}
|
||||
create (SynLongIdent.createS "AutoOpen") (SynExpr.CreateConst ())
|
||||
|
10
WoofWare.Myriad.Plugins/SynExpr/SynIdent.fs
Normal file
10
WoofWare.Myriad.Plugins/SynExpr/SynIdent.fs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace WoofWare.Myriad.Plugins
|
||||
|
||||
open Fantomas.FCS.Syntax
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal SynIdent =
|
||||
let inline createI (i : Ident) : SynIdent = SynIdent.SynIdent (i, None)
|
||||
|
||||
let inline createS (i : string) : SynIdent =
|
||||
SynIdent.SynIdent (Ident.create i, None)
|
@@ -17,8 +17,8 @@ module internal SynMemberDefn =
|
||||
SynMemberFlags.MemberKind = SynMemberKind.Member
|
||||
}
|
||||
|
||||
|
||||
let abstractMember
|
||||
(attrs : SynAttribute list)
|
||||
(ident : SynIdent)
|
||||
(typars : SynTyparDecls option)
|
||||
(arity : SynValInfo)
|
||||
@@ -28,7 +28,13 @@ module internal SynMemberDefn =
|
||||
=
|
||||
let slot =
|
||||
SynValSig.SynValSig (
|
||||
[],
|
||||
attrs
|
||||
|> List.map (fun attr ->
|
||||
{
|
||||
Attributes = [ attr ]
|
||||
Range = range0
|
||||
}
|
||||
),
|
||||
ident,
|
||||
SynValTyparDecls.SynValTyparDecls (typars, true),
|
||||
returnType,
|
||||
|
@@ -267,6 +267,8 @@ module internal SynType =
|
||||
| SynType.Paren (ty, _) -> stripOptionalParen ty
|
||||
| ty -> ty
|
||||
|
||||
let inline paren (ty : SynType) : SynType = SynType.Paren (ty, range0)
|
||||
|
||||
let inline createLongIdent (ident : LongIdent) : SynType =
|
||||
SynType.LongIdent (SynLongIdent.create ident)
|
||||
|
||||
@@ -283,6 +285,17 @@ module internal SynType =
|
||||
|
||||
let inline app (name : string) (args : SynType list) : SynType = app' (named name) args
|
||||
|
||||
/// Returns None if the input list was empty.
|
||||
let inline tupleNoParen (ty : SynType list) : SynType option =
|
||||
match List.rev ty with
|
||||
| [] -> None
|
||||
| [ t ] -> Some t
|
||||
| t :: rest ->
|
||||
([ SynTupleTypeSegment.Type t ], rest)
|
||||
||> List.fold (fun ty nextArg -> SynTupleTypeSegment.Type nextArg :: SynTupleTypeSegment.Star range0 :: ty)
|
||||
|> fun segs -> SynType.Tuple (false, segs, range0)
|
||||
|> Some
|
||||
|
||||
let inline appPostfix (name : string) (arg : SynType) : SynType =
|
||||
SynType.App (named name, None, [ arg ], [], None, true, range0)
|
||||
|
||||
@@ -299,16 +312,54 @@ module internal SynType =
|
||||
}
|
||||
)
|
||||
|
||||
let inline signatureParamOfType (ty : SynType) (name : Ident option) : SynType =
|
||||
SynType.SignatureParameter ([], false, name, ty, range0)
|
||||
let inline signatureParamOfType
|
||||
(attrs : SynAttribute list)
|
||||
(ty : SynType)
|
||||
(optional : bool)
|
||||
(name : Ident option)
|
||||
: SynType
|
||||
=
|
||||
SynType.SignatureParameter (
|
||||
attrs
|
||||
|> List.map (fun attr ->
|
||||
{
|
||||
Attributes = [ attr ]
|
||||
Range = range0
|
||||
}
|
||||
),
|
||||
optional,
|
||||
name,
|
||||
ty,
|
||||
range0
|
||||
)
|
||||
|
||||
let inline var (ty : SynTypar) : SynType = SynType.Var (ty, range0)
|
||||
|
||||
let unit : SynType = named "unit"
|
||||
let obj : SynType = named "obj"
|
||||
let bool : SynType = named "bool"
|
||||
let int : SynType = named "int"
|
||||
let array (elt : SynType) : SynType = SynType.Array (1, elt, range0)
|
||||
|
||||
let list (elt : SynType) : SynType =
|
||||
SynType.App (named "list", None, [ elt ], [], None, true, range0)
|
||||
|
||||
let option (elt : SynType) : SynType =
|
||||
SynType.App (named "option", None, [ elt ], [], None, true, range0)
|
||||
|
||||
let anon : SynType = SynType.Anon range0
|
||||
|
||||
let task (elt : SynType) : SynType =
|
||||
SynType.App (
|
||||
createLongIdent' [ "System" ; "Threading" ; "Tasks" ; "Task" ],
|
||||
None,
|
||||
[ elt ],
|
||||
[],
|
||||
None,
|
||||
true,
|
||||
range0
|
||||
)
|
||||
|
||||
let string : SynType = named "string"
|
||||
|
||||
/// Given ['a1, 'a2] and 'ret, returns 'a1 -> 'a2 -> 'ret.
|
||||
|
@@ -44,7 +44,7 @@ module internal SynUnionCase =
|
||||
|
||||
SynUnionCase.SynUnionCase (
|
||||
SynAttributes.ofAttrs case.Attributes,
|
||||
SynIdent.SynIdent (case.Name, None),
|
||||
SynIdent.createI case.Name,
|
||||
SynUnionCaseKind.Fields fields,
|
||||
case.XmlDoc |> Option.defaultValue PreXmlDoc.Empty,
|
||||
case.Access,
|
||||
|
@@ -30,6 +30,7 @@
|
||||
<Compile Include="SynExpr\SynAttributes.fs" />
|
||||
<Compile Include="SynExpr\PreXmlDoc.fs" />
|
||||
<Compile Include="SynExpr\Ident.fs" />
|
||||
<Compile Include="SynExpr\SynIdent.fs" />
|
||||
<Compile Include="SynExpr\SynLongIdent.fs" />
|
||||
<Compile Include="SynExpr\SynExprLetOrUseTrivia.fs" />
|
||||
<Compile Include="SynExpr\SynArgPats.fs" />
|
||||
|
Reference in New Issue
Block a user