func checkDuplicateFlags(current *CmdClause, flagGroups []*flagGroup) error {
	for _, flags := range flagGroups {
		for _, flag := range current.flagOrder {
			if flag.shorthand != 0 {
				if _, ok := flags.short[string(flag.shorthand)]; ok {
					return fmt.Errorf("duplicate short flag -%c", flag.shorthand)
				}
			}
			if _, ok := flags.long[flag.name]; ok {
				return fmt.Errorf("duplicate long flag --%s", flag.name)
			}
		}
	}
	flagGroups = append(flagGroups, current.flagGroup)
	for _, subcmd := range current.commandOrder {
		if err := checkDuplicateFlags(subcmd, flagGroups); err != nil {
			return err
		}
	}
	return nil
}
Recursively check commands for duplicate flags.
package kingpin
import (
	"fmt"
	"io"
	"os"
	"strings"
)
var (
	ErrCommandNotSpecified = fmt.Errorf("command not specified")
)
type Action func(*ParseContext) error
type ApplicationValidator func(*Application) error
type Application struct {
	*flagGroup
	*argGroup
	*cmdGroup
	initialized   bool
	Name          string
	Help          string
	author        string
	version       string
	writer        io.Writer  
	usageTemplate string
	action        Action
	preAction     Action
	validator     ApplicationValidator
	terminate     func(status int)  
}
func New(name, help string) *Application {
	a := &Application{
		flagGroup:     newFlagGroup(),
		argGroup:      newArgGroup(),
		Name:          name,
		Help:          help,
		writer:        os.Stderr,
		usageTemplate: DefaultUsageTemplate,
		terminate:     os.Exit,
	}
	a.cmdGroup = newCmdGroup(a)
	a.Flag("help", "Show help (also see --help-long and --help-man).").Bool()
	a.Flag("help-long", "Generate long help.").Hidden().PreAction(a.generateLongHelp).Bool()
	a.Flag("help-man", "Generate a man page.").Hidden().PreAction(a.generateManPage).Bool()
	return a
}
func (a *Application) generateLongHelp(c *ParseContext) error {
	a.Writer(os.Stdout)
	if err := a.UsageForContextWithTemplate(c, 2, LongHelpTemplate); err != nil {
		return err
	}
	a.terminate(0)
	return nil
}
func (a *Application) generateManPage(c *ParseContext) error {
	a.Writer(os.Stdout)
	if err := a.UsageForContextWithTemplate(c, 2, ManPageTemplate); err != nil {
		return err
	}
	a.terminate(0)
	return nil
}
func (a *Application) Terminate(terminate func(int)) *Application {
	if terminate == nil {
		terminate = func(int) {}
	}
	a.terminate = terminate
	return a
}
func (a *Application) Writer(w io.Writer) *Application {
	a.writer = w
	return a
}
func (a *Application) UsageTemplate(template string) *Application {
	a.usageTemplate = template
	return a
}
func (a *Application) Validate(validator ApplicationValidator) *Application {
	a.validator = validator
	return a
}
func (a *Application) ParseContext(args []string) (*ParseContext, error) {
	if err := a.init(); err != nil {
		return nil, err
	}
	context := tokenize(args)
	_, err := parse(context, a)
	return context, err
}
func (a *Application) Parse(args []string) (command string, err error) {
	context, err := a.ParseContext(args)
	if err != nil {
		if a.hasHelp(args) {
			a.writeUsage(context, err)
		}
		return "", err
	}
	a.maybeHelp(context)
	if !context.EOL() {
		return "", fmt.Errorf("unexpected argument '%s'", context.Peek())
	}
	command, err = a.execute(context)
	if err == ErrCommandNotSpecified {
		a.writeUsage(context, nil)
	}
	return command, err
}
func (a *Application) writeUsage(context *ParseContext, err error) {
	if err != nil {
		a.Errorf("%s", err)
	}
	if err := a.UsageForContext(context); err != nil {
		panic(err)
	}
	a.terminate(1)
}
func (a *Application) hasHelp(args []string) bool {
	for _, arg := range args {
		if arg == "--help" {
			return true
		}
	}
	return false
}
func (a *Application) maybeHelp(context *ParseContext) {
	for _, element := range context.Elements {
		if flag, ok := element.Clause.(*FlagClause); ok && flag.name == "help" {
			a.writeUsage(context, nil)
		}
	}
}
func (a *Application) findCommandFromArgs(args []string) (command string, err error) {
	if err := a.init(); err != nil {
		return "", err
	}
	context := tokenize(args)
	if err := a.parse(context); err != nil {
		return "", err
	}
	return a.findCommandFromContext(context), nil
}
func (a *Application) findCommandFromContext(context *ParseContext) string {
	commands := []string{}
	for _, element := range context.Elements {
		if c, ok := element.Clause.(*CmdClause); ok {
			commands = append(commands, c.name)
		}
	}
	return strings.Join(commands, " ")
}
func (a *Application) Version(version string) *Application {
	a.version = version
	a.Flag("version", "Show application version.").Action(func(*ParseContext) error {
		fmt.Println(version)
		a.terminate(0)
		return nil
	}).Bool()
	return a
}
func (a *Application) Author(author string) *Application {
	a.author = author
	return a
}
func (a *Application) Action(action Action) *Application {
	a.action = action
	return a
}
func (a *Application) PreAction(action Action) *Application {
	a.preAction = action
	return a
}
func (a *Application) Command(name, help string) *CmdClause {
	return a.addCommand(name, help)
}
func (a *Application) init() error {
	if a.initialized {
		return nil
	}
	if a.cmdGroup.have() && a.argGroup.have() {
		return fmt.Errorf("can't mix top-level Arg()s with Command()s")
	}
	if a.cmdGroup.have() {
		var command []string
		help := a.Command("help", "Show help.").Action(func(c *ParseContext) error {
			a.Usage(command)
			a.terminate(0)
			return nil
		})
		help.Arg("command", "Show help on command.").StringsVar(&command)
		l := len(a.commandOrder)
		a.commandOrder = append(a.commandOrder[l-1:l], a.commandOrder[:l-1]...)
	}
	if err := a.flagGroup.init(); err != nil {
		return err
	}
	if err := a.cmdGroup.init(); err != nil {
		return err
	}
	if err := a.argGroup.init(); err != nil {
		return err
	}
	for _, cmd := range a.commands {
		if err := cmd.init(); err != nil {
			return err
		}
	}
	flagGroups := []*flagGroup{a.flagGroup}
	for _, cmd := range a.commandOrder {
		if err := checkDuplicateFlags(cmd, flagGroups); err != nil {
			return err
		}
	}
	a.initialized = true
	return nil
}