Compile typed command runners
This commit is contained in:
40
command.go
40
command.go
@@ -119,13 +119,12 @@ type commandPayload interface {
|
||||
hasRun() bool
|
||||
bridgeFlags() []internalcobra.Flag
|
||||
bridgeArguments() []internalcobra.Argument
|
||||
prepare([][]string, []string, bool) (func() any, error)
|
||||
checkInput(any) error
|
||||
run(Invocation, any) Outcome
|
||||
prepare([][]string, []string, bool) (func(*execution) Outcome, error)
|
||||
}
|
||||
|
||||
type typedCommand[I any] struct {
|
||||
spec CommandSpec[I]
|
||||
spec CommandSpec[I]
|
||||
privateRun func(commandExecution, I) Outcome
|
||||
}
|
||||
|
||||
func (c typedCommand[I]) validate() error {
|
||||
@@ -133,7 +132,7 @@ func (c typedCommand[I]) validate() error {
|
||||
}
|
||||
|
||||
func (c typedCommand[I]) hasRun() bool {
|
||||
return c.spec.Run != nil
|
||||
return c.spec.Run != nil || c.privateRun != nil
|
||||
}
|
||||
|
||||
func (c typedCommand[I]) bridgeFlags() []internalcobra.Flag {
|
||||
@@ -167,36 +166,37 @@ func (c typedCommand[I]) bridgeArguments() []internalcobra.Argument {
|
||||
return arguments
|
||||
}
|
||||
|
||||
func (c typedCommand[I]) prepare(flagValues [][]string, operands []string, enforceRequired bool) (func() any, error) {
|
||||
func (c typedCommand[I]) prepare(flagValues [][]string, operands []string, enforceRequired bool) (func(*execution) Outcome, error) {
|
||||
prepared, err := prepareInput(c.spec, flagValues, operands, enforceRequired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return func() any {
|
||||
return func(current *execution) Outcome {
|
||||
input := prepared.build()
|
||||
return &input
|
||||
if c.spec.CheckInput != nil {
|
||||
if err := c.spec.CheckInput(input); err != nil {
|
||||
return classifyInputError(err)
|
||||
}
|
||||
}
|
||||
if c.privateRun != nil {
|
||||
return c.privateRun(current.commandContext(), input)
|
||||
}
|
||||
return c.spec.Run(Invocation{Context: current.ctx, Streams: current.streams}, input)
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c typedCommand[I]) run(invocation Invocation, input any) Outcome {
|
||||
return c.spec.Run(invocation, *input.(*I))
|
||||
}
|
||||
|
||||
func (c typedCommand[I]) checkInput(input any) error {
|
||||
if c.spec.CheckInput == nil {
|
||||
return nil
|
||||
}
|
||||
return c.spec.CheckInput(*input.(*I))
|
||||
}
|
||||
|
||||
// NewCommand captures a typed command declaration. Construction issues are
|
||||
// retained and reported when the declaration is installed.
|
||||
func NewCommand[I any](spec CommandSpec[I]) Command {
|
||||
return captureCommand(spec, nil)
|
||||
}
|
||||
|
||||
func captureCommand[I any](spec CommandSpec[I], privateRun func(commandExecution, I) Outcome) Command {
|
||||
copySpec := spec
|
||||
copySpec.Flags = append([]Flag[I](nil), spec.Flags...)
|
||||
copySpec.Arguments = append([]Argument[I](nil), spec.Arguments...)
|
||||
copySpec.Children = append([]Command(nil), spec.Children...)
|
||||
payload := typedCommand[I]{spec: copySpec}
|
||||
payload := typedCommand[I]{spec: copySpec, privateRun: privateRun}
|
||||
record := &commandRecord{
|
||||
name: spec.Name, summary: spec.Summary, description: spec.Description,
|
||||
children: copySpec.Children, payload: payload,
|
||||
|
||||
Reference in New Issue
Block a user