package cli import ( "errors" "flag" "fmt" "io" "time" ) type GlobalOpts struct { ConfigPath string Debug bool ConfigStanza string } func (o GlobalOpts) String() string { return "--config --debug --account" } type Command interface { Func([]string) error Help(io.Writer, *flag.FlagSet) } type CommandMap map[string]Command type ProgramInfo struct { Name string Opts GlobalOpts Commands CommandMap } func Usage(w io.Writer, info ProgramInfo) { fmt.Fprintf(w, "USAGE: %s [%s] SUBCOMMAND [subcommand opts]\n", info.Name, info.Opts) fmt.Fprintf(w, "\nSUBCOMMANDS:\n") for command := range info.Commands { fmt.Fprintf(w, "\t%s\n", command) } } type Pair struct { Set, Unset bool } type PairFlag struct { *Pair } func NewPairFlag() PairFlag { return PairFlag{ &Pair{false, false}, } } func (p Pair) String() string { switch p { case Pair{true, false}: return "set" case Pair{false, true}: return "unset" default: return "undef" } } func (pf PairFlag) String() string { return fmt.Sprint(pf.Pair) } func (pf PairFlag) Set(s string) error { if s == "set" { v := Pair{true, false} *pf.Pair = v return nil } if s == "unset" { v := Pair{false, true} *pf.Pair = v return nil } return ErrAllowedPairFlagValues } var ErrAllowedPairFlagValues = errors.New("only `set` or `unset` are allowed") type AbsTimeFlag struct { *time.Time } func NewAbsTimeFlag() AbsTimeFlag { return AbsTimeFlag{ Time: &time.Time{}, } } func (t AbsTimeFlag) String() string { return fmt.Sprint(t.Time) } func (t AbsTimeFlag) Set(s string) error { const layout = "2006-01-02T15:04:05" var parsedTime time.Time var err error if s == "" { t.Time = &parsedTime return nil } parsedTime, err = time.Parse(layout, s) if err != nil { return err } t.Time = &parsedTime return nil }