Safe list handling for ActionInputs - #38
Conversation
JordanMarr
left a comment
There was a problem hiding this comment.
Thanks for this! I dug into it and it's more valuable than the title suggests: on main, F# list inputs don't work at all (omitted → NullReferenceException; supplied → S.CL's "FSharpList cannot be created without a custom binder"). With this branch, omitted gives [], order is preserved, and int list parses. So I'd like to get it in. A few changes first:
1. Route conversion failures through AddError.
A bad token currently escapes as an exception instead of a parse error, e.g. option<int list> "-n" with -n abc throws FormatException. Catch the conversion failure and call result.AddError(...) so the user gets S.CL's normal error output and exit code.
2. Reuse MaybeParser.parseTokenValue for element conversion.
Convert.ChangeType alone can't handle FileInfo / DirectoryInfo / Uri, so option<FileInfo list> throws InvalidCastException. Going through MaybeParser (the same path tryParse/customParser use) keeps behavior consistent across the library. Building the closed List.ofArray method once when the option is created, rather than on every parse, would be nice too.
3. Dedupe the two protect overloads.
The Option<'T> and Argument<'T> bodies are identical. Build the parser and default-value factory once in a shared helper and have each overload just assign them. The typ.GetElementType() branch is also unreachable since the caller already guards on list<_>.
4. Leave Input.option where it was.
It moved from the top of the module to below recursive, which makes the diff noisy without changing anything. SafeInputLists is defined above the module, so the original position works.
5. A few more tests.
The current test sets arity Arity.ZeroOrMore explicitly, so the new default arity isn't exercised. Cases I'd add: option omitted (no explicit arity) → []; int list with values; bad token → non-zero exit and no exception; argument<string list> with values and omitted.
Also, #37 just merged, so you'll need to rebase — Tests.fsproj will conflict on the <Compile Include> line.
Once these are in I'll merge. Thanks again!
…typed value (acceptOnlyFromChoices, acceptOnlyFromChoicesWith, acceptManyFromChoices, acceptManyFromChoicesWith, acceptOnlyFromChoicesIgnoreCase, acceptManyFromChoicesIgnoreCase)
…g to typed value Added tests; and bullet points in readme.md Tests demonstrate failing, correct, and undefined behaviours.
- README example was missing the option name argument - Drop the "tryParse overrides mapFromAmong" note, remarks, and the test asserting that undefined behaviour - Reword doc comments with inline examples Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PsmkZPCobsju7AauvVH8du
1. Conversion errors route through AddError 2. List protection routes through SRTP overloads 3. Tests cover option(int list), option(string list), argument(int list), argument(string list)
We don't have the element type as typar to dispatch through |
No more errors on empty lists or requirements for custom binders by default.