-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathargs.go
160 lines (141 loc) · 4.04 KB
/
args.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package cli
import (
"fmt"
"slices"
)
// ArgValidator is a function responsible for validating the provided positional arguments
// to a [Command].
//
// An ArgValidator should return an error if it thinks the arguments are not valid.
type ArgValidator func(cmd *Command, args []string) error
// AnyArgs is a positional argument validator that allows any arbitrary args,
// it never returns an error.
//
// This is the default argument validator on a [Command] instantiated with cli.New.
func AnyArgs() ArgValidator {
return func(_ *Command, _ []string) error {
return nil
}
}
// NoArgs is a positional argument validator that does not allow any arguments,
// it returns an error if there are any arguments.
func NoArgs() ArgValidator {
return func(cmd *Command, args []string) error {
if len(args) > 0 {
if len(cmd.subcommands) > 0 {
// Maybe it's a typo of a subcommand
return fmt.Errorf(
"unknown subcommand %q for command %q, available subcommands: %v",
args[0],
cmd.name,
cmd.subcommandNames(),
)
}
return fmt.Errorf("command %s accepts no arguments but got %v", cmd.name, args)
}
return nil
}
}
// MinArgs is a positional argument validator that requires at least n arguments.
func MinArgs(n int) ArgValidator {
return func(cmd *Command, args []string) error {
if len(args) < n {
return fmt.Errorf(
"command %s requires at least %d arguments, but got %d: %v",
cmd.name,
n,
len(args),
args,
)
}
return nil
}
}
// MaxArgs is a positional argument validator that returns an error if there are more than n arguments.
func MaxArgs(n int) ArgValidator {
return func(cmd *Command, args []string) error {
if len(args) > n {
return fmt.Errorf(
"command %s has a limit of %d argument(s), but got %d: %v",
cmd.name,
n,
len(args),
args,
)
}
return nil
}
}
// ExactArgs is a positional argument validator that allows exactly n args, any more
// or less will return an error.
func ExactArgs(n int) ArgValidator {
return func(cmd *Command, args []string) error {
if len(args) != n {
return fmt.Errorf(
"command %s requires exactly %d arguments, but got %d: %v",
cmd.name,
n,
len(args),
args,
)
}
return nil
}
}
// BetweenArgs is a positional argument validator that allows between min and max arguments (inclusive),
// any outside that range will return an error.
//
//nolint:predeclared // min has same name as min function but we don't use it here and the clarity is worth it
func BetweenArgs(min, max int) ArgValidator {
return func(cmd *Command, args []string) error {
nArgs := len(args)
if nArgs < min || nArgs > max {
return fmt.Errorf(
"command %s requires between %d and %d arguments, but got %d: %v",
cmd.name,
min,
max,
nArgs,
args,
)
}
return nil
}
}
// ValidArgs is a positional argument validator that only allows arguments that are contained in
// the valid slice. If any non-valid arguments are seen, an error will be returned.
func ValidArgs(valid []string) ArgValidator {
return func(cmd *Command, args []string) error {
for _, arg := range args {
if !slices.Contains(valid, arg) {
return fmt.Errorf(
"command %s got an invalid argument %s, expected one of %v",
cmd.name,
arg,
valid,
)
}
}
return nil
}
}
// Combine allows multiple positional argument validators to be composed together.
//
// The first validator to fail will be the one that returns the error.
func Combine(validators ...ArgValidator) ArgValidator {
return func(cmd *Command, args []string) error {
for _, validator := range validators {
if err := validator(cmd, args); err != nil {
return err
}
}
return nil
}
}
// positionalArg is a named positional argument to a command.
type positionalArg struct {
name string // The name of the argument
description string // A short description of the argument
value string // The actual parsed value from the command line
defaultValue string // The default value to be used if not set, only set by the OptionalArg option
}