package flagx import ( "encoding" "flag" "fmt" "os" "strings" "time" ) var commandLine = []*flag.FlagSet{ flag.NewFlagSet(os.Args[0], flag.ContinueOnError), } func init() { Parse() } func findProperFlagSet(name string) *flag.FlagSet { for _, cl := range commandLine { if cl.Lookup(name) == nil { return cl } } next := flag.NewFlagSet(fmt.Sprintf("%s-%d", os.Args[0], len(commandLine)), flag.ContinueOnError) commandLine = append(commandLine, next) return next } func VisitAll(fn func(*flag.Flag)) { for _, cl := range commandLine { cl.VisitAll(fn) } } // Visit visits the command-line flags in lexicographical order, calling fn // for each. It visits only those flags that have been set. func Visit(fn func(*flag.Flag)) { for _, cl := range commandLine { cl.Visit(fn) } } func Lookup(name string) *flag.Flag { for _, cl := range commandLine { f := cl.Lookup(name) if f != nil { return f } } return nil } func Set(name, value string) error { for _, cl := range commandLine { if cl.Lookup(name) != nil { return cl.Set(name, value) } } return fmt.Errorf("no such flag -%v", name) } func PrintDefaults() { for _, cl := range commandLine { cl.PrintDefaults() } } func BoolVar(p *bool, name string, value bool, usage string) { findProperFlagSet(name).BoolVar(p, name, value, usage) } func Bool(name string, value bool, usage string) *bool { return findProperFlagSet(name).Bool(name, value, usage) } func IntVar(p *int, name string, value int, usage string) { findProperFlagSet(name).IntVar(p, name, value, usage) } func Int(name string, value int, usage string) *int { return findProperFlagSet(name).Int(name, value, usage) } func Int64Var(p *int64, name string, value int64, usage string) { findProperFlagSet(name).Int64Var(p, name, value, usage) } func Int64(name string, value int64, usage string) *int64 { return findProperFlagSet(name).Int64(name, value, usage) } func UintVar(p *uint, name string, value uint, usage string) { findProperFlagSet(name).UintVar(p, name, value, usage) } func Uint(name string, value uint, usage string) *uint { return findProperFlagSet(name).Uint(name, value, usage) } func Uint64Var(p *uint64, name string, value uint64, usage string) { findProperFlagSet(name).Uint64Var(p, name, value, usage) } func Uint64(name string, value uint64, usage string) *uint64 { return findProperFlagSet(name).Uint64(name, value, usage) } func StringVar(p *string, name string, value string, usage string) { findProperFlagSet(name).StringVar(p, name, value, usage) } func String(name string, value string, usage string) *string { return findProperFlagSet(name).String(name, value, usage) } func Float64Var(p *float64, name string, value float64, usage string) { findProperFlagSet(name).Float64Var(p, name, value, usage) } func Float64(name string, value float64, usage string) *float64 { return findProperFlagSet(name).Float64(name, value, usage) } func DurationVar(p *time.Duration, name string, value time.Duration, usage string) { findProperFlagSet(name).DurationVar(p, name, value, usage) } func Duration(name string, value time.Duration, usage string) *time.Duration { return findProperFlagSet(name).Duration(name, value, usage) } func TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) { findProperFlagSet(name).TextVar(p, name, value, usage) } func Func(name, usage string, fn func(string) error) { findProperFlagSet(name).Func(name, usage, fn) } func Var(value flag.Value, name string, usage string) { findProperFlagSet(name).Var(value, name, usage) } func Parse() { args := os.Args[1:] for _, cl := range commandLine { if cl.Parsed() { continue } var filtered []string cl.VisitAll(func(f *flag.Flag) { for _, arg := range args { test := strings.TrimLeft(arg, "-") if test == f.Name || strings.HasPrefix(test, f.Name+"=") { filtered = append(filtered, arg) break } } }) cl.Parse(filtered) } } func Parsed() bool { for _, cl := range commandLine { if !cl.Parsed() { return false } } return true } func NewFlagSet(name string, errorHandling flag.ErrorHandling) *flag.FlagSet { return flag.NewFlagSet(name, errorHandling) }