1package cobra
2
3import (
4	"fmt"
5)
6
7type PositionalArgs func(cmd *Command, args []string) error
8
9// Legacy arg validation has the following behaviour:
10// - root commands with no subcommands can take arbitrary arguments
11// - root commands with subcommands will do subcommand validity checking
12// - subcommands will always accept arbitrary arguments
13func legacyArgs(cmd *Command, args []string) error {
14	// no subcommand, always take args
15	if !cmd.HasSubCommands() {
16		return nil
17	}
18
19	// root command with subcommands, do subcommand checking.
20	if !cmd.HasParent() && len(args) > 0 {
21		return fmt.Errorf("unknown command %q for %q%s", args[0], cmd.CommandPath(), cmd.findSuggestions(args[0]))
22	}
23	return nil
24}
25
26// NoArgs returns an error if any args are included.
27func NoArgs(cmd *Command, args []string) error {
28	if len(args) > 0 {
29		return fmt.Errorf("unknown command %q for %q", args[0], cmd.CommandPath())
30	}
31	return nil
32}
33
34// OnlyValidArgs returns an error if any args are not in the list of ValidArgs.
35func OnlyValidArgs(cmd *Command, args []string) error {
36	if len(cmd.ValidArgs) > 0 {
37		for _, v := range args {
38			if !stringInSlice(v, cmd.ValidArgs) {
39				return fmt.Errorf("invalid argument %q for %q%s", v, cmd.CommandPath(), cmd.findSuggestions(args[0]))
40			}
41		}
42	}
43	return nil
44}
45
46// ArbitraryArgs never returns an error.
47func ArbitraryArgs(cmd *Command, args []string) error {
48	return nil
49}
50
51// MinimumNArgs returns an error if there is not at least N args.
52func MinimumNArgs(n int) PositionalArgs {
53	return func(cmd *Command, args []string) error {
54		if len(args) < n {
55			return fmt.Errorf("requires at least %d arg(s), only received %d", n, len(args))
56		}
57		return nil
58	}
59}
60
61// MaximumNArgs returns an error if there are more than N args.
62func MaximumNArgs(n int) PositionalArgs {
63	return func(cmd *Command, args []string) error {
64		if len(args) > n {
65			return fmt.Errorf("accepts at most %d arg(s), received %d", n, len(args))
66		}
67		return nil
68	}
69}
70
71// ExactArgs returns an error if there are not exactly n args.
72func ExactArgs(n int) PositionalArgs {
73	return func(cmd *Command, args []string) error {
74		if len(args) != n {
75			return fmt.Errorf("accepts %d arg(s), received %d", n, len(args))
76		}
77		return nil
78	}
79}
80
81// RangeArgs returns an error if the number of args is not within the expected range.
82func RangeArgs(min int, max int) PositionalArgs {
83	return func(cmd *Command, args []string) error {
84		if len(args) < min || len(args) > max {
85			return fmt.Errorf("accepts between %d and %d arg(s), received %d", min, max, len(args))
86		}
87		return nil
88	}
89}
90