forked from go-clix/cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
args.go
140 lines (114 loc) · 3.07 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
package cli
import (
"fmt"
"github.com/posener/complete"
)
// Arguments is used to validate and complete positional arguments.
// Use `Args()` to create an instance from functions.
type Arguments interface {
Validator
complete.Predictor
}
// Validator checks that arguments have the expected form
type Validator interface {
// Validate receives the arguments of the command (without flags) and shall
// return an error if they are unexpected.
Validate(args []string) error
}
// Args bundles user-supplied implementations of the respective interfaces into
// an Arguments implementation.
type Args struct {
Validator
complete.Predictor
}
// ValidateFunc allows to use an ordinary func as an Validator
type ValidateFunc func(args []string) error
// Validate wrap the underlying function
func (v ValidateFunc) Validate(args []string) error {
return v(args)
}
// PredictFunc allows to use an ordinary func as an Predictor
type PredictFunc = complete.PredictFunc
// ---
// Common Argument implementations
// ---
// No Arguments
// ArgsNone checks that no arguments were given, and disables predictions.
func ArgsNone() Arguments {
return Args{
Validator: ValidateNone(),
Predictor: PredictNone(),
}
}
// ValidateNone checks for no arguments at all
func ValidateNone() ValidateFunc {
return ValidateExact(0)
}
// PredictNone predicts exactly nothing
func PredictNone() complete.Predictor {
return PredictFunc(func(args complete.Args) []string {
return nil
})
}
// Exact arguments
// ArgsExact checks for exactly n arguments, predicting anything
func ArgsExact(n int) Arguments {
return Args{
Validator: ValidateExact(n),
Predictor: PredictAny(),
}
}
// ValidateExact checks that exactly n arguments were given
func ValidateExact(n int) ValidateFunc {
return func(args []string) error {
if len(args) != n {
return fmt.Errorf("accepts %v arg, received %v", n, len(args))
}
return nil
}
}
// Any arguments
// ArgsAny allows any number of arguments with any value
func ArgsAny() Arguments {
return Args{
Validator: ValidateAny(),
Predictor: PredictAny(),
}
}
// PredictAny predicts any files/directories
func PredictAny() complete.Predictor {
return complete.PredictFiles("*")
}
// ValidateAny always approves
func ValidateAny() ValidateFunc {
return func(args []string) error {
return nil
}
}
// Predefined arguments
// ArgsSet check the given argument is in the predefined set of options. Only
// these options are predicted. Only a single argument is assumed.
func ArgsSet(set ...string) Arguments {
return Args{
Validator: ValidateSet(set...),
Predictor: PredictSet(set...),
}
}
// PredictSet predicts the values from the given set
func PredictSet(set ...string) complete.Predictor {
return complete.PredictSet(set...)
}
// ValidateSet checks that the given single argument is part of the set.
func ValidateSet(set ...string) ValidateFunc {
return func(args []string) error {
if err := ValidateExact(1)(args); err != nil {
return err
}
for _, s := range set {
if args[0] == s {
return nil
}
}
return fmt.Errorf("only accepts %v", set)
}
}