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
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
@ -243,3 +244,51 @@ func TestChildTakesArgs(t *testing.T) {
 | 
			
		||||
		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.
 | 
			
		||||
- `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:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user