From b4c85c8b9a6af857531c1a4e9ed43a2b376c5c44 Mon Sep 17 00:00:00 2001 From: chester Date: Fri, 15 Mar 2019 23:06:55 +0000 Subject: [PATCH 1/5] Added post processing checking of sub command mandatory flag --- src/Argu/Parsers/Common.fs | 14 ++++++++++++++ tests/Argu.Tests/Tests.fs | 18 +++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/Argu/Parsers/Common.fs b/src/Argu/Parsers/Common.fs index dd096a3a..8ff079f8 100644 --- a/src/Argu/Parsers/Common.fs +++ b/src/Argu/Parsers/Common.fs @@ -67,6 +67,20 @@ let postProcessResults (argInfo : UnionArgInfo) (ignoreMissingMandatory : bool) | _, ts' -> ts' match combined with + | [| sub |] -> + match sub.CaseInfo.ParameterInfo.Value with + | SubCommand (_, unionArg, __) -> + let errors = + unionArg.Cases.Value + |> Array.choose (fun case -> + if case.IsMandatory.Value && not ignoreMissingMandatory then + Some (error unionArg ErrorCode.PostProcess "missing parameter '%s'." case.Name.Value) + else None + ) + match errors with + | [||] -> combined + | x -> Array.head x + | _ -> combined | [||] when caseInfo.IsMandatory.Value && not ignoreMissingMandatory -> error argInfo ErrorCode.PostProcess "missing parameter '%s'." caseInfo.Name.Value | _ -> combined diff --git a/tests/Argu.Tests/Tests.fs b/tests/Argu.Tests/Tests.fs index 9644e8d6..1f85462c 100644 --- a/tests/Argu.Tests/Tests.fs +++ b/tests/Argu.Tests/Tests.fs @@ -36,6 +36,14 @@ module ``Argu Tests Main List`` = | Force -> "force changes in remote repo" | Remote _ -> "push changes to remote repository and branch" + type CheckoutArgs = + | [] Branch of string + with + interface IArgParserTemplate with + member this.Usage = + match this with + | Branch _ -> "push changes to remote repository and branch" + [] type CleanArgs = | D @@ -90,6 +98,7 @@ module ``Argu Tests Main List`` = | [] B | [] C | [] Push of ParseResults + | [] Checkout of ParseResults | [] Clean of ParseResults | [] Required of ParseResults | [] Unrecognized of ParseResults @@ -120,6 +129,7 @@ module ``Argu Tests Main List`` = | First_Parameter _ -> "parameter that has to appear at beginning of command line args." | Last_Parameter _ -> "parameter that has to appear at end of command line args." | Push _ -> "push changes" + | Checkout _ -> "checkout ref" | Clean _ -> "clean state" | Required _ -> "required subcommand" | Unrecognized _ -> "unrecognized subcommand" @@ -426,6 +436,12 @@ module ``Argu Tests Main List`` = raisesWith <@ parser.ParseCommandLine args @> (fun e -> <@ e.FirstLine.Contains "must be followed by " @>) + [] + let ``Main command parsing should fail on missing mandatory sub command parameter`` () = + let args = [|"--mandatory-arg" ; "true" ; "checkout" |] + raisesWith <@ parser.ParseCommandLine args @> + (fun e -> <@ e.FirstLine.Contains "--branch" @>) + [] let ``Main command parsing should allow trailing arguments`` () = let args = [|"push" ; "origin" ; "master" ; "-f" |] @@ -593,7 +609,7 @@ module ``Argu Tests Main List`` = [] let ``Get all subcommand parsers`` () = let subcommands = parser.GetSubCommandParsers() - test <@ subcommands.Length = 4 @> + test <@ subcommands.Length = 5 @> test <@ subcommands |> List.forall (fun sc -> sc.IsSubCommandParser) @> [] From 37c0d5471bb8fe03e750344d0155f9d531fefa04 Mon Sep 17 00:00:00 2001 From: chester Date: Wed, 27 Mar 2019 22:59:13 +0000 Subject: [PATCH 2/5] Added recursive sub command checking --- src/Argu/Parsers/Common.fs | 26 ++++++++++++++------------ tests/Argu.Tests/Tests.fs | 24 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/Argu/Parsers/Common.fs b/src/Argu/Parsers/Common.fs index 8ff079f8..5414c886 100644 --- a/src/Argu/Parsers/Common.fs +++ b/src/Argu/Parsers/Common.fs @@ -66,21 +66,23 @@ let postProcessResults (argInfo : UnionArgInfo) (ignoreMissingMandatory : bool) | Choice1Of2 ts, ts' when caseInfo.GatherAllSources.Value -> Array.append ts ts' | _, ts' -> ts' - match combined with - | [| sub |] -> - match sub.CaseInfo.ParameterInfo.Value with + let rec searchSub caseInfo = + match caseInfo.ParameterInfo.Value with | SubCommand (_, unionArg, __) -> - let errors = - unionArg.Cases.Value - |> Array.choose (fun case -> + unionArg.Cases.Value + |> Array.collect (fun case -> if case.IsMandatory.Value && not ignoreMissingMandatory then - Some (error unionArg ErrorCode.PostProcess "missing parameter '%s'." case.Name.Value) - else None - ) - match errors with - | [||] -> combined - | x -> Array.head x + [|(error unionArg ErrorCode.PostProcess "missing parameter '%s'." case.Name.Value)|] + else + searchSub case) + | _ -> [||] + + match combined with + | [| sub |] -> + match searchSub (sub.CaseInfo) with + | [|head::_|] -> head | _ -> combined + | [||] when caseInfo.IsMandatory.Value && not ignoreMissingMandatory -> error argInfo ErrorCode.PostProcess "missing parameter '%s'." caseInfo.Name.Value | _ -> combined diff --git a/tests/Argu.Tests/Tests.fs b/tests/Argu.Tests/Tests.fs index 1f85462c..19dea584 100644 --- a/tests/Argu.Tests/Tests.fs +++ b/tests/Argu.Tests/Tests.fs @@ -36,6 +36,22 @@ module ``Argu Tests Main List`` = | Force -> "force changes in remote repo" | Remote _ -> "push changes to remote repository and branch" + type NewArgs = + | [] Name of string + with + interface IArgParserTemplate with + member this.Usage = + match this with + | Name _ -> "New name" + + type TagArgs = + | New of ParseResults + with + interface IArgParserTemplate with + member this.Usage = + match this with + | New _ -> "New tag" + type CheckoutArgs = | [] Branch of string with @@ -99,6 +115,7 @@ module ``Argu Tests Main List`` = | [] C | [] Push of ParseResults | [] Checkout of ParseResults + | [] Tag of ParseResults | [] Clean of ParseResults | [] Required of ParseResults | [] Unrecognized of ParseResults @@ -130,6 +147,7 @@ module ``Argu Tests Main List`` = | Last_Parameter _ -> "parameter that has to appear at end of command line args." | Push _ -> "push changes" | Checkout _ -> "checkout ref" + | Tag _ -> "tag" | Clean _ -> "clean state" | Required _ -> "required subcommand" | Unrecognized _ -> "unrecognized subcommand" @@ -442,6 +460,12 @@ module ``Argu Tests Main List`` = raisesWith <@ parser.ParseCommandLine args @> (fun e -> <@ e.FirstLine.Contains "--branch" @>) + [] + let ``Main command parsing should fail on missing mandatory sub command's sub command parameter`` () = + let args = [|"--mandatory-arg"; "true"; "tag"; "--new"; |] + raisesWith <@ parser.ParseCommandLine args @> + (fun e -> <@ e.FirstLine.Contains "--name" @>) + [] let ``Main command parsing should allow trailing arguments`` () = let args = [|"push" ; "origin" ; "master" ; "-f" |] From 9c1bcf3e6e7795deb60065b4aaeb0d73df14a6ab Mon Sep 17 00:00:00 2001 From: chester Date: Wed, 27 Mar 2019 23:01:53 +0000 Subject: [PATCH 3/5] Fixed sub command test --- tests/Argu.Tests/Tests.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Argu.Tests/Tests.fs b/tests/Argu.Tests/Tests.fs index 19dea584..f1a5dafa 100644 --- a/tests/Argu.Tests/Tests.fs +++ b/tests/Argu.Tests/Tests.fs @@ -633,7 +633,7 @@ module ``Argu Tests Main List`` = [] let ``Get all subcommand parsers`` () = let subcommands = parser.GetSubCommandParsers() - test <@ subcommands.Length = 5 @> + test <@ subcommands.Length = 6 @> test <@ subcommands |> List.forall (fun sc -> sc.IsSubCommandParser) @> [] From 3096a54da086176a4384a867211bf285349ad30f Mon Sep 17 00:00:00 2001 From: chester Date: Sat, 28 Nov 2020 12:52:21 +0000 Subject: [PATCH 4/5] Simplify the searchSub function --- src/Argu/Parsers/Common.fs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Argu/Parsers/Common.fs b/src/Argu/Parsers/Common.fs index 5414c886..ffe11410 100644 --- a/src/Argu/Parsers/Common.fs +++ b/src/Argu/Parsers/Common.fs @@ -69,17 +69,18 @@ let postProcessResults (argInfo : UnionArgInfo) (ignoreMissingMandatory : bool) let rec searchSub caseInfo = match caseInfo.ParameterInfo.Value with | SubCommand (_, unionArg, __) -> - unionArg.Cases.Value - |> Array.collect (fun case -> + match unionArg.Cases.Value with + | [| case |] -> if case.IsMandatory.Value && not ignoreMissingMandatory then [|(error unionArg ErrorCode.PostProcess "missing parameter '%s'." case.Name.Value)|] else - searchSub case) + searchSub case + | _ -> [||] | _ -> [||] match combined with | [| sub |] -> - match searchSub (sub.CaseInfo) with + match searchSub sub.CaseInfo with | [|head::_|] -> head | _ -> combined From 94e4d2570d7bcbb3294b62a21129ecf9dff0a170 Mon Sep 17 00:00:00 2001 From: chester Date: Sun, 6 Dec 2020 12:06:42 +0000 Subject: [PATCH 5/5] Changed function to return option --- src/Argu/Parsers/Common.fs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Argu/Parsers/Common.fs b/src/Argu/Parsers/Common.fs index ffe11410..541282e5 100644 --- a/src/Argu/Parsers/Common.fs +++ b/src/Argu/Parsers/Common.fs @@ -66,22 +66,22 @@ let postProcessResults (argInfo : UnionArgInfo) (ignoreMissingMandatory : bool) | Choice1Of2 ts, ts' when caseInfo.GatherAllSources.Value -> Array.append ts ts' | _, ts' -> ts' - let rec searchSub caseInfo = + let rec searchCaseInfoForError caseInfo = match caseInfo.ParameterInfo.Value with | SubCommand (_, unionArg, __) -> match unionArg.Cases.Value with | [| case |] -> if case.IsMandatory.Value && not ignoreMissingMandatory then - [|(error unionArg ErrorCode.PostProcess "missing parameter '%s'." case.Name.Value)|] + Some (error unionArg ErrorCode.PostProcess "missing parameter '%s'." case.Name.Value) else - searchSub case - | _ -> [||] - | _ -> [||] + searchCaseInfoForError case + | _ -> None + | _ -> None match combined with | [| sub |] -> - match searchSub sub.CaseInfo with - | [|head::_|] -> head + match searchCaseInfoForError sub.CaseInfo with + | Some error -> error | _ -> combined | [||] when caseInfo.IsMandatory.Value && not ignoreMissingMandatory ->