// SetFlagsFromEnv parses all registered flags in the given flagset, // and if they are not already set it attempts to set their values from // environment variables. Environment variables take the name of the flag but // are UPPERCASE, have the prefix "PREFIX_", and any dashes are replaced by // underscores - for example: some-flag => PREFIX_SOME_FLAG func SetFlagsFromEnv(fs *flag.FlagSet, prefix string) error { var err error alreadySet := make(map[string]bool) fs.Visit(func(f *flag.Flag) { alreadySet[f.Name] = true }) if prefix == "" { prefix = "_" } else { prefix = strings.ToUpper(strings.Replace(prefix, "-", "_", -1)) } fs.VisitAll(func(f *flag.Flag) { if !alreadySet[f.Name] { key := prefix + strings.ToUpper(strings.Replace(f.Name, "-", "_", -1)) val := os.Getenv(key) if val != "" { if serr := fs.Set(f.Name, val); serr != nil { err = fmt.Errorf("invalid value %q for %s: %v", val, key, serr) } } } }) return err }
// SetFlagsFromYaml goes through all registered flags in the given flagset, // and if they are not already set it attempts to set their values from // the YAML config. It will use the key REPLACE(UPPERCASE(flagname), '-', '_') func SetFlagsFromYaml(fs *flag.FlagSet, rawYaml []byte) (err error) { conf := make(map[string]string) if err = yaml.Unmarshal(rawYaml, conf); err != nil { return } alreadySet := map[string]struct{}{} fs.Visit(func(f *flag.Flag) { alreadySet[f.Name] = struct{}{} }) errs := make([]error, 0) fs.VisitAll(func(f *flag.Flag) { if f.Name == "" { return } if _, ok := alreadySet[f.Name]; ok { return } tag := strings.Replace(strings.ToUpper(f.Name), "-", "_", -1) val, ok := conf[tag] if !ok { return } if serr := fs.Set(f.Name, val); serr != nil { errs = append(errs, fmt.Errorf("invalid value %q for %s: %v", val, tag, serr)) } }) if len(errs) != 0 { err = ErrorSlice(errs) } return }
func usageFor(fs *flag.FlagSet, usage string, extra string) func() { return func() { var b bytes.Buffer b.WriteString("Usage:\n " + usage + "\n") var options [][]string fs.VisitAll(func(f *flag.Flag) { var opt = " -" + f.Name if f.DefValue == "[]" { f.DefValue = "" } if f.DefValue != "false" { opt += "=" + fmt.Sprintf(`"%s"`, f.DefValue) } options = append(options, []string{opt, f.Usage}) }) if len(options) > 0 { b.WriteString("\nOptions:\n") optionTable(&b, options) } fmt.Println(b.String()) if len(extra) > 0 { fmt.Println(extra) } } }
func getFlags(flagset *flag.FlagSet) (flags []*flag.Flag) { flags = make([]*flag.Flag, 0) flagset.VisitAll(func(f *flag.Flag) { flags = append(flags, f) }) return }
func hasFlags(flags *flag.FlagSet) bool { any := false flags.VisitAll(func(*flag.Flag) { any = true }) return any }
// Usage returns a usage documentation of a command. func (c Command) Usage(flags *flag.FlagSet) string { usage := fmt.Sprintf("Usage: %s", c.Long) if flags == nil { return usage } var hasFlag bool flags.VisitAll(func(_ *flag.Flag) { hasFlag = true }) if hasFlag == false { return usage } buf := bytes.NewBufferString(usage) buf.WriteString("\n\nOptions:\n") defer flags.SetOutput(nil) flags.SetOutput(buf) flags.PrintDefaults() return buf.String() }
func usageFor(fs *flag.FlagSet, usage string) func() { return func() { var b bytes.Buffer b.WriteString(ansi.Bold("Usage:") + "\n " + usage + "\n") var options [][]string fs.VisitAll(func(f *flag.Flag) { var opt = " -" + f.Name if f.DefValue != "false" { opt += "=" + f.DefValue } options = append(options, []string{opt, f.Usage}) }) if len(options) > 0 { b.WriteString("\n" + ansi.Bold("Options:") + "\n") optionTable(&b, options) } fmt.Println(b.String()) } }
// checkCommandLine ensures all required positional and flag-like parameters // are set. Returns true if they are, or false (and prints to stderr) if not. func checkCommandLine(args []string, flags *flag.FlagSet, minPosCount, maxPosCount int) bool { // Check number of expected positional arguments. if maxPosCount == 0 && len(args) != 0 { log.Errorf("Unexpected arguments: %v", args) return false } if len(args) < minPosCount || len(args) > maxPosCount { log.Errorf("Expecting [%d, %d] arguments, got %d", minPosCount, maxPosCount, len(args)) return false } // Check required unset flags. unset := []*flag.Flag{} flags.VisitAll(func(f *flag.Flag) { if strings.HasPrefix(f.DefValue, "<") && f.Value.String() == f.DefValue { unset = append(unset, f) } }) if len(unset) != 0 { missing := []string{} for _, f := range unset { missing = append(missing, f.Name) } log.Errorf("Missing required flags: %v", missing) return false } return true }
// ParseSet parses the given flagset. The specified prefix will be applied to // the environment variable names. func ParseSet(prefix string, set *flag.FlagSet) error { var explicit []*flag.Flag var all []*flag.Flag set.Visit(func(f *flag.Flag) { explicit = append(explicit, f) }) var err error set.VisitAll(func(f *flag.Flag) { if err != nil { return } all = append(all, f) if !contains(explicit, f) { name := strings.Replace(f.Name, ".", "_", -1) name = strings.Replace(name, "-", "_", -1) if prefix != "" { name = prefix + name } name = strings.ToUpper(name) val := os.Getenv(name) if val != "" { if ferr := f.Value.Set(val); ferr != nil { err = fmt.Errorf("failed to set flag %q with value %q", f.Name, val) } } } }) return err }
func commandHelp(name string, cmd Command, f *flag.FlagSet) { type HasUsage interface { Usage() string } fmt.Fprintf(os.Stderr, "Usage: %s %s [OPTIONS]", os.Args[0], name) if u, ok := cmd.(HasUsage); ok { fmt.Fprintf(os.Stderr, " %s", u.Usage()) } fmt.Fprintf(os.Stderr, "\n") type HasDescription interface { Description() string } if u, ok := cmd.(HasDescription); ok { fmt.Fprintf(os.Stderr, "%s\n", u.Description()) } n := 0 f.VisitAll(func(_ *flag.Flag) { n += 1 }) if n > 0 { fmt.Fprintf(os.Stderr, "\nOptions:\n") tw := tabwriter.NewWriter(os.Stderr, 2, 0, 2, ' ', 0) f.VisitAll(func(f *flag.Flag) { fmt.Fprintf(tw, "\t-%s=%s\t%s\n", f.Name, f.DefValue, f.Usage) }) tw.Flush() } }
// AddGoFlagSet will add the given *flag.FlagSet to the flag.FlagSet func (f *FlagSet) AddGoFlagSet(newSet *goflag.FlagSet) { if newSet == nil { return } newSet.VisitAll(func(goflag *goflag.Flag) { f.AddGoFlag(goflag) }) }
// printCommandHelp is used by handlers to display command help. func printCommandHelp(handler Handler, flags *flag.FlagSet) { fmt.Println("SYNTAX") fmt.Println("\t" + handler.Syntax()) fmt.Println("") fmt.Println("OPTIONS:") flags.VisitAll(func(f *flag.Flag) { fmt.Printf("\t-%-10s%s\n", f.Name, f.Usage) }) }
func hasFlags(f flag.FlagSet) bool { nFlags := 0 f.VisitAll(func(*flag.Flag) { nFlags++ }) if nFlags != 0 { return true } return false }
// ParseSet parses the config file for the provided flag set. // If the flags are already set, values are overwritten // by the values in the config file. Defaults are not set // if the flag is not in the file. func (g *GlobalConf) ParseSet(flagSetName string, set *flag.FlagSet) { set.VisitAll(func(f *flag.Flag) { if val, ok := getEnv(g.EnvPrefix, flagSetName, f.Name); ok { set.Set(f.Name, val) return } val, found := g.dict.GetString(flagSetName, f.Name) if found { set.Set(f.Name, val) } }) }
func completeFlags(cl CommandLine, flags *flag.FlagSet) (completions []string, rest CommandLine) { if len(cl) == 0 { return nil, cl } var inFlag string for len(cl) > 1 { w := cl[0] if inFlag != "" { inFlag = "" } else if len(w) > 1 && w[0] == '-' && w != "--" { if !strings.Contains(w, "=") { var i int for i = 0; i < len(w) && w[i] == '-'; i++ { } inFlag = w[i:] } if flag := flags.Lookup(inFlag); flag != nil { if bf, ok := flag.Value.(boolFlag); ok && bf.IsBoolFlag() { inFlag = "" } } } else { if w == "--" { cl = cl[1:] } return nil, cl } cl = cl[1:] } if inFlag != "" { // Complete a flag value. No-op for now. return []string{}, nil } else if len(cl[0]) > 0 && cl[0][0] == '-' { // complete a flag name prefix := strings.TrimLeft(cl[0], "-") flags.VisitAll(func(f *flag.Flag) { if strings.HasPrefix(f.Name, prefix) { completions = append(completions, "-"+f.Name) } }) return completions, nil } if cl[0] == "" { flags.VisitAll(func(f *flag.Flag) { completions = append(completions, "-"+f.Name) }) } return completions, cl }
// Parses the config file for the provided flag set. // If the flags are already set, values are overwritten // by the values in the config file. Defaults are not set // if the flag is not in the file. func (g *GlobalConf) ParseSet(flagSetName string, set *flag.FlagSet) { set.VisitAll(func(f *flag.Flag) { val := getEnv(flagSetName, f.Name) if val != "" { set.Set(f.Name, val) return } val, found := g.dict.GetString(flagSetName, f.Name) if found { set.Set(f.Name, val) } }) }
// SetFlagsFromEnv parses all registered flags in the given flagset, // and if they are not already set it attempts to set their values from // environment variables. Environment variables take the name of the flag but // are UPPERCASE, have the given prefix and any dashes are replaced by // underscores - for example: some-flag => ETCD_SOME_FLAG func SetFlagsFromEnv(prefix string, fs *flag.FlagSet) error { var err error alreadySet := make(map[string]bool) fs.Visit(func(f *flag.Flag) { alreadySet[flagToEnv(prefix, f.Name)] = true }) usedEnvKey := make(map[string]bool) fs.VisitAll(func(f *flag.Flag) { err = setFlagFromEnv(fs, prefix, f.Name, usedEnvKey, alreadySet, true) }) verifyEnv(prefix, usedEnvKey, alreadySet) return err }
// flagsFromEnv parses all registered flags in the given flagset, // and if they are not already set it attempts to set their values from // environment variables. Environment variables take the name of the flag but // are UPPERCASE, have the given prefix, and any dashes are replaced by // underscores - for example: some-flag => PREFIX_SOME_FLAG func flagsFromEnv(prefix string, fs *flag.FlagSet) { alreadySet := make(map[string]bool) fs.Visit(func(f *flag.Flag) { alreadySet[f.Name] = true }) fs.VisitAll(func(f *flag.Flag) { if !alreadySet[f.Name] { key := strings.ToUpper(prefix + "_" + strings.Replace(f.Name, "-", "_", -1)) val := os.Getenv(key) if val != "" { fs.Set(f.Name, val) } } }) }
// helpFlags builds the text in 'help' regarding available command flags. func helpFlags(fp *flag.FlagSet) string { result := "" fp.VisitAll(func(f *flag.Flag) { if f.DefValue != "" { result = result + " -" + f.Name + "=" + f.DefValue + "\n " + f.Usage } else { result = result + " -" + f.Name + "\n " + f.Usage } result = result + "\n" }) if result != "" { result = "Full Options:\n" + result } return result }
func UsageWithIgnoredFlagsFunc(fs *flag.FlagSet, ignore []string) func() { iMap := make(map[string]struct{}, len(ignore)) for _, name := range ignore { iMap[name] = struct{}{} } return func() { fs.VisitAll(func(f *flag.Flag) { if _, ok := iMap[f.Name]; ok { return } format := " -%s=%s: %s\n" fmt.Fprintf(os.Stderr, format, f.Name, f.DefValue, f.Usage) }) } }
// processField generates a flag based on the given field and fieldName. If a // nested struct is detected, a flag for each field of that nested struct is // generated too. func (f *FlagLoader) processField(flagSet *flag.FlagSet, fieldName string, field *structs.Field) error { if !field.IsExported() { return nil } if f.CamelCase { fieldName = strings.Join(camelcase.Split(fieldName), "-") } switch { case field.Kind() == reflect.Struct && !implementsTextUnmarshaler(field): for _, ff := range field.Fields() { flagName := fieldName + "-" + ff.Name() if f.Flatten { // first check if it's set or not, because if we have duplicate // we don't want to break the flag. Panic by giving a readable // output flagSet.VisitAll(func(fl *flag.Flag) { if strings.ToLower(ff.Name()) == fl.Name { // already defined panic(fmt.Sprintf("flag '%s' is already defined in outer struct", fl.Name)) } }) flagName = ff.Name() } if err := f.processField(flagSet, flagName, ff); err != nil { return err } } case field.Kind() == reflect.Ptr: field.InitElem() return f.processField(flagSet, fieldName, field) default: // Add custom prefix to the flag if it's set if f.Prefix != "" { fieldName = f.Prefix + "-" + fieldName } flagSet.Var(newFieldValue(field), flagName(fieldName), flagUsage(fieldName)) } return nil }
// processField generates a flag based on the given field and fieldName. If a // nested struct is detected, a flag for each field of that nested struct is // generated too. func (f *FlagLoader) processField(flagSet *flag.FlagSet, fieldName string, field *structs.Field) error { if f.CamelCase { fieldName = strings.Join(camelcase.Split(fieldName), "-") } switch field.Kind() { case reflect.Struct: for _, ff := range field.Fields() { flagName := field.Name() + "-" + ff.Name() if f.Flatten { // first check if it's set or not, because if we have duplicate // we don't want to break the flag. Panic by giving a readable // output flagSet.VisitAll(func(fl *flag.Flag) { if strings.ToLower(ff.Name()) == fl.Name { // already defined panic(fmt.Sprintf("flag '%s' is already defined in outer struct", fl.Name)) } }) flagName = ff.Name() } if err := f.processField(flagSet, flagName, ff); err != nil { return err } } default: // First see tag, if exists, use tag instead of fieldname flagTag := field.Tag(f.FlagTagName) if flagTag != "" { fieldName = flagTag } else if f.Prefix != "" { fieldName = f.Prefix + "-" + fieldName } // we only can get the value from expored fields, unexported fields panics if field.IsExported() { flagSet.Var(newFieldValue(field), flagName(fieldName), flagUsage(fieldName)) } } return nil }
func addFlagsToContext(flagset *flag.FlagSet, cxt cookoo.Context) { store := func(f *flag.Flag) { // fmt.Printf("Storing %s in context with value %s.\n", f.Name, f.Value.String()) // Basically, we can tell the difference between booleans and strings, and that's it. // Other types are a loss. /* if f.IsBoolFlag != nil { cxt.Put(f.Name, f.Value.String() == "true") } else { cxt.Put(f.Name, f.Value.String()) } */ cxt.Put(f.Name, f.Value.String()) } flagset.VisitAll(store) }
// from github.com/coreos/etcd // // SetFlagsFromEnv parses all registered flags in the given flagset, // and if they are not already set it attempts to set their values from // environment variables. Environment variables take the name of the flag but // are UPPERCASE, have the prefix `s`, and any dashes are replaced by // underscores - for example: some-flag => ETCD_SOME_FLAG func AddEnvironmentToFlags(s string, fs *flag.FlagSet) error { var err error alreadySet := make(map[string]bool) fs.Visit(func(f *flag.Flag) { alreadySet[f.Name] = true }) fs.VisitAll(func(f *flag.Flag) { if !alreadySet[f.Name] { key := s + "_" + ToEnvironmentKey(f.Name) val := os.Getenv(key) if val != "" { if serr := fs.Set(f.Name, val); serr != nil { err = fmt.Errorf("invalid value %q for %s: %v", val, key, serr) } } } }) return err }
// MustFlag sets flags that are skipped by dst.Parse when p contains // the respective key for flag.Flag.Name. // // It's use is recommended with command line arguments as in: // flag.Parse() // p.MustFlag(flag.CommandLine) func (p *Properties) MustFlag(dst *flag.FlagSet) { m := make(map[string]*flag.Flag) dst.VisitAll(func(f *flag.Flag) { m[f.Name] = f }) dst.Visit(func(f *flag.Flag) { delete(m, f.Name) // overridden }) for name, f := range m { v, ok := p.Get(name) if !ok { continue } if err := f.Value.Set(v); err != nil { ErrorHandler(err) } } }
// Populate sets the flags in set from the environment. The // environment value used will be the name of the flag in upper case, // with '-' changed to '_', and (if prefixis not the empty string) // prepended with prefix and an underscore. So, if prefix is // "DOORMAN", and the flag's name "foo-bar", the environment variable // DOORMAN_FOO_BAR will be used. func Populate(set *flag.FlagSet, prefix string) error { var ( setThroughFlags = make(map[string]bool) knownEnv = make(map[string]bool) err error ) set.Visit(func(f *flag.Flag) { setThroughFlags[f.Name] = true }) set.VisitAll(func(f *flag.Flag) { key := flagToEnv(prefix, f.Name) knownEnv[key] = true val := os.Getenv(key) if val == "" { return } if setThroughFlags[f.Name] { log.Warningf("Recognized environment variable %v, but shadowed by flag %v: won't be used.", key, f.Name) return } if e := set.Set(f.Name, val); e != nil { err = fmt.Errorf("Invalid value %q for %v.", val, key) return } }) for _, env := range os.Environ() { kv := strings.SplitN(env, "=", 2) if len(kv) < 1 { continue } if name := kv[0]; strings.HasPrefix(name, prefix) && !knownEnv[name] { log.Warningf("Unrecognized environment variable %s", name) } } return err }
// SetFlagsFromEnv parses all registered flags in the given flagset, // and if they are not already set it attempts to set their values from // environment variables. Environment variables take the name of the flag but // are UPPERCASE, have the prefix "ETCD_", and any dashes are replaced by // underscores - for example: some-flag => ETCD_SOME_FLAG func SetFlagsFromEnv(fs *flag.FlagSet) error { var err error alreadySet := make(map[string]bool) fs.Visit(func(f *flag.Flag) { alreadySet[flagToEnv(f.Name)] = true }) usedEnvKey := make(map[string]bool) fs.VisitAll(func(f *flag.Flag) { key := flagToEnv(f.Name) if !alreadySet[key] { val := os.Getenv(key) if val != "" { usedEnvKey[key] = true if serr := fs.Set(f.Name, val); serr != nil { err = fmt.Errorf("invalid value %q for %s: %v", val, key, serr) } plog.Infof("recognized and used environment variable %s=%s", key, val) } } }) for _, env := range os.Environ() { kv := strings.SplitN(env, "=", 2) if len(kv) != 2 { plog.Warningf("found invalid env %s", env) } if usedEnvKey[kv[0]] { continue } if alreadySet[kv[0]] { plog.Infof("recognized environment variable %s, but unused: shadowed by corresponding flag ", kv[0]) continue } if strings.HasPrefix(env, "ETCD_") { plog.Warningf("unrecognized environment variable %s", env) } } return err }
func optionsUsage(flagSet *flag.FlagSet) { w := newTabWriter() flagSet.VisitAll(func(f *flag.Flag) { v := f.Value if _, ok := v.(*boolValue); ok { if f.DefValue == "false" { fmt.Fprintf(w, " -%s\t%s\n", f.Name, f.Usage) } else { fmt.Fprintf(w, " -%s=true\t%s\n", f.Name, f.Usage) } } else { if flagIsString(f) { fmt.Fprintf(w, " -%s %q\t%s\n", f.Name, f.DefValue, f.Usage) } else { fmt.Fprintf(w, " -%s %s\t%s\n", f.Name, f.DefValue, f.Usage) } } }) w.Flush() }
// FilterArgs filters the args slice to only include the the flags // in the given flagset and returns a new arg slice that has the // included args as well as a slice that has only the excluded args. // The final returned slice is the positional arguments. func FilterArgs(fs *flag.FlagSet, args []string) ([]string, []string, []string) { // Optimistically make all the length of the arguments. There // should never be so many arguments that this is too ineffecient. inc := make([]string, 0, len(args)) exc := make([]string, 0, len(args)) pos := make([]string, 0, len(args)) // Make a map of the valid flags flags := make(map[string]struct{}) fs.VisitAll(func(f *flag.Flag) { flags[f.Name] = struct{}{} }) // Go through each, parse out a single argument, and determine where // it should go plus how many of the slots. i := 0 for i < len(args) { n, loc := filterOne(flags, args, i) // Determine what slice to add the values to var result *[]string switch loc { case filterLocBoth: result = &pos case filterLocInc: result = &inc case filterLocExc: result = &exc } // Copy the values *result = append(*result, args[i:i+n]...) // Increment i so we continue moving through the arguments i += n } return inc, exc, pos }
func flags() *flag.FlagSet { var f flag.FlagSet f.BoolVar(&testing, "testing", testing, "print data w/o saving") f.BoolVar(&snmpNames, "names", snmpNames, "print column names and exit") f.StringVar(&configFile, "config", configFile, "config file") f.BoolVar(&verbose, "verbose", verbose, "verbose mode") f.IntVar(&repeat, "repeat", repeat, "number of times to repeat") f.IntVar(&freq, "freq", freq, "delay (in seconds)") f.IntVar(&httpPort, "http", httpPort, "http port") f.StringVar(&logDir, "logs", logDir, "log directory") f.Usage = func() { fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) f.VisitAll(func(flag *flag.Flag) { format := "%10s: %s\n" fmt.Fprintf(os.Stderr, format, "-"+flag.Name, flag.Usage) }) fmt.Fprintf(os.Stderr, "\nAll settings can be set in config file: %s\n", configFile) os.Exit(1) } return &f }