From 45b20e4ecd9e32bafea7c101e672909b9eec4268 Mon Sep 17 00:00:00 2001 From: umarcor Date: Mon, 28 Mar 2022 01:34:40 +0200 Subject: [PATCH 1/7] deprecate ExactValidArgs in favour of MatchAll(OnlyValidArgs, ...) --- args.go | 20 ++++++++------------ args_test.go | 38 ++++++++++++++++++++------------------ user_guide.md | 39 ++++++++++++++++++++++++++++----------- 3 files changed, 56 insertions(+), 41 deletions(-) diff --git a/args.go b/args.go index 20a022b30..8c0f1142c 100644 --- a/args.go +++ b/args.go @@ -86,18 +86,6 @@ func ExactArgs(n int) PositionalArgs { } } -// ExactValidArgs returns an error if -// there are not exactly N positional args OR -// there are any positional args that are not in the `ValidArgs` field of `Command` -func ExactValidArgs(n int) PositionalArgs { - return func(cmd *Command, args []string) error { - if err := ExactArgs(n)(cmd, args); err != nil { - return err - } - return OnlyValidArgs(cmd, args) - } -} - // RangeArgs returns an error if the number of args is not within the expected range. func RangeArgs(min int, max int) PositionalArgs { return func(cmd *Command, args []string) error { @@ -119,3 +107,11 @@ func MatchAll(pargs ...PositionalArgs) PositionalArgs { return nil } } + +// ExactValidArgs returns an error if there are not exactly N positional args OR +// there are any positional args that are not in the `ValidArgs` field of `Command` +// +// Deprecated: use MatchAll(OnlyValidArgs, ExactArgs(n)) instead +func ExactValidArgs(n int) PositionalArgs { + return MatchAll(OnlyValidArgs, ExactArgs(n)) +} diff --git a/args_test.go b/args_test.go index 6bd41c8fd..29a9ed421 100644 --- a/args_test.go +++ b/args_test.go @@ -159,24 +159,6 @@ func TestExactArgsWithInvalidCount(t *testing.T) { exactArgsWithInvalidCount(err, t) } -func TestExactValidArgs(t *testing.T) { - c := getCommand(ExactValidArgs(3), true) - output, err := executeCommand(c, "three", "one", "two") - expectSuccess(output, err, t) -} - -func TestExactValidArgsWithInvalidCount(t *testing.T) { - c := getCommand(ExactValidArgs(2), false) - _, err := executeCommand(c, "three", "one", "two") - exactArgsWithInvalidCount(err, t) -} - -func TestExactValidArgsWithInvalidArgs(t *testing.T) { - c := getCommand(ExactValidArgs(3), true) - _, err := executeCommand(c, "three", "a", "two") - validWithInvalidArgs(err, t) -} - func TestRangeArgs(t *testing.T) { c := getCommand(RangeArgs(2, 4), false) output, err := executeCommand(c, "a", "b", "c") @@ -293,6 +275,26 @@ func TestMatchAll(t *testing.T) { } } +// DEPRECATED + +func TestExactValidArgs(t *testing.T) { + c := getCommand(ExactValidArgs(3), true) + output, err := executeCommand(c, "three", "one", "two") + expectSuccess(output, err, t) +} + +func TestExactValidArgsWithInvalidCount(t *testing.T) { + c := getCommand(ExactValidArgs(2), false) + _, err := executeCommand(c, "three", "one", "two") + exactArgsWithInvalidCount(err, t) +} + +func TestExactValidArgsWithInvalidArgs(t *testing.T) { + c := getCommand(ExactValidArgs(3), true) + _, err := executeCommand(c, "three", "a", "two") + validWithInvalidArgs(err, t) +} + // This test make sure we keep backwards-compatibility with respect // to the legacyArgs() function. // It makes sure the root command accepts arguments if it does not have diff --git a/user_guide.md b/user_guide.md index 5a7acf88e..06d38625a 100644 --- a/user_guide.md +++ b/user_guide.md @@ -331,17 +331,34 @@ If `Args` is undefined or `nil`, it defaults to `ArbitraryArgs`. The following validators are built in: -- `NoArgs` - the command will report an error if there are any positional args. -- `ArbitraryArgs` - the command will accept any args. -- `OnlyValidArgs` - the command will report an error if there are any positional args that are not in the `ValidArgs` field of `Command`. -- `MinimumNArgs(int)` - the command will report an error if there are not at least N positional args. -- `MaximumNArgs(int)` - the command will report an error if there are more than N positional args. -- `ExactArgs(int)` - the command will report an error if there are not exactly N positional args. -- `ExactValidArgs(int)` - the command will report an error if there are not exactly N positional args OR if there are any positional args that are not in the `ValidArgs` field of `Command` -- `RangeArgs(min, max)` - the command will report an error if the number of args is not between the minimum and maximum number of expected args. -- `MatchAll(pargs ...PositionalArgs)` - enables combining existing checks with arbitrary other checks (e.g. you want to check the ExactArgs length along with other qualities). - -An example of setting the custom validator: +- Number of arguments: + - `NoArgs` - report an error if there are any positional args. + - `ArbitraryArgs` - accept any number of args. + - `MinimumNArgs(int)` - report an error if less than N positional args are provided. + - `MaximumNArgs(int)` - report an error if more than N positional args are provided. + - `ExactArgs(int)` - report an error if there are not exactly N positional args. + - `RangeArgs(min, max)` - report an error if the number of args is not between `min` and `max`. +- Content of the arguments: + - `OnlyValidArgs` - report an error if there are any positional args that are not in the `ValidArgs` field of type + `[]string` defined in `Command`. + +Moreover, `MatchAll(pargs ...PositionalArgs)` enables combining existing checks with arbitrary other checks. +For instance, if you want to report an error if there are not exactly N positional args OR if there are any positional +args that are not in the `ValidArgs` field of `Command`, you can call `MatchAll` on `ExactArgs` and `OnlyValidArgs`, as +shown below: + +```go +var cmd = &cobra.Command{ + Short: "hello", + Args: MatchAll(OnlyValidArgs, ExactArgs(2)), + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Hello, World!") + }, +} +``` + +It is possible to set any custom validator that satisfies `func(cmd *cobra.Command, args []string) error`. +For example: ```go var cmd = &cobra.Command{ From ec474022ff8c4be91265a86b2c3e52bbcb883cf1 Mon Sep 17 00:00:00 2001 From: umarcor Date: Mon, 18 Mar 2019 23:32:12 +0100 Subject: [PATCH 2/7] test combinations of args validators --- args.go | 4 +- args_test.go | 228 +++++++++++++++++++++++++++++++++++++++++++++++--- user_guide.md | 19 +++-- 3 files changed, 227 insertions(+), 24 deletions(-) diff --git a/args.go b/args.go index 8c0f1142c..7c4cc1b50 100644 --- a/args.go +++ b/args.go @@ -32,7 +32,8 @@ func NoArgs(cmd *Command, args []string) error { return nil } -// OnlyValidArgs returns an error if any args are not in the list of ValidArgs. +// OnlyValidArgs returns an error if there are any positional args that are not in +// the `ValidArgs` field of `Command` func OnlyValidArgs(cmd *Command, args []string) error { if len(cmd.ValidArgs) > 0 { // Remove any description that may be included in ValidArgs. @@ -41,7 +42,6 @@ func OnlyValidArgs(cmd *Command, args []string) error { for _, v := range cmd.ValidArgs { validArgs = append(validArgs, strings.Split(v, "\t")[0]) } - for _, v := range args { if !stringInSlice(v, validArgs) { return fmt.Errorf("invalid argument %q for %q%s", v, cmd.CommandPath(), cmd.findSuggestions(args[0])) diff --git a/args_test.go b/args_test.go index 29a9ed421..9d26a41b2 100644 --- a/args_test.go +++ b/args_test.go @@ -27,7 +27,7 @@ func expectSuccess(output string, err error, t *testing.T) { } } -func validWithInvalidArgs(err error, t *testing.T) { +func validOnlyWithInvalidArgs(err error, t *testing.T) { if err == nil { t.Fatal("Expected an error") } @@ -43,7 +43,7 @@ func noArgsWithArgs(err error, t *testing.T) { t.Fatal("Expected an error") } got := err.Error() - expected := `unknown command "illegal" for "c"` + expected := `unknown command "one" for "c"` if got != expected { t.Errorf("Expected: %q, got: %q", expected, got) } @@ -93,84 +93,280 @@ func rangeArgsWithInvalidCount(err error, t *testing.T) { } } +// NoArgs + func TestNoArgs(t *testing.T) { c := getCommand(NoArgs, false) output, err := executeCommand(c) expectSuccess(output, err, t) } -func TestNoArgsWithArgs(t *testing.T) { +func TestNoArgs_WithArgs(t *testing.T) { c := getCommand(NoArgs, false) - _, err := executeCommand(c, "illegal") + _, err := executeCommand(c, "one") + noArgsWithArgs(err, t) +} + +func TestNoArgs_WithValid_WithArgs(t *testing.T) { + c := getCommand(NoArgs, true) + _, err := executeCommand(c, "one") + noArgsWithArgs(err, t) +} + +func TestNoArgs_WithValid_WithInvalidArgs(t *testing.T) { + c := getCommand(NoArgs, true) + _, err := executeCommand(c, "one") noArgsWithArgs(err, t) } +func TestNoArgs_WithValidOnly_WithInvalidArgs(t *testing.T) { + c := getCommand(MatchAll(OnlyValidArgs, NoArgs), true) + _, err := executeCommand(c, "a") + validOnlyWithInvalidArgs(err, t) +} + +// OnlyValidArgs + func TestOnlyValidArgs(t *testing.T) { c := getCommand(OnlyValidArgs, true) output, err := executeCommand(c, "one", "two") expectSuccess(output, err, t) } -func TestOnlyValidArgsWithInvalidArgs(t *testing.T) { +func TestOnlyValidArgs_WithInvalidArgs(t *testing.T) { c := getCommand(OnlyValidArgs, true) _, err := executeCommand(c, "a") - validWithInvalidArgs(err, t) + validOnlyWithInvalidArgs(err, t) } +// ArbitraryArgs + func TestArbitraryArgs(t *testing.T) { c := getCommand(ArbitraryArgs, false) output, err := executeCommand(c, "a", "b") expectSuccess(output, err, t) } +func TestArbitraryArgs_WithValid(t *testing.T) { + c := getCommand(ArbitraryArgs, true) + output, err := executeCommand(c, "one", "two") + expectSuccess(output, err, t) +} + +func TestArbitraryArgs_WithValid_WithInvalidArgs(t *testing.T) { + c := getCommand(ArbitraryArgs, true) + output, err := executeCommand(c, "a") + expectSuccess(output, err, t) +} + +func TestArbitraryArgs_WithValidOnly_WithInvalidArgs(t *testing.T) { + c := getCommand(MatchAll(OnlyValidArgs, ArbitraryArgs), true) + _, err := executeCommand(c, "a") + validOnlyWithInvalidArgs(err, t) +} + +// MinimumNArgs + func TestMinimumNArgs(t *testing.T) { c := getCommand(MinimumNArgs(2), false) output, err := executeCommand(c, "a", "b", "c") expectSuccess(output, err, t) } -func TestMinimumNArgsWithLessArgs(t *testing.T) { +func TestMinimumNArgs_WithValid(t *testing.T) { + c := getCommand(MinimumNArgs(2), true) + output, err := executeCommand(c, "one", "three") + expectSuccess(output, err, t) +} + +func TestMinimumNArgs_WithValid__WithInvalidArgs(t *testing.T) { + c := getCommand(MinimumNArgs(2), true) + output, err := executeCommand(c, "a", "b") + expectSuccess(output, err, t) +} + +func TestMinimumNArgs_WithValidOnly_WithInvalidArgs(t *testing.T) { + c := getCommand(MatchAll(OnlyValidArgs, MinimumNArgs(2)), true) + _, err := executeCommand(c, "a", "b") + validOnlyWithInvalidArgs(err, t) +} + +func TestMinimumNArgs_WithLessArgs(t *testing.T) { c := getCommand(MinimumNArgs(2), false) _, err := executeCommand(c, "a") minimumNArgsWithLessArgs(err, t) } +func TestMinimumNArgs_WithLessArgs_WithValid(t *testing.T) { + c := getCommand(MinimumNArgs(2), true) + _, err := executeCommand(c, "one") + minimumNArgsWithLessArgs(err, t) +} + +func TestMinimumNArgs_WithLessArgs_WithValid_WithInvalidArgs(t *testing.T) { + c := getCommand(MinimumNArgs(2), true) + _, err := executeCommand(c, "a") + minimumNArgsWithLessArgs(err, t) +} + +func TestMinimumNArgs_WithLessArgs_WithValidOnly_WithInvalidArgs(t *testing.T) { + c := getCommand(MatchAll(OnlyValidArgs, MinimumNArgs(2)), true) + _, err := executeCommand(c, "a") + validOnlyWithInvalidArgs(err, t) +} + +// MaximumNArgs + func TestMaximumNArgs(t *testing.T) { c := getCommand(MaximumNArgs(3), false) output, err := executeCommand(c, "a", "b") expectSuccess(output, err, t) } -func TestMaximumNArgsWithMoreArgs(t *testing.T) { +func TestMaximumNArgs_WithValid(t *testing.T) { + c := getCommand(MaximumNArgs(2), true) + output, err := executeCommand(c, "one", "three") + expectSuccess(output, err, t) +} + +func TestMaximumNArgs_WithValid_WithInvalidArgs(t *testing.T) { + c := getCommand(MaximumNArgs(2), true) + output, err := executeCommand(c, "a", "b") + expectSuccess(output, err, t) +} + +func TestMaximumNArgs_WithValidOnly_WithInvalidArgs(t *testing.T) { + c := getCommand(MatchAll(OnlyValidArgs, MaximumNArgs(2)), true) + _, err := executeCommand(c, "a", "b") + validOnlyWithInvalidArgs(err, t) +} + +func TestMaximumNArgs_WithMoreArgs(t *testing.T) { c := getCommand(MaximumNArgs(2), false) _, err := executeCommand(c, "a", "b", "c") maximumNArgsWithMoreArgs(err, t) } +func TestMaximumNArgs_WithMoreArgs_WithValid(t *testing.T) { + c := getCommand(MaximumNArgs(2), true) + _, err := executeCommand(c, "one", "three", "two") + maximumNArgsWithMoreArgs(err, t) +} + +func TestMaximumNArgs_WithMoreArgs_WithValid_WithInvalidArgs(t *testing.T) { + c := getCommand(MaximumNArgs(2), true) + _, err := executeCommand(c, "a", "b", "c") + maximumNArgsWithMoreArgs(err, t) +} + +func TestMaximumNArgs_WithMoreArgs_WithValidOnly_WithInvalidArgs(t *testing.T) { + c := getCommand(MatchAll(OnlyValidArgs, MaximumNArgs(2)), true) + _, err := executeCommand(c, "a", "b", "c") + validOnlyWithInvalidArgs(err, t) +} + +// ExactArgs + func TestExactArgs(t *testing.T) { c := getCommand(ExactArgs(3), false) output, err := executeCommand(c, "a", "b", "c") expectSuccess(output, err, t) } -func TestExactArgsWithInvalidCount(t *testing.T) { +func TestExactArgs_WithValid(t *testing.T) { + c := getCommand(ExactArgs(3), true) + output, err := executeCommand(c, "three", "one", "two") + expectSuccess(output, err, t) +} + +func TestExactArgs_WithValid_WithInvalidArgs(t *testing.T) { + c := getCommand(ExactArgs(3), true) + output, err := executeCommand(c, "three", "a", "two") + expectSuccess(output, err, t) +} + +func TestExactArgs_WithValidOnly_WithInvalidArgs(t *testing.T) { + c := getCommand(MatchAll(OnlyValidArgs, ExactArgs(3)), true) + _, err := executeCommand(c, "three", "a", "two") + validOnlyWithInvalidArgs(err, t) +} + +func TestExactArgs_WithInvalidCount(t *testing.T) { c := getCommand(ExactArgs(2), false) _, err := executeCommand(c, "a", "b", "c") exactArgsWithInvalidCount(err, t) } +func TestExactArgs_WithInvalidCount_WithValid(t *testing.T) { + c := getCommand(ExactArgs(2), true) + _, err := executeCommand(c, "three", "one", "two") + exactArgsWithInvalidCount(err, t) +} + +func TestExactArgs_WithInvalidCount_WithValid_WithInvalidArgs(t *testing.T) { + c := getCommand(ExactArgs(2), true) + _, err := executeCommand(c, "three", "a", "two") + exactArgsWithInvalidCount(err, t) +} + +func TestExactArgs_WithInvalidCount_WithValidOnly_WithInvalidArgs(t *testing.T) { + c := getCommand(MatchAll(OnlyValidArgs, ExactArgs(2)), true) + _, err := executeCommand(c, "three", "a", "two") + validOnlyWithInvalidArgs(err, t) +} + +// RangeArgs + func TestRangeArgs(t *testing.T) { c := getCommand(RangeArgs(2, 4), false) output, err := executeCommand(c, "a", "b", "c") expectSuccess(output, err, t) } -func TestRangeArgsWithInvalidCount(t *testing.T) { +func TestRangeArgs_WithValid(t *testing.T) { + c := getCommand(RangeArgs(2, 4), true) + output, err := executeCommand(c, "three", "one", "two") + expectSuccess(output, err, t) +} + +func TestRangeArgs_WithValid_WithInvalidArgs(t *testing.T) { + c := getCommand(RangeArgs(2, 4), true) + output, err := executeCommand(c, "three", "a", "two") + expectSuccess(output, err, t) +} + +func TestRangeArgs_WithValidOnly_WithInvalidArgs(t *testing.T) { + c := getCommand(MatchAll(OnlyValidArgs, RangeArgs(2, 4)), true) + _, err := executeCommand(c, "three", "a", "two") + validOnlyWithInvalidArgs(err, t) +} + +func TestRangeArgs_WithInvalidCount(t *testing.T) { c := getCommand(RangeArgs(2, 4), false) _, err := executeCommand(c, "a") rangeArgsWithInvalidCount(err, t) } +func TestRangeArgs_WithInvalidCount_WithValid(t *testing.T) { + c := getCommand(RangeArgs(2, 4), true) + _, err := executeCommand(c, "two") + rangeArgsWithInvalidCount(err, t) +} + +func TestRangeArgs_WithInvalidCount_WithValid_WithInvalidArgs(t *testing.T) { + c := getCommand(RangeArgs(2, 4), true) + _, err := executeCommand(c, "a") + rangeArgsWithInvalidCount(err, t) +} + +func TestRangeArgs_WithInvalidCount_WithValidOnly_WithInvalidArgs(t *testing.T) { + c := getCommand(MatchAll(OnlyValidArgs, RangeArgs(2, 4)), true) + _, err := executeCommand(c, "a") + validOnlyWithInvalidArgs(err, t) +} + +// Takes(No)Args + func TestRootTakesNoArgs(t *testing.T) { rootCmd := &Command{Use: "root", Run: emptyRun} childCmd := &Command{Use: "child", Run: emptyRun} @@ -283,16 +479,22 @@ func TestExactValidArgs(t *testing.T) { expectSuccess(output, err, t) } -func TestExactValidArgsWithInvalidCount(t *testing.T) { +func TestExactValidArgs_WithInvalidCount(t *testing.T) { c := getCommand(ExactValidArgs(2), false) _, err := executeCommand(c, "three", "one", "two") exactArgsWithInvalidCount(err, t) } -func TestExactValidArgsWithInvalidArgs(t *testing.T) { +func TestExactValidArgs_WithInvalidCount_WithInvalidArgs(t *testing.T) { c := getCommand(ExactValidArgs(3), true) _, err := executeCommand(c, "three", "a", "two") - validWithInvalidArgs(err, t) + validOnlyWithInvalidArgs(err, t) +} + +func TestExactValidArgs_WithInvalidArgs(t *testing.T) { + c := getCommand(ExactValidArgs(3), true) + _, err := executeCommand(c, "three", "a") + validOnlyWithInvalidArgs(err, t) } // This test make sure we keep backwards-compatibility with respect diff --git a/user_guide.md b/user_guide.md index 06d38625a..8d81162a8 100644 --- a/user_guide.md +++ b/user_guide.md @@ -302,15 +302,15 @@ rootCmd.MarkPersistentFlagRequired("region") ### Flag Groups -If you have different flags that must be provided together (e.g. if they provide the `--username` flag they MUST provide the `--password` flag as well) then +If you have different flags that must be provided together (e.g. if they provide the `--username` flag they MUST provide the `--password` flag as well) then Cobra can enforce that requirement: ```go rootCmd.Flags().StringVarP(&u, "username", "u", "", "Username (required if password is set)") rootCmd.Flags().StringVarP(&pw, "password", "p", "", "Password (required if username is set)") rootCmd.MarkFlagsRequiredTogether("username", "password") -``` +``` -You can also prevent different flags from being provided together if they represent mutually +You can also prevent different flags from being provided together if they represent mutually exclusive options such as specifying an output format as either `--json` or `--yaml` but never both: ```go rootCmd.Flags().BoolVar(&u, "json", false, "Output in JSON") @@ -327,8 +327,6 @@ In both of these cases: ## Positional and Custom Arguments Validation of positional arguments can be specified using the `Args` field of `Command`. -If `Args` is undefined or `nil`, it defaults to `ArbitraryArgs`. - The following validators are built in: - Number of arguments: @@ -339,8 +337,9 @@ The following validators are built in: - `ExactArgs(int)` - report an error if there are not exactly N positional args. - `RangeArgs(min, max)` - report an error if the number of args is not between `min` and `max`. - Content of the arguments: - - `OnlyValidArgs` - report an error if there are any positional args that are not in the `ValidArgs` field of type - `[]string` defined in `Command`. + - `OnlyValidArgs` - report an error if there are any positional args not specified in the `ValidArgs` field of `Command`, which can optionally be set to a list of valid values for positional args. + +If `Args` is undefined or `nil`, it defaults to `ArbitraryArgs`. Moreover, `MatchAll(pargs ...PositionalArgs)` enables combining existing checks with arbitrary other checks. For instance, if you want to report an error if there are not exactly N positional args OR if there are any positional @@ -364,9 +363,11 @@ For example: var cmd = &cobra.Command{ Short: "hello", Args: func(cmd *cobra.Command, args []string) error { - if len(args) < 1 { - return errors.New("requires a color argument") + // Optionally run one of the validators provided by cobra + if err := cobra.MinimumNArgs(1)(cmd, args); err != nil { + return err } + // Run the custom validation logic if myapp.IsValidColor(args[0]) { return nil } From b3982ec9bc06d5f8d2fb6b80739e6fd5c6b1755a Mon Sep 17 00:00:00 2001 From: umarcor Date: Tue, 30 Aug 2022 19:29:43 +0200 Subject: [PATCH 3/7] args: inverse the methods in ExactValidArgs --- args.go | 2 +- args_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/args.go b/args.go index 7c4cc1b50..3f77ff103 100644 --- a/args.go +++ b/args.go @@ -113,5 +113,5 @@ func MatchAll(pargs ...PositionalArgs) PositionalArgs { // // Deprecated: use MatchAll(OnlyValidArgs, ExactArgs(n)) instead func ExactValidArgs(n int) PositionalArgs { - return MatchAll(OnlyValidArgs, ExactArgs(n)) + return MatchAll(ExactArgs(n), OnlyValidArgs) } diff --git a/args_test.go b/args_test.go index 9d26a41b2..858bc9a51 100644 --- a/args_test.go +++ b/args_test.go @@ -488,7 +488,7 @@ func TestExactValidArgs_WithInvalidCount(t *testing.T) { func TestExactValidArgs_WithInvalidCount_WithInvalidArgs(t *testing.T) { c := getCommand(ExactValidArgs(3), true) _, err := executeCommand(c, "three", "a", "two") - validOnlyWithInvalidArgs(err, t) + exactArgsWithInvalidCount(err, t) } func TestExactValidArgs_WithInvalidArgs(t *testing.T) { From 83365ac14e01b6700bce04b2e73add6654c0b885 Mon Sep 17 00:00:00 2001 From: umarcor Date: Tue, 30 Aug 2022 19:31:37 +0200 Subject: [PATCH 4/7] args_test: specify 2 args instead of 3 in TestExactValidArgs_WithInvalidArgs --- args_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/args_test.go b/args_test.go index 858bc9a51..7ae9ed6b5 100644 --- a/args_test.go +++ b/args_test.go @@ -492,7 +492,7 @@ func TestExactValidArgs_WithInvalidCount_WithInvalidArgs(t *testing.T) { } func TestExactValidArgs_WithInvalidArgs(t *testing.T) { - c := getCommand(ExactValidArgs(3), true) + c := getCommand(ExactValidArgs(2), true) _, err := executeCommand(c, "three", "a") validOnlyWithInvalidArgs(err, t) } From 4e31482378d51181ed0651cd6daf6a6aa2e946ab Mon Sep 17 00:00:00 2001 From: umarcor Date: Tue, 30 Aug 2022 19:32:25 +0200 Subject: [PATCH 5/7] args_test: specify 2 args instead of 3 in TestExactValidArgs_WithInvalidCount_WithInvalidArgs --- args_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/args_test.go b/args_test.go index 7ae9ed6b5..1346d2999 100644 --- a/args_test.go +++ b/args_test.go @@ -486,7 +486,7 @@ func TestExactValidArgs_WithInvalidCount(t *testing.T) { } func TestExactValidArgs_WithInvalidCount_WithInvalidArgs(t *testing.T) { - c := getCommand(ExactValidArgs(3), true) + c := getCommand(ExactValidArgs(2), true) _, err := executeCommand(c, "three", "a", "two") exactArgsWithInvalidCount(err, t) } From 6863083cddaccf6e875723c9facf3e2216a88882 Mon Sep 17 00:00:00 2001 From: umarcor Date: Tue, 30 Aug 2022 19:35:15 +0200 Subject: [PATCH 6/7] args_test: fix command passed to TestNoArgs_WithValid_WithInvalidArgs --- args_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/args_test.go b/args_test.go index 1346d2999..ae4df2e24 100644 --- a/args_test.go +++ b/args_test.go @@ -38,12 +38,12 @@ func validOnlyWithInvalidArgs(err error, t *testing.T) { } } -func noArgsWithArgs(err error, t *testing.T) { +func noArgsWithArgs(err error, t *testing.T, arg string) { if err == nil { t.Fatal("Expected an error") } got := err.Error() - expected := `unknown command "one" for "c"` + expected := `unknown command "` + arg + `" for "c"` if got != expected { t.Errorf("Expected: %q, got: %q", expected, got) } @@ -104,19 +104,19 @@ func TestNoArgs(t *testing.T) { func TestNoArgs_WithArgs(t *testing.T) { c := getCommand(NoArgs, false) _, err := executeCommand(c, "one") - noArgsWithArgs(err, t) + noArgsWithArgs(err, t, "one") } func TestNoArgs_WithValid_WithArgs(t *testing.T) { c := getCommand(NoArgs, true) _, err := executeCommand(c, "one") - noArgsWithArgs(err, t) + noArgsWithArgs(err, t, "one") } func TestNoArgs_WithValid_WithInvalidArgs(t *testing.T) { c := getCommand(NoArgs, true) - _, err := executeCommand(c, "one") - noArgsWithArgs(err, t) + _, err := executeCommand(c, "a") + noArgsWithArgs(err, t, "a") } func TestNoArgs_WithValidOnly_WithInvalidArgs(t *testing.T) { From 8095ca31dd6a9a6a200ac88672b1786a6212ddae Mon Sep 17 00:00:00 2001 From: umarcor Date: Tue, 30 Aug 2022 19:57:51 +0200 Subject: [PATCH 7/7] adjust docs --- args.go | 2 +- user_guide.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/args.go b/args.go index 3f77ff103..e2f40d515 100644 --- a/args.go +++ b/args.go @@ -111,7 +111,7 @@ func MatchAll(pargs ...PositionalArgs) PositionalArgs { // ExactValidArgs returns an error if there are not exactly N positional args OR // there are any positional args that are not in the `ValidArgs` field of `Command` // -// Deprecated: use MatchAll(OnlyValidArgs, ExactArgs(n)) instead +// Deprecated: use MatchAll(ExactArgs(n), OnlyValidArgs) instead func ExactValidArgs(n int) PositionalArgs { return MatchAll(ExactArgs(n), OnlyValidArgs) } diff --git a/user_guide.md b/user_guide.md index 8d81162a8..6128ae46f 100644 --- a/user_guide.md +++ b/user_guide.md @@ -349,7 +349,7 @@ shown below: ```go var cmd = &cobra.Command{ Short: "hello", - Args: MatchAll(OnlyValidArgs, ExactArgs(2)), + Args: MatchAll(ExactArgs(2), OnlyValidArgs), Run: func(cmd *cobra.Command, args []string) { fmt.Println("Hello, World!") },