146 lines
3.3 KiB
Go
146 lines
3.3 KiB
Go
package cli
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
// ValueSource is a source which can be used to look up a value,
|
|
// typically for use with a cli.Flag
|
|
type ValueSource interface {
|
|
fmt.Stringer
|
|
fmt.GoStringer
|
|
|
|
// Lookup returns the value from the source and if it was found
|
|
// or returns an empty string and false
|
|
Lookup() (string, bool)
|
|
}
|
|
|
|
// ValueSourceChain contains an ordered series of ValueSource that
|
|
// allows for lookup where the first ValueSource to resolve is
|
|
// returned
|
|
type ValueSourceChain struct {
|
|
Chain []ValueSource
|
|
}
|
|
|
|
func NewValueSourceChain(src ...ValueSource) ValueSourceChain {
|
|
return ValueSourceChain{
|
|
Chain: src,
|
|
}
|
|
}
|
|
|
|
func (vsc *ValueSourceChain) Append(other ValueSourceChain) {
|
|
vsc.Chain = append(vsc.Chain, other.Chain...)
|
|
}
|
|
|
|
func (vsc *ValueSourceChain) EnvKeys() []string {
|
|
vals := []string{}
|
|
|
|
for _, src := range vsc.Chain {
|
|
if v, ok := src.(*envVarValueSource); ok {
|
|
vals = append(vals, v.Key)
|
|
}
|
|
}
|
|
|
|
return vals
|
|
}
|
|
|
|
func (vsc *ValueSourceChain) String() string {
|
|
s := []string{}
|
|
|
|
for _, vs := range vsc.Chain {
|
|
s = append(s, vs.String())
|
|
}
|
|
|
|
return strings.Join(s, ",")
|
|
}
|
|
|
|
func (vsc *ValueSourceChain) GoString() string {
|
|
s := []string{}
|
|
|
|
for _, vs := range vsc.Chain {
|
|
s = append(s, vs.GoString())
|
|
}
|
|
|
|
return fmt.Sprintf("&ValueSourceChain{Chain:{%[1]s}}", strings.Join(s, ","))
|
|
}
|
|
|
|
func (vsc *ValueSourceChain) Lookup() (string, bool) {
|
|
s, _, ok := vsc.LookupWithSource()
|
|
return s, ok
|
|
}
|
|
|
|
func (vsc *ValueSourceChain) LookupWithSource() (string, ValueSource, bool) {
|
|
for _, src := range vsc.Chain {
|
|
if value, found := src.Lookup(); found {
|
|
return value, src, true
|
|
}
|
|
}
|
|
|
|
return "", nil, false
|
|
}
|
|
|
|
// envVarValueSource encapsulates a ValueSource from an environment variable
|
|
type envVarValueSource struct {
|
|
Key string
|
|
}
|
|
|
|
func (e *envVarValueSource) Lookup() (string, bool) {
|
|
return os.LookupEnv(strings.TrimSpace(string(e.Key)))
|
|
}
|
|
|
|
func (e *envVarValueSource) String() string { return fmt.Sprintf("environment variable %[1]q", e.Key) }
|
|
func (e *envVarValueSource) GoString() string {
|
|
return fmt.Sprintf("&envVarValueSource{Key:%[1]q}", e.Key)
|
|
}
|
|
|
|
func EnvVar(key string) ValueSource {
|
|
return &envVarValueSource{
|
|
Key: key,
|
|
}
|
|
}
|
|
|
|
// EnvVars is a helper function to encapsulate a number of
|
|
// envVarValueSource together as a ValueSourceChain
|
|
func EnvVars(keys ...string) ValueSourceChain {
|
|
vsc := ValueSourceChain{Chain: []ValueSource{}}
|
|
|
|
for _, key := range keys {
|
|
vsc.Chain = append(vsc.Chain, &envVarValueSource{Key: key})
|
|
}
|
|
|
|
return vsc
|
|
}
|
|
|
|
// fileValueSource encapsulates a ValueSource from a file
|
|
type fileValueSource struct {
|
|
Path string
|
|
}
|
|
|
|
func (f *fileValueSource) Lookup() (string, bool) {
|
|
data, err := os.ReadFile(f.Path)
|
|
return string(data), err == nil
|
|
}
|
|
|
|
func (f *fileValueSource) String() string { return fmt.Sprintf("file %[1]q", f.Path) }
|
|
func (f *fileValueSource) GoString() string {
|
|
return fmt.Sprintf("&fileValueSource{Path:%[1]q}", f.Path)
|
|
}
|
|
|
|
func File(path string) ValueSource {
|
|
return &fileValueSource{Path: path}
|
|
}
|
|
|
|
// Files is a helper function to encapsulate a number of
|
|
// fileValueSource together as a ValueSourceChain
|
|
func Files(paths ...string) ValueSourceChain {
|
|
vsc := ValueSourceChain{Chain: []ValueSource{}}
|
|
|
|
for _, path := range paths {
|
|
vsc.Chain = append(vsc.Chain, &fileValueSource{Path: path})
|
|
}
|
|
|
|
return vsc
|
|
}
|