forked from akamensky/argparse
-
Notifications
You must be signed in to change notification settings - Fork 0
/
command.go
125 lines (110 loc) · 2.56 KB
/
command.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
package argparse
import (
"fmt"
)
func (o *Command) help() {
result := &help{}
a := &arg{
result: &result,
sname: "h",
lname: "help",
size: 1,
opts: &Options{Help: "Print help information"},
unique: true,
}
o.addArg(a)
}
func (o *Command) addArg(a *arg) {
if a.lname != "" {
if a.sname == "" || len(a.sname) == 1 {
// Search parents for overlapping commands and fail silently if any
current := o
for current != nil {
if current.args != nil {
for _, v := range current.args {
if (a.sname != "" && a.sname == v.sname) || a.lname == v.lname {
return
}
}
}
current = current.parent
}
a.parent = o
o.args = append(o.args, a)
}
}
}
// Will parse provided list of arguments
// common usage would be to pass directly os.Args
func (o *Command) parse(args *[]string) error {
// If we already been parsed do nothing
if o.parsed {
return nil
}
// If no arguments left to parse do nothing
if len(*args) < 1 {
return nil
}
// Parse only matching commands
// But we always have to parse top level
if o.name == "" {
o.name = (*args)[0]
} else {
if o.name != (*args)[0] && o.parent != nil {
return nil
}
}
// Set happened status to true when command happend
o.happened = true
// Reduce arguments by removing Command name
*args = (*args)[1:]
// Parse subcommands if any
if o.commands != nil && len(o.commands) > 0 {
// If we have subcommands and 0 args left
// that is an error of SubCommandError type
if len(*args) < 1 {
return newSubCommandError(o)
}
for _, v := range o.commands {
err := v.parse(args)
if err != nil {
return err
}
}
}
// Iterate over the args
for i := 0; i < len(o.args); i++ {
oarg := o.args[i]
for j := 0; j < len(*args); j++ {
arg := (*args)[j]
if arg == "" {
continue
}
if cnt := oarg.check(arg); cnt > 0 {
if len(*args) < j+oarg.size {
return fmt.Errorf("not enough arguments for %s", oarg.name())
}
err := oarg.parse((*args)[j+1:j+oarg.size], cnt)
if err != nil {
return err
}
oarg.reduce(j, args)
continue
}
}
// Check if arg is required and not provided
if oarg.opts != nil && oarg.opts.Required && !oarg.parsed {
return fmt.Errorf("[%s] is required", oarg.name())
}
// Check for argument default value and if provided try to type cast and assign
if oarg.opts != nil && oarg.opts.Default != nil && !oarg.parsed {
err := oarg.setDefault()
if err != nil {
return err
}
}
}
// Set parsed status to true and return quietly
o.parsed = true
return nil
}