-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
env.go
53 lines (49 loc) · 1.19 KB
/
env.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
package flagx
import (
"flag"
"fmt"
"os"
"strings"
)
// ParseEnv lists any unset flags, checks whether a corresponding
// environment variable exists, and if so calls Set with its value.
// Flag names are prefixed and converted to SCREAMING_SNAKE_CASE when
// looking up environment variables.
func ParseEnv(fl *flag.FlagSet, prefix string) error {
fl = flagOrDefault(fl)
seen := listVisitedFlagNames(fl)
var nameAndVals [][2]string
fl.VisitAll(func(fn *flag.Flag) {
if !seen[fn.Name] {
key := kebabToUpperSnake(prefix, fn.Name)
if val, ok := os.LookupEnv(key); ok {
nameAndVals = append(nameAndVals, [2]string{fn.Name, val})
}
}
})
for i := range nameAndVals {
name := nameAndVals[i][0]
val := nameAndVals[i][1]
if err := fl.Set(name, val); err != nil {
err = fmt.Errorf("invalid value %q for flag -%s: %v", val, name, err)
return handleErr(fl, err)
}
}
return nil
}
func kebabToUpperSnake(prefix, name string) string {
s := name
if prefix != "" {
s = prefix + "_" + name
}
return strings.Map(func(r rune) rune {
switch {
case 'a' <= r && r <= 'z':
return r + 'A' - 'a'
case 'A' <= r && r <= 'Z',
'0' <= r && r <= '9':
return r
}
return '_'
}, s)
}