-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdefine.go
More file actions
73 lines (68 loc) · 2.34 KB
/
Copy pathdefine.go
File metadata and controls
73 lines (68 loc) · 2.34 KB
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
package optparse
import "regexp"
var (
reNoLong = regexp.MustCompile(`\A--\[no-\]([^\s=]+)(.*)?\z`)
reLong = regexp.MustCompile(`\A--([^\s=\[]+)(.*)?\z`)
reShort = regexp.MustCompile(`\A-(.)(.*)?\z`)
reArgLb = regexp.MustCompile(`\A\[(.*)\]\z`)
reArgPfx = regexp.MustCompile(`\A[=\s]+`)
)
// MakeSpec builds a Spec from the string arguments of an MRI `on(...)` call (the
// option flag strings such as "-v", "--verbose", "--name VALUE", "--[no-]color",
// "--name [VALUE]", and any trailing description strings). The optional coerce
// argument supplies a type/list converter that MRI would pass as a Class, Array,
// or Hash positional; pass "" for none.
//
// For a candidate list, set coerce to CoerceList and provide list (and optionally
// values); for a built-in type pass CoerceInteger/CoerceFloat/CoerceArray/
// CoerceString. rbgo maps the Ruby `on(*args)` positional arguments onto these.
func MakeSpec(opts []string, coerce string, list, values []string) Spec {
s := Spec{Coerce: coerce, List: list, Values: values}
for _, o := range opts {
switch {
case reNoLong.MatchString(o):
m := reNoLong.FindStringSubmatch(o)
s.Long = append(s.Long, "--"+m[1])
s.Negatable = true
if m[2] != "" {
applyArgSpec(&s, m[2])
}
case reLong.MatchString(o):
m := reLong.FindStringSubmatch(o)
s.Long = append(s.Long, "--"+m[1])
if m[2] != "" {
applyArgSpec(&s, m[2])
}
case reShort.MatchString(o):
m := reShort.FindStringSubmatch(o)
s.Short = append(s.Short, "-"+m[1])
if m[2] != "" {
applyArgSpec(&s, m[2])
}
default:
s.Desc = append(s.Desc, o)
}
}
return s
}
// applyArgSpec parses the trailing argument descriptor of a flag string (MRI's
// parse_argspec): "[VAL]" → optional, "VAL" → required, "" → none.
func applyArgSpec(s *Spec, rest string) {
rest = reArgPfx.ReplaceAllString(rest, "")
switch {
case reArgLb.MatchString(rest):
s.ArgStyle = ArgOptional
s.ArgName = reArgLb.FindStringSubmatch(rest)[1]
case rest != "":
s.ArgStyle = ArgRequired
s.ArgName = rest
default:
s.ArgStyle = ArgNone
s.ArgName = ""
}
}
// Define registers an option from raw MRI `on(...)` flag/description strings,
// returning the assigned spec index. It is sugar over MakeSpec + On.
func (p *Parser) Define(opts []string, coerce string, list, values []string) int {
return p.On(MakeSpec(opts, coerce, list, values))
}