...
1 package cli
2
3 import "sort"
4
5
6 type CommandCategories interface {
7
8 AddCommand(category string, command *Command)
9
10 Categories() []CommandCategory
11 }
12
13 type commandCategories []*commandCategory
14
15 func newCommandCategories() CommandCategories {
16 ret := commandCategories([]*commandCategory{})
17 return &ret
18 }
19
20 func (c *commandCategories) Less(i, j int) bool {
21 return lexicographicLess((*c)[i].Name(), (*c)[j].Name())
22 }
23
24 func (c *commandCategories) Len() int {
25 return len(*c)
26 }
27
28 func (c *commandCategories) Swap(i, j int) {
29 (*c)[i], (*c)[j] = (*c)[j], (*c)[i]
30 }
31
32 func (c *commandCategories) AddCommand(category string, command *Command) {
33 for _, commandCategory := range []*commandCategory(*c) {
34 if commandCategory.name == category {
35 commandCategory.commands = append(commandCategory.commands, command)
36 return
37 }
38 }
39 newVal := append(*c,
40 &commandCategory{name: category, commands: []*Command{command}})
41 *c = newVal
42 }
43
44 func (c *commandCategories) Categories() []CommandCategory {
45 ret := make([]CommandCategory, len(*c))
46 for i, cat := range *c {
47 ret[i] = cat
48 }
49 return ret
50 }
51
52
53 type CommandCategory interface {
54
55 Name() string
56
57 VisibleCommands() []*Command
58 }
59
60 type commandCategory struct {
61 name string
62 commands []*Command
63 }
64
65 func (c *commandCategory) Name() string {
66 return c.name
67 }
68
69 func (c *commandCategory) VisibleCommands() []*Command {
70 if c.commands == nil {
71 c.commands = []*Command{}
72 }
73
74 var ret []*Command
75 for _, command := range c.commands {
76 if !command.Hidden {
77 ret = append(ret, command)
78 }
79 }
80 return ret
81 }
82
83
84 type FlagCategories interface {
85
86 AddFlag(category string, fl Flag)
87
88 VisibleCategories() []VisibleFlagCategory
89 }
90
91 type defaultFlagCategories struct {
92 m map[string]*defaultVisibleFlagCategory
93 }
94
95 func newFlagCategories() FlagCategories {
96 return &defaultFlagCategories{
97 m: map[string]*defaultVisibleFlagCategory{},
98 }
99 }
100
101 func newFlagCategoriesFromFlags(fs []Flag) FlagCategories {
102 fc := newFlagCategories()
103
104 var categorized bool
105 for _, fl := range fs {
106 if cf, ok := fl.(CategorizableFlag); ok {
107 if cat := cf.GetCategory(); cat != "" {
108 fc.AddFlag(cat, cf)
109 categorized = true
110 }
111 }
112 }
113
114 if categorized {
115 for _, fl := range fs {
116 if cf, ok := fl.(CategorizableFlag); ok {
117 if cf.GetCategory() == "" {
118 fc.AddFlag("", fl)
119 }
120 }
121 }
122 }
123
124 return fc
125 }
126
127 func (f *defaultFlagCategories) AddFlag(category string, fl Flag) {
128 if _, ok := f.m[category]; !ok {
129 f.m[category] = &defaultVisibleFlagCategory{name: category, m: map[string]Flag{}}
130 }
131
132 f.m[category].m[fl.String()] = fl
133 }
134
135 func (f *defaultFlagCategories) VisibleCategories() []VisibleFlagCategory {
136 catNames := []string{}
137 for name := range f.m {
138 catNames = append(catNames, name)
139 }
140
141 sort.Strings(catNames)
142
143 ret := make([]VisibleFlagCategory, len(catNames))
144 for i, name := range catNames {
145 ret[i] = f.m[name]
146 }
147
148 return ret
149 }
150
151
152 type VisibleFlagCategory interface {
153
154 Name() string
155
156 Flags() []VisibleFlag
157 }
158
159 type defaultVisibleFlagCategory struct {
160 name string
161 m map[string]Flag
162 }
163
164 func (fc *defaultVisibleFlagCategory) Name() string {
165 return fc.name
166 }
167
168 func (fc *defaultVisibleFlagCategory) Flags() []VisibleFlag {
169 vfNames := []string{}
170 for flName, fl := range fc.m {
171 if vf, ok := fl.(VisibleFlag); ok {
172 if vf.IsVisible() {
173 vfNames = append(vfNames, flName)
174 }
175 }
176 }
177
178 sort.Strings(vfNames)
179
180 ret := make([]VisibleFlag, len(vfNames))
181 for i, flName := range vfNames {
182 ret[i] = fc.m[flName].(VisibleFlag)
183 }
184
185 return ret
186 }
187
View as plain text