From 1ac4d77cc93bc169bb1597311a4f4336fdacebe3 Mon Sep 17 00:00:00 2001 From: Patrick Stevens <3138005+Smaug123@users.noreply.github.com> Date: Mon, 26 Aug 2024 12:38:36 +0100 Subject: [PATCH] Arg parser post (#19) --- .../posts/2024-08-26-woofware-arg-parser.md | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 hugo/content/posts/2024-08-26-woofware-arg-parser.md diff --git a/hugo/content/posts/2024-08-26-woofware-arg-parser.md b/hugo/content/posts/2024-08-26-woofware-arg-parser.md new file mode 100644 index 0000000..d2607ab --- /dev/null +++ b/hugo/content/posts/2024-08-26-woofware-arg-parser.md @@ -0,0 +1,56 @@ +--- +lastmod: "2024-08-26T12:26:00.0000000+00:00" +author: patrick +categories: +- uncategorized +date: "2024-08-26T12:26:00.0000000+00:00" +title: WoofWare.Myriad.Plugins learns to parse args +summary: "My F# source generators have some new features, including an argument parser." +--- + +This post is about [WoofWare.Myriad.Plugins](https://github.com/Smaug123/WoofWare.Myriad), a set of [F#](https://en.wikipedia.org/wiki/F_Sharp_(programming_language)) source generators ([see it on NuGet](https://www.nuget.org/packages/WoofWare.Myriad.Plugins)). +Go and read [the README on GitHub](https://github.com/Smaug123/WoofWare.Myriad/blob/main/README.md) if you're interested. + +They are particularly intended for `PublishAot` [ahead-of-time compilation](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/) contexts, in which reflection is heavily restricted, but also for anyone who doesn't want reflection for whatever reason (e.g. "to obtain the ability to step through code in a debugger", or "for more predictable speed"). + +Since [my last post], I've implemented the following: + +* `[]` (to stamp out `toJsonNode : 'T -> JsonNode` methods) +* `[]` (to build a non-stack-overflowing [catamorphism](https://fsharpforfunandprofit.com/posts/recursive-types-and-folds/) for an algebraic data type) +* `[]` (to stamp out an argument parser). + +## `ArgParser` + +Example: + +```fsharp +[] +type Foo = + { + [] + SomeFlag : bool + A : int option + [] + B : Choice + [] + BWithEnv : Choice + C : float list + // optionally: + [] + Rest : string list // or e.g. `int list` if you want them parsed into a type too + } + static member DefaultB () = 4 +``` + +Features: + +* Optional arguments of type `'a option`. +* `[]` and `[]` to auto-populate default arguments which are not supplied. Default values are modelled as `Choice<'a, 'a>`, with `Choice1Of2` meaning "the user gave me this", and `Choice2Of2` meaning "this was populated from a default source". +* Help text with `[]`, summoned with `--help` in any position where the parser is expecting an argument, and also summoned during certain failures to parse. +* Detailed control over `TimeSpan` parsing with `[]` (and `[]` if desired). +* Accumulation of arguments supplied repeatedly: for example, `Path : FileInfo list` is populated with `--path /foo/bar --path /baz/quux`. +* Handling of `--foo=bar` and `--foo bar` equivalently. +* Booleans have arity 1 or 0, whichever leads to a successful parse: `--flag` and `--flag=true` and `--flag true` are equivalent. +* Positional arguments can appear anywhere, although if they start with a `--` then it is best to put them after a trailing `--` separator: `--named-arg=blah -- --pos-arg1 pos-arg2 --pos-arg3`. + +[my last post]: {{< ref "2023-12-31-woofware-myriad-plugins" >}}