Compile configuration selector metadata during capture

This commit is contained in:
2026-10-11 13:05:22 +00:00
parent fba917f5bd
commit cec4da69d3
4 changed files with 115 additions and 79 deletions

View File

@@ -56,12 +56,7 @@ func newConfigOperationCommand[I, S any](prepared *preparedSuite[I, S], operatio
flags = append(flags, commandkit.ValueFlag(commandkit.FlagMeta{Name: "path", Usage: "JSON Pointer path to explain.", Required: true}, (*string)(nil), parseConfigString,
func(input **configCommandInput[I, S], value commandkit.Supplied[string]) { (*input).path = value }))
}
selectorIndexes := selectorIndexesForOperation(prepared, operation)
selectorBindings := make([]commandkit.Flag[I], 0, len(selectorIndexes))
for _, index := range selectorIndexes {
selectorBindings = append(selectorBindings, prepared.selectors[index].Binding)
}
flags = append(flags, commandkit.CaptureFlags(selectorBindings, func(input **configCommandInput[I, S]) *commandkit.FlagValues[I] {
flags = append(flags, commandkit.CaptureFlags(prepared.bindingsByOperation[operation], func(input **configCommandInput[I, S]) *commandkit.FlagValues[I] {
if input == nil || *input == nil {
return nil
}
@@ -85,19 +80,6 @@ func newConfigOperationCommand[I, S any](prepared *preparedSuite[I, S], operatio
})
}
func selectorIndexesForOperation[I, S any](prepared *preparedSuite[I, S], operation Operation) []int {
used := make([]int, 0, len(prepared.selectors))
for index := range prepared.selectors {
for _, scope := range prepared.scopes {
if containsOperation(scope.scope.Operations, operation) && selectorApplies(prepared.selectors[index].Scopes, scope.scope.Name) {
used = append(used, index)
break
}
}
}
return used
}
func operationDeclaration(operation Operation) (string, string) {
switch operation {
case Validate:
@@ -133,19 +115,13 @@ func prepareConfigOperation[I, S any](prepared *preparedSuite[I, S], operation O
return fmt.Errorf("scope all is supported only for validate and show")
}
selected := make([]*preparedScope[I, S], 0, len(prepared.scopes))
var selected []*preparedScope[I, S]
if scopeName == "all" {
for _, scope := range orderedScopeRecords(prepared.scopes) {
selected = append(selected, prepared.byName[scope.scope.Name])
}
selected = prepared.scopes
} else if scope, exists := prepared.byName[scopeName]; exists {
selected = append(selected, scope)
selected = []*preparedScope[I, S]{scope}
} else {
choices := make([]string, 0, len(prepared.scopes))
for _, scope := range orderedScopeRecords(prepared.scopes) {
choices = append(choices, scope.scope.Name)
}
return fmt.Errorf("unknown configuration scope %q (available: %s)", scopeName, joinNames(choices))
return fmt.Errorf("unknown configuration scope %q (available: %s)", scopeName, prepared.scopeChoices)
}
for _, scope := range selected {
@@ -175,23 +151,14 @@ func prepareConfigOperation[I, S any](prepared *preparedSuite[I, S], operation O
path: path,
scopes: make([]selectedScopeInput[I, S], 0, len(selected)),
}
operationSelectors := selectorIndexesForOperation(prepared, operation)
capturedSelectors := make(map[int]struct{}, len(operationSelectors))
for _, index := range operationSelectors {
capturedSelectors[index] = struct{}{}
}
for _, scope := range selected {
var value I
if prepared.newInput != nil {
value = prepared.newInput()
}
bindings := make([]commandkit.Flag[I], 0, len(scope.selectorIndexes))
for _, index := range scope.selectorIndexes {
if _, ok := capturedSelectors[index]; ok {
bindings = append(bindings, prepared.selectors[index].Binding)
}
}
if err := input.values.ApplyTo(&value, bindings...); err != nil {
// Availability was checked above, so every binding for this scope
// belongs to the operation's captured union.
if err := input.values.ApplyTo(&value, scope.bindings...); err != nil {
return fmt.Errorf("configuration scope %q: %w", scope.scope.Name, err)
}
if prepared.checkInput != nil {