diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index d09bdd0c..bbe92ab8 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,6 +1,9 @@ +### 6.1.3 +* Add ParseResults.GetResult(expr, unit -> 'T) helper for Catch [#187](https://github.com/fsprojects/Argu/pull/187) + ### 6.1.2 -* Fix Mandatory arguments in nested subcommands. [#116](https://github.com/fsprojects/Argu/issues/116) -* Fix Consistent handling of numeric decimal separators using invariant culture. [#159](https://github.com/fsprojects/Argu/issues/159) +* Fix Mandatory arguments in nested subcommands. [#116](https://github.com/fsprojects/Argu/issues/116) [@chestercodes](https://github.com/chestercodes) +* Fix Consistent handling of numeric decimal separators using invariant culture. [#159](https://github.com/fsprojects/Argu/issues/159) [@stmax82](https://github.com/stmax82) ### 6.1.1 * Fix CustomAssignmentOrSpacedAttribute interop with optional fields. diff --git a/src/Argu/ParseResults.fs b/src/Argu/ParseResults.fs index fbceffec..c4ebfd8f 100644 --- a/src/Argu/ParseResults.fs +++ b/src/Argu/ParseResults.fs @@ -100,7 +100,7 @@ type ParseResults<[]'Template wh /// Returns the *last* specified parameter of given type. /// Command line parameters have precedence over AppSettings parameters. /// The name of the parameter, expressed as quotation of DU constructor. - /// Return this of no parameter of specific kind has been specified. + /// Return this if no parameter of specific kind has been specified. /// Optional source restriction: AppSettings or CommandLine. member s.GetResult ([] expr : Expr<'Template>, ?defaultValue : 'Template, ?source : ParseSource) : 'Template = match defaultValue with @@ -110,12 +110,25 @@ type ParseResults<[]'Template wh /// Returns the *last* specified parameter of given type. /// Command line parameters have precedence over AppSettings parameters. /// The name of the parameter, expressed as quotation of DU constructor. - /// Return this of no parameter of specific kind has been specified. + /// Return this if no parameter of specific kind has been specified. /// Optional source restriction: AppSettings or CommandLine. - member s.GetResult ([] expr : Expr<'Fields -> 'Template>, ?defaultValue : 'Fields , ?source : ParseSource) : 'Fields = + member s.GetResult ([] expr : Expr<'Fields -> 'Template>, ?defaultValue : 'Fields, ?source : ParseSource) : 'Fields = match defaultValue with | None -> let r = getResult source expr in r.FieldContents :?> 'Fields - | Some def -> defaultArg (s.TryGetResult expr) def + | Some def -> defaultArg (s.TryGetResult(expr, ?source = source)) def + + /// Returns the *last* specified parameter of given type. + /// Command line parameters have precedence over AppSettings parameters. + /// The name of the parameter, expressed as quotation of DU constructor. + /// Function used to default if no parameter has been specified. + /// Any resulting Exception will be trapped, and the Exception's .Message will be used as the Failure Message as per Raise and Catch. + /// Optional source restriction: AppSettings or CommandLine. + /// The error code to be returned. + /// Print usage together with error message. + member s.GetResult([] expr : Expr<'Fields -> 'Template>, defThunk : unit -> 'Fields, ?source : ParseSource, ?errorCode, ?showUsage) : 'Fields = + match s.TryGetResult(expr, ?source = source) with + | Some x -> x + | None -> s.Catch(defThunk, ?errorCode = errorCode, ?showUsage = showUsage) /// Checks if parameter of specific kind has been specified. /// The name of the parameter, expressed as quotation of DU constructor. @@ -130,7 +143,7 @@ type ParseResults<[]'Template wh /// The error message to be displayed. /// The error code to be returned. /// Print usage together with error message. - member _.Raise (msg : string, ?errorCode : ErrorCode, ?showUsage : bool) : 'T = + member _.Raise<'T>(msg : string, ?errorCode : ErrorCode, ?showUsage : bool) : 'T = let errorCode = defaultArg errorCode ErrorCode.PostProcess let showUsage = defaultArg showUsage true error (not showUsage) errorCode msg @@ -139,15 +152,15 @@ type ParseResults<[]'Template wh /// The error to be displayed. /// The error code to be returned. /// Print usage together with error message. - member r.Raise (error : exn, ?errorCode : ErrorCode, ?showUsage : bool) : 'T = - r.Raise (error.Message, ?errorCode = errorCode, ?showUsage = showUsage) + member r.Raise<'T>(error : exn, ?errorCode : ErrorCode, ?showUsage : bool) : 'T = + r.Raise(error.Message, ?errorCode = errorCode, ?showUsage = showUsage) - /// Handles any raised exception through the argument parser's exiter mechanism. Display usage optionally. + /// Handles any raised exception through the argument parser's exiter mechanism. /// The operation to be executed. /// The error code to be returned. - /// Print usage together with error message. - member r.Catch (f : unit -> 'T, ?errorCode : ErrorCode, ?showUsage : bool) : 'T = - try f () with e -> r.Raise(e.Message, ?errorCode = errorCode, ?showUsage = showUsage) + /// Print usage together with error message. Defaults to true + member r.Catch<'T>(f : unit -> 'T, ?errorCode : ErrorCode, ?showUsage : bool) : 'T = + try f () with e -> r.Raise(e, ?errorCode = errorCode, ?showUsage = showUsage) /// Returns the *last* specified parameter of given type. /// Command line parameters have precedence over AppSettings parameters. @@ -252,4 +265,4 @@ type ParseResults<[]'Template wh Unchecked.compare r.CachedAllResults.Value other.CachedAllResults.Value - | _ -> invalidArg "other" "cannot compare values of different types" \ No newline at end of file + | _ -> invalidArg "other" "cannot compare values of different types" diff --git a/tests/Argu.Tests/Tests.fs b/tests/Argu.Tests/Tests.fs index f19a316d..bbf13450 100644 --- a/tests/Argu.Tests/Tests.fs +++ b/tests/Argu.Tests/Tests.fs @@ -487,7 +487,7 @@ module ``Argu Tests Main List`` = test <@ nested.Contains <@ Force @> @> [] - let ``Main command parsing should not permit intermittent arguments`` () = + let ``Main command parsing should not permit interstitial arguments`` () = let args = [|"push" ; "origin" ; "-f" ; "master"|] raisesWith <@ parser.ParseCommandLine(args, ignoreMissing = true) @> (fun e -> <@ e.FirstLine.Contains "but was '-f'" @>) @@ -1006,4 +1006,16 @@ module ``Argu Tests Main Primitive`` = let results = parser.ParseCommandLine(args, ignoreUnrecognized = true) test <@ results.UnrecognizedCliParams = ["foobar"] @> test <@ results.Contains <@ Detach @> @> - test <@ results.GetResult <@ Main @> = "main" @> \ No newline at end of file + test <@ results.GetResult <@ Main @> = "main" @> + + [] + let ``Trap defaulting function exceptions`` () = + let results = parser.ParseCommandLine [| "--mandatory-arg" ; "true"; "command" |] + let defThunk (): string = failwith "Defaulting Failed" + raisesWith + <@ results.GetResult(Working_Directory, defThunk, showUsage = false) @> + <| fun e -> <@ e.Message = "Defaulting Failed" && e.ErrorCode = ErrorCode.PostProcess @> + raisesWith + <@ results.GetResult(Working_Directory, defThunk) @> + (fun e -> <@ e.Message.StartsWith "Defaulting Failed" && e.Message.Contains "--working-directory" @>) + \ No newline at end of file