-
Notifications
You must be signed in to change notification settings - Fork 3
/
serpent.go
80 lines (70 loc) · 2.03 KB
/
serpent.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
// Package serpent offers an all-in-one solution for a highly configurable CLI
// application. Within Coder, we use it for all of our subcommands, which
// demands more functionality than cobra/viber offers.
//
// The Command interface is loosely based on the chi middleware pattern and
// http.Handler/HandlerFunc.
package serpent
import (
"strings"
"golang.org/x/exp/maps"
)
// Group describes a hierarchy of groups that an option or command belongs to.
type Group struct {
Parent *Group `json:"parent,omitempty"`
Name string `json:"name,omitempty"`
YAML string `json:"yaml,omitempty"`
Description string `json:"description,omitempty"`
}
// Ancestry returns the group and all of its parents, in order.
func (g *Group) Ancestry() []Group {
if g == nil {
return nil
}
groups := []Group{*g}
for p := g.Parent; p != nil; p = p.Parent {
// Prepend to the slice so that the order is correct.
groups = append([]Group{*p}, groups...)
}
return groups
}
func (g *Group) FullName() string {
var names []string
for _, g := range g.Ancestry() {
names = append(names, g.Name)
}
return strings.Join(names, " / ")
}
// Annotations is an arbitrary key-mapping used to extend the Option and Command types.
// Its methods won't panic if the map is nil.
type Annotations map[string]string
// Mark sets a value on the annotations map, creating one
// if it doesn't exist. Mark does not mutate the original and
// returns a copy. It is suitable for chaining.
func (a Annotations) Mark(key string, value string) Annotations {
var aa Annotations
if a != nil {
aa = maps.Clone(a)
} else {
aa = make(Annotations)
}
aa[key] = value
return aa
}
// IsSet returns true if the key is set in the annotations map.
func (a Annotations) IsSet(key string) bool {
if a == nil {
return false
}
_, ok := a[key]
return ok
}
// Get retrieves a key from the map, returning false if the key is not found
// or the map is nil.
func (a Annotations) Get(key string) (string, bool) {
if a == nil {
return "", false
}
v, ok := a[key]
return v, ok
}