Preserve ordered flag occurrences
This commit is contained in:
@@ -3,6 +3,7 @@ package commandkit
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// ErrFlagInput identifies a missing required captured flag selected for an input.
|
||||
@@ -13,7 +14,8 @@ var ErrFlagWiring = errors.New("flag wiring is invalid")
|
||||
|
||||
// FlagValues stores invocation-local converted values and presence for captured
|
||||
// flags. It does not retain an input instance; values can be applied to
|
||||
// independently initialized destinations.
|
||||
// independently initialized destinations. Captured occurrence flags retain
|
||||
// their relative command-line order across the selected bindings.
|
||||
type FlagValues[I any] struct {
|
||||
values map[*bindingIdentity]preparedValue[I]
|
||||
}
|
||||
@@ -42,7 +44,7 @@ func CaptureFlags[Outer, I any](flags []Flag[I], target func(*Outer) *FlagValues
|
||||
if err != nil {
|
||||
return preparedValue[Outer]{}, err
|
||||
}
|
||||
return preparedValue[Outer]{
|
||||
result := preparedValue[Outer]{
|
||||
identity: identity,
|
||||
supplied: prepared.supplied,
|
||||
apply: func(outer *Outer) {
|
||||
@@ -55,7 +57,11 @@ func CaptureFlags[Outer, I any](flags []Flag[I], target func(*Outer) *FlagValues
|
||||
}
|
||||
store.values[inner.binding.identity] = prepared
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
for _, occurrence := range prepared.ordered {
|
||||
result.ordered = append(result.ordered, preparedOccurrence[Outer]{ordinal: occurrence.ordinal})
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
captured[index] = Flag[Outer]{binding: binding}
|
||||
@@ -66,11 +72,14 @@ func CaptureFlags[Outer, I any](flags []Flag[I], target func(*Outer) *FlagValues
|
||||
// ApplyTo applies selected original captured flags to an initialized
|
||||
// destination. A missing captured binding or nil destination matches
|
||||
// ErrFlagWiring. A required selected value that was not supplied matches
|
||||
// ErrFlagInput. Repeated core-owned values are copied for each application.
|
||||
// ErrFlagInput. Ordinary selected values are applied first, followed by selected
|
||||
// occurrence values in command-line order. Repeated core-owned values are copied
|
||||
// for each application.
|
||||
func (values FlagValues[I]) ApplyTo(target *I, selected ...Flag[I]) error {
|
||||
if target == nil {
|
||||
return fmt.Errorf("%w: destination is nil", ErrFlagWiring)
|
||||
}
|
||||
preparedValues := make([]preparedValue[I], 0, len(selected))
|
||||
for _, flag := range selected {
|
||||
binding := flag.binding
|
||||
if binding.identity == nil {
|
||||
@@ -83,7 +92,22 @@ func (values FlagValues[I]) ApplyTo(target *I, selected ...Flag[I]) error {
|
||||
if binding.meta.Required && !prepared.supplied {
|
||||
return fmt.Errorf("flag --%s: %w", binding.meta.Name, ErrFlagInput)
|
||||
}
|
||||
prepared.apply(target)
|
||||
preparedValues = append(preparedValues, prepared)
|
||||
}
|
||||
var ordered []preparedOccurrence[I]
|
||||
for _, prepared := range preparedValues {
|
||||
if prepared.apply != nil {
|
||||
prepared.apply(target)
|
||||
}
|
||||
for _, occurrence := range prepared.ordered {
|
||||
if occurrence.apply != nil {
|
||||
ordered = append(ordered, occurrence)
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.SliceStable(ordered, func(i, j int) bool { return *ordered[i].ordinal < *ordered[j].ordinal })
|
||||
for _, occurrence := range ordered {
|
||||
occurrence.apply(target)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user