enable composing PositionalArgs (#896)
* enable composing PositionalArgs * ExactValidArgs slated for removal * tests and docs * rename to MatchAll
This commit is contained in:
		
							
								
								
									
										12
									
								
								args.go
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								args.go
									
									
									
									
									
								
							@ -107,3 +107,15 @@ func RangeArgs(min int, max int) PositionalArgs {
 | 
				
			|||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MatchAll allows combining several PositionalArgs to work in concert.
 | 
				
			||||||
 | 
					func MatchAll(pargs ...PositionalArgs) PositionalArgs {
 | 
				
			||||||
 | 
						return func(cmd *Command, args []string) error {
 | 
				
			||||||
 | 
							for _, parg := range pargs {
 | 
				
			||||||
 | 
								if err := parg(cmd, args); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										49
									
								
								args_test.go
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								args_test.go
									
									
									
									
									
								
							@ -1,6 +1,7 @@
 | 
				
			|||||||
package cobra
 | 
					package cobra
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@ -243,3 +244,51 @@ func TestChildTakesArgs(t *testing.T) {
 | 
				
			|||||||
		t.Fatalf("Unexpected error: %v", err)
 | 
							t.Fatalf("Unexpected error: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestMatchAll(t *testing.T) {
 | 
				
			||||||
 | 
						// Somewhat contrived example check that ensures there are exactly 3
 | 
				
			||||||
 | 
						// arguments, and each argument is exactly 2 bytes long.
 | 
				
			||||||
 | 
						pargs := MatchAll(
 | 
				
			||||||
 | 
							ExactArgs(3),
 | 
				
			||||||
 | 
							func(cmd *Command, args []string) error {
 | 
				
			||||||
 | 
								for _, arg := range args {
 | 
				
			||||||
 | 
									if len([]byte(arg)) != 2 {
 | 
				
			||||||
 | 
										return fmt.Errorf("expected to be exactly 2 bytes long")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						testCases := map[string]struct {
 | 
				
			||||||
 | 
							args []string
 | 
				
			||||||
 | 
							fail bool
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							"happy path": {
 | 
				
			||||||
 | 
								[]string{"aa", "bb", "cc"},
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"incorrect number of args": {
 | 
				
			||||||
 | 
								[]string{"aa", "bb", "cc", "dd"},
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"incorrect number of bytes in one arg": {
 | 
				
			||||||
 | 
								[]string{"aa", "bb", "abc"},
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rootCmd := &Command{Use: "root", Args: pargs, Run: emptyRun}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for name, tc := range testCases {
 | 
				
			||||||
 | 
							t.Run(name, func(t *testing.T) {
 | 
				
			||||||
 | 
								_, err := executeCommand(rootCmd, tc.args...)
 | 
				
			||||||
 | 
								if err != nil && !tc.fail {
 | 
				
			||||||
 | 
									t.Errorf("unexpected: %v\n", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if err == nil && tc.fail {
 | 
				
			||||||
 | 
									t.Errorf("expected error")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -315,6 +315,7 @@ The following validators are built in:
 | 
				
			|||||||
- `ExactArgs(int)` - the command will report an error if there are not exactly 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`
 | 
					- `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.
 | 
					- `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:
 | 
					An example of setting the custom validator:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user