package cli import ( "errors" "flag" "fmt" "io" "strings" ) var ErrUnknownCommand = errors.New("error: unknown command") type SubcommandFunc = func(*flag.FlagSet) error type Subcommand struct { FlagSet *flag.FlagSet Usage string Func SubcommandFunc } type SubcommandGroup struct { subcommands map[string]Subcommand output io.Writer errorHandling flag.ErrorHandling } func NewSubcommandGroup(output io.Writer, errorHandling flag.ErrorHandling) SubcommandGroup { return SubcommandGroup{subcommands: make(map[string]Subcommand), output: output, errorHandling: errorHandling} } func (sg *SubcommandGroup) AddSubcommand(name string, usage string, fn SubcommandFunc) { fs := flag.NewFlagSet(name, sg.errorHandling) fs.SetOutput(sg.output) sg.subcommands[name] = Subcommand{ FlagSet: fs, Usage: usage, Func: fn, } } func (sg SubcommandGroup) ExecSubcommand(name string) error { cmd, ok := sg.subcommands[name] if !ok { return ErrUnknownCommand } return cmd.Func(cmd.FlagSet) } func (sg SubcommandGroup) Usage() string { var b strings.Builder b.WriteString(" subcommands:\n") for _, cmd := range sg.subcommands { fmt.Fprintf(&b, " %s: %s\n", cmd.FlagSet.Name(), cmd.Usage) } return b.String() }