forked from alecthomas/kingpin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
args.go
121 lines (107 loc) · 2.51 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
package kingpin
import "fmt"
type argGroup struct {
args []*ArgClause
}
func newArgGroup() *argGroup {
return &argGroup{}
}
func (a *argGroup) Arg(name, help string) *ArgClause {
arg := newArg(name, help)
a.args = append(a.args, arg)
return arg
}
func (a *argGroup) parse(tokens tokens) (tokens, error) {
for _, arg := range a.args {
token := tokens.Peek()
if token.IsFlag() {
return nil, fmt.Errorf("unknown flag '%s'", token)
}
if token.Type != TokenArg {
if arg.required {
return nil, fmt.Errorf("'%s' is required", arg.name)
}
break
}
var err error
tokens, err = arg.parse(tokens)
if err != nil {
return nil, err
}
}
return tokens, nil
}
func (a *argGroup) init() {
required := 0
seen := map[string]struct{}{}
for i, arg := range a.args {
if _, ok := seen[arg.name]; ok {
panic(fmt.Sprintf("duplicate argument '%s'", arg.name))
}
seen[arg.name] = struct{}{}
if arg.required && required != i {
panic("required arguments found after non-required")
}
if arg.required {
required++
}
arg.init()
}
}
type ArgClause struct {
parserMixin
name string
help string
defaultValue string
required bool
dispatch Dispatch
}
func newArg(name, help string) *ArgClause {
a := &ArgClause{
name: name,
help: help,
}
return a
}
// Required arguments must be input by the user. They can not have a Default() value provided.
func (a *ArgClause) Required() *ArgClause {
a.required = true
return a
}
// Default value for this argument. It *must* be parseable by the value of the argument.
func (a *ArgClause) Default(value string) *ArgClause {
a.defaultValue = value
return a
}
func (a *ArgClause) Dispatch(dispatch Dispatch) *ArgClause {
a.dispatch = dispatch
return a
}
func (a *ArgClause) init() {
if a.required && a.defaultValue != "" {
panic(fmt.Sprintf("required argument '%s' with unusable default value", a.name))
}
if a.value == nil {
panic(fmt.Sprintf("no parser defined for arg '%s'", a.name))
}
if a.defaultValue != "" {
if err := a.value.Set(a.defaultValue); err != nil {
panic(fmt.Sprintf("invalid default value '%s' for argument '%s'", a.defaultValue, a.name))
}
}
}
func (a *ArgClause) parse(tokens tokens) (tokens, error) {
if token, tokens := tokens.Next(); token.Type == TokenArg {
if err := a.value.Set(token.Value); err != nil {
return nil, err
}
if a.dispatch != nil {
if err := a.dispatch(); err != nil {
return nil, err
}
}
return tokens, nil
} else {
return tokens.Return(token), nil
}
}