diff --git a/README.md b/README.md index ed82acf..842c188 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,12 @@ $ go run ./gopher.go age=44 ``` +#### Parsing Priority +```go +flag.ParsePriority = flag.ParsePriorityEnv // parse environment variables first (default) +flag.ParsePriority = flag.ParsePriorityFile // parse configuration file first +flag.Parse() +``` You can also parse prefixed environment variables by setting a prefix name when creating a new empty flag set: diff --git a/extras.go b/extras.go index f937899..714cbb4 100644 --- a/extras.go +++ b/extras.go @@ -10,6 +10,11 @@ import ( "strings" ) +// Parse priority +const ParsePriorityFile = "File" +const ParsePriorityEnv = "Env" +var ParsePriority = ParsePriorityEnv + // EnvironmentPrefix defines a string that will be implicitely prefixed to a // flag name before looking it up in the environment variables. var EnvironmentPrefix = "" diff --git a/flag.go b/flag.go index ac9d78a..a3b1ad9 100644 --- a/flag.go +++ b/flag.go @@ -935,39 +935,52 @@ func (f *FlagSet) Parse(arguments []string) error { } } - // Parse environment variables - if err := f.ParseEnv(os.Environ()); err != nil { + // Prepare for parse configuration from file + var cFile string + if cf := f.formal[DefaultConfigFlagname]; cf != nil { + cFile = cf.Value.String() + } + if cf := f.actual[DefaultConfigFlagname]; cf != nil { + cFile = cf.Value.String() + } + + // Parse environment variables and configuration from file + var envErr error + var fileErr error + if ParsePriority == ParsePriorityEnv { + envErr = f.ParseEnv(os.Environ()) + if cFile != "" { + fileErr = f.ParseFile(cFile) + } + } else if ParsePriority == ParsePriorityFile { + if cFile != "" { + fileErr = f.ParseFile(cFile) + } + envErr = f.ParseEnv(os.Environ()) + } + + if envErr != nil { switch f.errorHandling { case ContinueOnError: - return err + return envErr case ExitOnError: os.Exit(2) case PanicOnError: - panic(err) + panic(envErr) } - return err + return envErr } - // Parse configuration from file - var cFile string - if cf := f.formal[DefaultConfigFlagname]; cf != nil { - cFile = cf.Value.String() - } - if cf := f.actual[DefaultConfigFlagname]; cf != nil { - cFile = cf.Value.String() - } - if cFile != "" { - if err := f.ParseFile(cFile); err != nil { - switch f.errorHandling { - case ContinueOnError: - return err - case ExitOnError: - os.Exit(2) - case PanicOnError: - panic(err) - } - return err + if fileErr != nil { + switch f.errorHandling { + case ContinueOnError: + return fileErr + case ExitOnError: + os.Exit(2) + case PanicOnError: + panic(fileErr) } + return fileErr } return nil