You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+4Lines changed: 4 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,5 +1,9 @@
1
1
Notable changes are recorded here.
2
2
3
+
# WoofWare.Myriad.Plugins 10.2.1
4
+
5
+
The `ArgParserGenerator` now ships with (limited) discriminated-union support: you can specify mutually exclusive sets of args and the parser will select the correct set.
6
+
3
7
# WoofWare.Myriad.Plugins 10.1.1
4
8
5
9
Fixes a number of bugs in the `ArgParserGenerator` by extracting the "untyped" logic into a standalone module.
BWithEnv = Choice2Of2 100 // whatever the value of $MY_ENV_VAR was, or a failed parse
228
+
DryRun = DryRunMode.Wet
229
+
AnimalPart = AnimalArgs.Fowl { Species = "pheasant" }
230
+
}
231
+
232
+
{
233
+
SomeFlag = false
234
+
A = None
235
+
B = Choice2Of2 4
236
+
BWithEnv = Choice1Of2 8
237
+
DryRun = DryRunMode.Wet
238
+
AnimalPart = AnimalArgs.Fish { Fins = 39 }
239
+
}
240
+
```
241
+
197
242
Default arguments are handled as `Choice<'a, 'a>`:
198
243
you get a `Choice1Of2` if the user provided the input, or a `Choice2Of2` if the parser filled in your specified default value.
199
244
200
245
You can control `TimeSpan` and friends with the `[<InvariantCulture>]` and `[<ParseExact @"hh\:mm\:ss">]` attributes.
201
246
202
247
You can generate extension methods for the type, instead of a module with the type's name, using `[<ArgParser (* isExtensionMethod = *) true>]`.
203
248
249
+
You can collect leftover args as positional args, with `[<PositionalArgs>]`; this respects a trailing `--` so that you can specify positional args which look like flags.
250
+
The positional args feature is currently *not* supported simultaneously with DUs, though: the generator will fail at build time.
251
+
204
252
If `--help` appears in a position where the parser is expecting a key (e.g. in the first position, or after a `--foo=bar`), the parser fails with help text.
205
253
The parser also makes a limited effort to supply help text when encountering an invalid parse.
206
254
255
+
Records compose: if your record contains other records which are visible to the source generator (that is, they're in the same file as the main args type), the fields of *those* records will also be included in the command line, as if you'd specified them inline in the top-level record.
256
+
257
+
Discriminated unions compose with each other and with records, hopefully as you would expect: the fields specified by the record of a DU field must be mutually satisified, or the parse will fail to select that DU field.
258
+
207
259
### What's the point?
208
260
209
261
I got fed up of waiting for us to find time to rewrite the in-house one at work.
210
-
That one has a bunch of nice compositional properties, which my version lacks:
211
-
I can basically only deal with primitive types, and e.g. you can't stack records and discriminated unions inside each other.
212
-
213
-
But I *do* want an F#-native argument parser suitable for AOT-compilation.
262
+
That one has slightly nicer usability properties, because it operates by reflection so it has fuller information at runtime.
263
+
(But I *do* want an F#-native argument parser suitable for AOT-compilation, so perhaps the limitations of my one here are inherent.)
214
264
215
265
Why not [Argu](https://fsprojects.github.io/Argu/)?
216
266
Answer: I got annoyed with having to construct my records by hand even after Argu returned and said the parsing was all "done".
@@ -221,9 +271,10 @@ This is very bare-bones, but do raise GitHub issues if you like (or if you find
221
271
222
272
* Help is signalled by throwing an exception, so you'll get an unsightly stack trace and a nonzero exit code.
223
273
* Help doesn't take into account any arguments the user has entered. Ideally you'd get contextual information like an identification of which args the user has supplied at the point where the parse failed or help was requested.
224
-
* I don't handle very many types, and in particular a real arg parser would handle DUs and records with nesting.
274
+
* I don't handle very many types at the leaves. You may find yourself needing to write wrapper types to contain the leaf values, if you want to parse them correctly.
225
275
* I don't try very hard to find a valid parse. It may well be possible to find a case where I fail to parse despite there existing a valid parse.
226
276
* There's no subcommand support (you'll have to do that yourself).
277
+
* Discriminated unions can't currently be specified in a type that contains positional args. This is a limitation I hope to relax soon.
227
278
228
279
It should work fine if you just want to compose a few primitive types, though.
0 commit comments