-
Notifications
You must be signed in to change notification settings - Fork 25
/
commandline.go
102 lines (80 loc) · 2.28 KB
/
commandline.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
package config
import (
"flag"
"os"
"strings"
"github.com/spf13/pflag"
"go.uber.org/fx"
"github.com/fluxninja/aperture/pkg/info"
"github.com/fluxninja/aperture/pkg/log"
)
const (
// ConfigPathFlag is the name of the flag for the configuration path.
ConfigPathFlag = "config_path"
)
/*
CommandLine
*/
// FlagSetBuilder is a function that helps users to build a Flagset.
type FlagSetBuilder func(*pflag.FlagSet) error
// FlagSetBuilderOut wraps the group of FlagSetBuilder and makes it handy to
// provide FlagSetBuilder via Fx.
type FlagSetBuilderOut struct {
fx.Out
Builder FlagSetBuilder `group:"FlagSetBuilders"`
}
// CommandLineIn holds parameters for NewCommandLine.
type CommandLineIn struct {
fx.In
// Builders help platform users set flags
Builders []FlagSetBuilder `group:"FlagSetBuilders"`
// pFlag error handling mode
ErrorHandling pflag.ErrorHandling `optional:"true"`
}
// CommandLineOut holds the output of NewCommandLine, set of defined flags.
type CommandLineOut struct {
fx.Out
FlagSet *pflag.FlagSet
}
// CommandLineConfig holds configuration for CommandLine.
type CommandLineConfig struct {
UnknownFlags bool
ExitOnHelp bool
}
// NewCommandLine returns a new CommandLineOut with new FlagSet.
func (config CommandLineConfig) NewCommandLine(cl CommandLineIn) (CommandLineOut, error) {
fs := pflag.NewFlagSet(info.Service, cl.ErrorHandling)
fs.ParseErrorsWhitelist.UnknownFlags = config.UnknownFlags
fs.SetNormalizeFunc(wordSepNormalizeFunc)
fs.String(ConfigPathFlag, DefaultConfigDirectory, "path to configuration file")
// Add flags from flag.CommandLine
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
for _, builder := range cl.Builders {
if err := builder(fs); err != nil {
return CommandLineOut{}, err
}
}
arguments := os.Args[1:]
if err := fs.Parse(arguments); err != nil {
if err == pflag.ErrHelp {
if config.ExitOnHelp {
// quietly exit
os.Exit(0)
}
} else {
log.Error().Err(err).Msg("Unable to parse command line!")
return CommandLineOut{}, err
}
}
return CommandLineOut{
FlagSet: fs,
}, nil
}
func wordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
from := []string{"-"}
to := "_"
for _, sep := range from {
name = strings.ReplaceAll(name, sep, to)
}
return pflag.NormalizedName(name)
}