91 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
	
	
| package cmd
 | |
| 
 | |
| import (
 | |
| 	"os"
 | |
| 	"path/filepath"
 | |
| 
 | |
| 	"go.fifitido.net/cmd/flags"
 | |
| )
 | |
| 
 | |
| type Command struct {
 | |
| 	Name             string
 | |
| 	ShortDescription string
 | |
| 	LongDescription  string
 | |
| 	aliases          []string
 | |
| 	arguments        []*Argument
 | |
| 	flags            []flags.Flag
 | |
| 	subcommands      []*Command
 | |
| 	parent           *Command
 | |
| 	run              func(args []string)
 | |
| 	isRoot           bool
 | |
| }
 | |
| 
 | |
| func NewRoot(options ...Option) *Command {
 | |
| 	cmd := &Command{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) CommandPath() string {
 | |
| 	if c.parent == nil {
 | |
| 		return filepath.Base(os.Args[0])
 | |
| 	}
 | |
| 
 | |
| 	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 {
 | |
| 		for _, subcommand := range c.subcommands {
 | |
| 			if subcommand.Name == args[0] {
 | |
| 				subcommand.Execute(args[1:])
 | |
| 				return
 | |
| 			}
 | |
| 
 | |
| 			for _, alias := range subcommand.aliases {
 | |
| 				if alias == args[0] {
 | |
| 					subcommand.Execute(args[1:])
 | |
| 					return
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		// TODO: remove when done with flag parsing
 | |
| 		if args[0] == "--help" {
 | |
| 			c.ShowHelp()
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if c.CanRun() {
 | |
| 		c.Run(args)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	c.ShowHelp()
 | |
| }
 |