vyvanse/vendor/github.com/namsral/flag/extras.go

186 lines
4.3 KiB
Go
Raw Normal View History

2017-08-25 08:22:58 +00:00
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package flag
import (
"bufio"
"os"
"strings"
)
// EnvironmentPrefix defines a string that will be implicitely prefixed to a
// flag name before looking it up in the environment variables.
var EnvironmentPrefix = ""
// ParseEnv parses flags from environment variables.
// Flags already set will be ignored.
func (f *FlagSet) ParseEnv(environ []string) error {
m := f.formal
env := make(map[string]string)
for _, s := range environ {
i := strings.Index(s, "=")
if i < 1 {
continue
}
env[s[0:i]] = s[i+1 : len(s)]
}
for _, flag := range m {
name := flag.Name
_, set := f.actual[name]
if set {
continue
}
flag, alreadythere := m[name]
if !alreadythere {
if name == "help" || name == "h" { // special case for nice help message.
f.usage()
return ErrHelp
}
return f.failf("environment variable provided but not defined: %s", name)
}
envKey := strings.ToUpper(flag.Name)
if f.envPrefix != "" {
envKey = f.envPrefix + "_" + envKey
}
envKey = strings.Replace(envKey, "-", "_", -1)
value, isSet := env[envKey]
if !isSet {
continue
}
hasValue := false
if len(value) > 0 {
hasValue = true
}
if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg
if hasValue {
if err := fv.Set(value); err != nil {
return f.failf("invalid boolean value %q for environment variable %s: %v", value, name, err)
}
} else {
// flag without value is regarded a bool
fv.Set("true")
}
} else {
if err := flag.Value.Set(value); err != nil {
return f.failf("invalid value %q for environment variable %s: %v", value, name, err)
}
}
// update f.actual
if f.actual == nil {
f.actual = make(map[string]*Flag)
}
f.actual[name] = flag
}
return nil
}
// NewFlagSetWithEnvPrefix returns a new empty flag set with the specified name,
// environment variable prefix, and error handling property.
func NewFlagSetWithEnvPrefix(name string, prefix string, errorHandling ErrorHandling) *FlagSet {
f := NewFlagSet(name, errorHandling)
f.envPrefix = prefix
return f
}
// DefaultConfigFlagname defines the flag name of the optional config file
// path. Used to lookup and parse the config file when a default is set and
// available on disk.
var DefaultConfigFlagname = "config"
// ParseFile parses flags from the file in path.
// Same format as commandline argumens, newlines and lines beginning with a
// "#" charater are ignored. Flags already set will be ignored.
func (f *FlagSet) ParseFile(path string) error {
// Extract arguments from file
fp, err := os.Open(path)
if err != nil {
return err
}
defer fp.Close()
scanner := bufio.NewScanner(fp)
for scanner.Scan() {
line := scanner.Text()
// Ignore empty lines
if len(line) == 0 {
continue
}
// Ignore comments
if line[:1] == "#" {
continue
}
// Match `key=value` and `key value`
var name, value string
hasValue := false
for i, v := range line {
if v == '=' || v == ' ' {
hasValue = true
name, value = line[:i], line[i+1:]
break
}
}
if hasValue == false {
name = line
}
// Ignore flag when already set; arguments have precedence over file
if f.actual[name] != nil {
continue
}
m := f.formal
flag, alreadythere := m[name]
if !alreadythere {
if name == "help" || name == "h" { // special case for nice help message.
f.usage()
return ErrHelp
}
return f.failf("configuration variable provided but not defined: %s", name)
}
if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg
if hasValue {
if err := fv.Set(value); err != nil {
return f.failf("invalid boolean value %q for configuration variable %s: %v", value, name, err)
}
} else {
// flag without value is regarded a bool
fv.Set("true")
}
} else {
if err := flag.Value.Set(value); err != nil {
return f.failf("invalid value %q for configuration variable %s: %v", value, name, err)
}
}
// update f.actual
if f.actual == nil {
f.actual = make(map[string]*Flag)
}
f.actual[name] = flag
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}