forked from fabiolb/fabio
-
Notifications
You must be signed in to change notification settings - Fork 0
/
flagset.go
107 lines (90 loc) · 2.34 KB
/
flagset.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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package config
import (
"flag"
"strings"
"github.com/magiconair/properties"
)
// -- stringSliceValue
type stringSliceValue []string
func newStringSliceValue(val []string, p *[]string) *stringSliceValue {
*p = val
return (*stringSliceValue)(p)
}
func (v *stringSliceValue) Set(s string) error {
*v = []string{}
for _, x := range strings.Split(s, ",") {
x = strings.TrimSpace(x)
if x == "" {
continue
}
*v = append(*v, x)
}
return nil
}
func (v *stringSliceValue) Get() interface{} { return []string(*v) }
func (v *stringSliceValue) String() string { return strings.Join(*v, ",") }
// -- FlagSet
type FlagSet struct {
flag.FlagSet
set map[string]bool
}
func NewFlagSet(name string, errorHandling flag.ErrorHandling) *FlagSet {
fs := &FlagSet{set: make(map[string]bool)}
fs.Init(name, errorHandling)
return fs
}
// IsSet returns true if a variable was set via any mechanism.
func (f *FlagSet) IsSet(name string) bool {
return f.set[name]
}
func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) {
f.Var(newStringSliceValue(value, p), name, usage)
}
// ParseFlags parses command line arguments and provides fallback
// values from environment variables and config file values.
// Environment variables are case-insensitive and can have either
// of the provided prefixes.
func (f *FlagSet) ParseFlags(args, environ, prefixes []string, p *properties.Properties) error {
if err := f.Parse(args); err != nil {
return err
}
if len(prefixes) == 0 {
prefixes = []string{""}
}
// parse environment in case-insensitive way
env := map[string]string{}
for _, e := range environ {
p := strings.SplitN(e, "=", 2)
env[strings.ToUpper(p[0])] = p[1]
}
// determine all values that were set via cmdline
f.Visit(func(fl *flag.Flag) {
f.set[fl.Name] = true
})
// lookup the rest via environ and properties
f.VisitAll(func(fl *flag.Flag) {
// skip if already set
if f.set[fl.Name] {
return
}
// check environment variables
for _, pfx := range prefixes {
name := strings.ToUpper(pfx + strings.Replace(fl.Name, ".", "_", -1))
if val, ok := env[name]; ok {
f.set[fl.Name] = true
f.Set(fl.Name, val)
return
}
}
// check properties
if p == nil {
return
}
if val, ok := p.Get(fl.Name); ok {
f.set[fl.Name] = true
f.Set(fl.Name, val)
return
}
})
return nil
}