119 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			119 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
| package cmd
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 
 | |
| 	"go.fifitido.net/cmd/opt"
 | |
| )
 | |
| 
 | |
| type Command struct {
 | |
| 	Name             string
 | |
| 	version          string
 | |
| 	ShortDescription string
 | |
| 	LongDescription  string
 | |
| 	Aliases          []string
 | |
| 	Args             []*Argument
 | |
| 	Opts             opt.Set
 | |
| 	Subcommands      Set
 | |
| 	Parent           *Command
 | |
| 	run              func(args []string)
 | |
| 	isRoot           bool
 | |
| }
 | |
| 
 | |
| func NewRoot(name string, version string, options ...Option) *Command {
 | |
| 	cmd := &Command{Name: name, version: version, isRoot: true}
 | |
| 	cmd.ApplyOptions(options...)
 | |
| 	return cmd
 | |
| }
 | |
| 
 | |
| func New(name string, options ...Option) *Command {
 | |
| 	cmd := &Command{Name: name}
 | |
| 	cmd.ApplyOptions(options...)
 | |
| 	return cmd
 | |
| }
 | |
| 
 | |
| func (c *Command) ApplyOptions(options ...Option) {
 | |
| 	for _, option := range options {
 | |
| 		option(c)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (c *Command) Root() *Command {
 | |
| 	if c.isRoot {
 | |
| 		return c
 | |
| 	}
 | |
| 
 | |
| 	return c.Parent.Root()
 | |
| }
 | |
| 
 | |
| func (c *Command) IsRoot() bool {
 | |
| 	return c.isRoot
 | |
| }
 | |
| 
 | |
| func (c *Command) CommandPath() string {
 | |
| 	if c.Parent == nil {
 | |
| 		return ""
 | |
| 	}
 | |
| 
 | |
| 	parentPath := c.Parent.CommandPath()
 | |
| 	if parentPath == "" {
 | |
| 		return c.Name
 | |
| 	}
 | |
| 
 | |
| 	return c.Parent.CommandPath() + " " + c.Name
 | |
| }
 | |
| 
 | |
| func (c *Command) CanRun() bool {
 | |
| 	return c.run != nil
 | |
| }
 | |
| 
 | |
| func (c *Command) Run(args []string) {
 | |
| 	c.run(args)
 | |
| }
 | |
| 
 | |
| func (c *Command) Execute(args []string) {
 | |
| 	if c.isRoot {
 | |
| 		args = args[1:]
 | |
| 	}
 | |
| 	if len(args) > 0 {
 | |
| 		sc, ok := c.Subcommands.Get(args[0])
 | |
| 		if ok {
 | |
| 			sc.Execute(args[1:])
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	parser := opt.NewParser(args, c.Opts, false)
 | |
| 	restArgs, err := parser.Parse()
 | |
| 	if err != nil {
 | |
| 		fmt.Println(err.Error())
 | |
| 		c.ShowHelp()
 | |
| 		os.Exit(1)
 | |
| 	}
 | |
| 
 | |
| 	versionOpt, ok := opt.Globals().GetBool("version")
 | |
| 	if ok && versionOpt.Value() {
 | |
| 		c.ShowVersion()
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	helpOpt, ok := opt.Globals().GetBool("help")
 | |
| 	if ok && helpOpt.Value() {
 | |
| 		c.ShowHelp()
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	if c.CanRun() {
 | |
| 		c.Run(restArgs)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	c.ShowHelp()
 | |
| }
 | |
| 
 | |
| func (c *Command) ShowVersion() {
 | |
| 	rootName := c.Root().Name
 | |
| 	fmt.Printf("%s %s\n", rootName, c.version)
 | |
| }
 |