/ command.go
command.go
  1  package dispatch2
  2  
  3  import (
  4  	"context"
  5  	"fmt"
  6  )
  7  
  8  type Command[Config any] interface {
  9  	After(middlewares ...MiddlewareFunc[Config])
 10  	Aliases() []string
 11  	Before(middlewares ...MiddlewareFunc[Config])
 12  	Execute(context.Context, *Config, []string) error
 13  	Executer() Executer[Config]
 14  	NSubcommands() int
 15  	Name() string
 16  	Register(name, synopsis, usage string, aliases []string, executer Executer[Config]) error
 17  	RegisterCommand(Command[Config]) error
 18  	RegisterFunc(name, synopsis, usage string, aliases []string, executer ExecuterFunc[Config]) error
 19  	Subcommands() []Command[Config]
 20  	Synopsis() string
 21  	Usage() string
 22  }
 23  
 24  type command[Config any] struct {
 25  	afterMiddlewares  []MiddlewareFunc[Config]
 26  	aliases           []string
 27  	beforeMiddlewares []MiddlewareFunc[Config]
 28  	executer          Executer[Config]
 29  	name              string
 30  	subcommands       []Command[Config]
 31  	synopsis          string
 32  	usage             string
 33  }
 34  
 35  var _ Command[struct{}] = &command[struct{}]{}
 36  
 37  func NewCommand[Config any](name, synopsis, usage string, aliases []string, executer Executer[Config]) *command[Config] {
 38  	return &command[Config]{
 39  		aliases:  aliases,
 40  		executer: executer,
 41  		name:     name,
 42  		synopsis: synopsis,
 43  		usage:    usage,
 44  	}
 45  }
 46  
 47  func NewCommandFunc[Config any](name, synopsis, usage string, aliases []string, executer ExecuterFunc[Config]) *command[Config] {
 48  	return &command[Config]{
 49  		aliases:  aliases,
 50  		executer: executer,
 51  		name:     name,
 52  		synopsis: synopsis,
 53  		usage:    usage,
 54  	}
 55  }
 56  func (c *command[Config]) After(middlewares ...MiddlewareFunc[Config]) {
 57  	for _, m := range middlewares {
 58  		c.afterMiddlewares = append(c.afterMiddlewares, invertMiddleware(m))
 59  	}
 60  }
 61  
 62  func (c *command[Config]) Before(middlewares ...MiddlewareFunc[Config]) {
 63  	c.beforeMiddlewares = append(c.beforeMiddlewares, middlewares...)
 64  }
 65  
 66  func (c *command[Config]) Subcommands() []Command[Config] {
 67  	return c.subcommands
 68  }
 69  
 70  func (c *command[Config]) NSubcommands() int {
 71  	return len(c.subcommands)
 72  }
 73  
 74  func (c *command[Config]) Aliases() []string {
 75  	return c.aliases
 76  }
 77  
 78  func (c *command[Config]) Executer() Executer[Config] {
 79  	return c.executer
 80  }
 81  
 82  func (c *command[Config]) Name() string {
 83  	return c.name
 84  }
 85  func (c *command[Config]) Synopsis() string {
 86  	return c.synopsis
 87  }
 88  func (c *command[Config]) Usage() string {
 89  	return c.usage
 90  }
 91  
 92  func (c *command[Config]) RegisterCommand(command Command[Config]) error {
 93  	c.subcommands = append(c.subcommands, command)
 94  	//TODO check if name or alias is taken
 95  	return nil
 96  }
 97  
 98  func (c *command[Config]) Register(name, synopsis, usage string, aliases []string, executer Executer[Config]) error {
 99  	return c.RegisterCommand(NewCommand(name, synopsis, usage, aliases, executer))
100  }
101  
102  func (c *command[Config]) RegisterFunc(name, synopsis, usage string, aliases []string, executerFunc ExecuterFunc[Config]) error {
103  	return c.RegisterCommand(NewCommand(name, synopsis, usage, aliases, executerFunc))
104  }
105  
106  func (c *command[Config]) Execute(ctx context.Context, cfg *Config, args []string) error {
107  	select {
108  	case <-ctx.Done():
109  		return ctx.Err()
110  	default:
111  		executer := c.Executer()
112  		if executer == nil {
113  			return fmt.Errorf("command: cannot execute nil executer")
114  		}
115  
116  		// Apply AFTER middlewares (registration order, inverted)
117  		for _, middleware := range c.afterMiddlewares {
118  			executer = middleware(WrapExecuter(executer))
119  		}
120  
121  		// Before middlewares: (reverse order)
122  		for i := len(c.beforeMiddlewares) - 1; i >= 0; i-- {
123  			executer = c.beforeMiddlewares[i](WrapExecuter(executer))
124  		}
125  
126  		return executer.Execute(ctx, cfg, args)
127  	}
128  }