Skip to content

Commit 7023fcd

Browse files
nelz9999umarcor
authored andcommitted
add MatchAll: enable composing PositionalArgs (spf13#896)
1 parent 70089ce commit 7023fcd

File tree

3 files changed

+62
-0
lines changed

3 files changed

+62
-0
lines changed

args.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,18 @@ func RangeArgs(min int, max int) PositionalArgs {
9696
}
9797
}
9898

99+
// MatchAll allows combining several PositionalArgs to work in concert.
100+
func MatchAll(pargs ...PositionalArgs) PositionalArgs {
101+
return func(cmd *Command, args []string) error {
102+
for _, parg := range pargs {
103+
if err := parg(cmd, args); err != nil {
104+
return err
105+
}
106+
}
107+
return nil
108+
}
109+
}
110+
99111
// ExactValidArgs returns an error if there are not exactly N positional args OR
100112
// there are any positional args that are not in the `ValidArgs` field of `Command`
101113
//

args_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cobra
22

33
import (
4+
"fmt"
45
"strings"
56
"testing"
67
)
@@ -191,3 +192,51 @@ func TestChildTakesArgs(t *testing.T) {
191192
t.Fatalf("Unexpected error: %v", err)
192193
}
193194
}
195+
196+
func TestMatchAll(t *testing.T) {
197+
// Somewhat contrived example check that ensures there are exactly 3
198+
// arguments, and each argument is exactly 2 bytes long.
199+
pargs := MatchAll(
200+
ExactArgs(3),
201+
func(cmd *Command, args []string) error {
202+
for _, arg := range args {
203+
if len([]byte(arg)) != 2 {
204+
return fmt.Errorf("expected to be exactly 2 bytes long")
205+
}
206+
}
207+
return nil
208+
},
209+
)
210+
211+
testCases := map[string]struct {
212+
args []string
213+
fail bool
214+
}{
215+
"happy path": {
216+
[]string{"aa", "bb", "cc"},
217+
false,
218+
},
219+
"incorrect number of args": {
220+
[]string{"aa", "bb", "cc", "dd"},
221+
true,
222+
},
223+
"incorrect number of bytes in one arg": {
224+
[]string{"aa", "bb", "abc"},
225+
true,
226+
},
227+
}
228+
229+
rootCmd := &Command{Use: "root", Args: pargs, Run: emptyRun}
230+
231+
for name, tc := range testCases {
232+
t.Run(name, func(t *testing.T) {
233+
_, err := executeCommand(rootCmd, tc.args...)
234+
if err != nil && !tc.fail {
235+
t.Errorf("unexpected: %v\n", err)
236+
}
237+
if err == nil && tc.fail {
238+
t.Errorf("expected error")
239+
}
240+
})
241+
}
242+
}

user_guide.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ The following validators are built in:
311311
- `MaximumNArgs(int)` - report an error if more than N positional args are provided.
312312
- `ExactArgs(int)` - report an error if there are not exactly N positional args.
313313
- `RangeArgs(min, max)` - report an error if the number of args is not between `min` and `max`.
314+
- `MatchAll(pargs ...PositionalArgs)` - enables combining existing checks with arbitrary other checks (e.g. you want to check the ExactArgs length along with other qualities).
314315

315316
If `Args` is undefined or `nil`, it defaults to `ArbitraryArgs`.
316317

0 commit comments

Comments
 (0)