-
Notifications
You must be signed in to change notification settings - Fork 0
/
matcher.go
67 lines (61 loc) · 1.44 KB
/
matcher.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
package cmdy
import (
"sort"
)
// PrefixMatcher returns a simple Matcher for use with a command Group that will match a
// command if the input is an unambiguous prefix of one of the Group's Builders.
//
// grp := NewGroup("grp", Builders{
// "foo": fooBuilder,
// "bar": barBuilder,
// "bark": barkBuilder,
// "bork": borkBuilder,
// })
//
// // Matches must be 2 or more characters to be considered:
// m := PrefixMatcher(grp, 2)
//
// $ myprog grp fo // fooBuilder
// $ myprog grp ba // NOPE; bar or bark
// $ myprog grp bar // barBuilder
// $ myprog grp bark // barkBuilder
// $ myprog grp b // NOPE; too short
//
func PrefixMatcher(group *Group, minLen int) Matcher {
if minLen <= 0 {
panic("minLen must be > 0")
}
strs := make([]string, 0, len(group.Builders))
for s := range group.Builders {
strs = append(strs, s)
}
sort.Strings(strs)
return func(bldrs Builders, in string) (bld Builder, name string, rerr error) {
max := 0
inlen := len(in)
for _, str := range strs {
var cur int
var curlen = len(str)
if inlen > curlen {
continue
} else if str == in {
return group.Builders[str], str, nil
}
for i := 0; i < curlen; i++ {
if i >= inlen || str[i] != in[i] {
break
}
cur++
}
if cur > 0 && cur >= minLen {
if cur == max {
return nil, "", nil
} else if cur > max {
max = cur
bld, name = group.Builders[str], str
}
}
}
return bld, name, nil
}
}