...
1 package rags
2
3 import (
4 "flag"
5 "fmt"
6 "sort"
7 "strings"
8 )
9
10
11 const (
12 Global = "global"
13 uncategorized = "uncategorized"
14 )
15
16
17
18
19 type Rag struct {
20 Name string
21 Short string
22 Usage string
23 Category string
24 Required bool
25 Value flag.Getter
26 }
27
28 func (f *Rag) Names() []string {
29 if f.Short != "" {
30 return []string{f.Name, f.Short}
31 }
32 return []string{f.Name}
33 }
34
35 func (f *Rag) Set(s string) error {
36 return f.Value.Set(s)
37 }
38
39 func (f *Rag) Apply(fs *flag.FlagSet) {
40 if f.Name == "" {
41 panic("invalid rich flag: name is required")
42 }
43 if f.Value == nil {
44 panic(fmt.Sprintf("invalid rich flag '%s': value is required", f.Name))
45 }
46 for _, name := range f.Names() {
47 fs.Var(f.Value, name, f.Usage)
48 }
49 }
50
51
52 func (f *Rag) withOpts(opts *options) *Rag {
53 f.Category = opts.category
54 f.Required = opts.required
55 f.Short = opts.short
56
57 return f
58 }
59
60 func normalizeCategory(c string) string {
61
62 c = strings.ToLower(c)
63 c = strings.TrimSpace(c)
64 c = strings.TrimSuffix(c, ":")
65 c = strings.TrimSuffix(c, "flags")
66
67
68 c = strings.TrimSpace(c)
69
70 return c
71 }
72
73
74
75
76 func sortCategories(c []string) {
77 sort.SliceStable(c, func(i, j int) bool {
78 switch {
79 case c[i] == uncategorized, c[i] == "", c[j] == Global:
80 return true
81 case c[j] == uncategorized, c[j] == "", c[i] == Global:
82 return false
83 default:
84 return c[i] < c[j]
85 }
86 })
87 }
88
89
90
91 type FlagOption func(*options)
92
93 type options struct {
94 category string
95 required bool
96 short string
97 }
98
99
100 func WithCategory(c string) FlagOption {
101 return func(o *options) {
102 o.category = c
103 }
104 }
105
106
107 func WithRequired() FlagOption {
108 return func(o *options) {
109 o.required = true
110 }
111 }
112
113
114 func WithShort(s string) FlagOption {
115 return func(o *options) {
116 o.short = s
117 }
118 }
119
120 func makeOptions(opts ...FlagOption) *options {
121 o := &options{}
122 for _, opt := range opts {
123 opt(o)
124 }
125 return o
126 }
127
View as plain text