Simplify typed input preparation
This commit is contained in:
63
binding.go
63
binding.go
@@ -239,17 +239,6 @@ func (p preparedInput[I]) build() I {
|
||||
return input
|
||||
}
|
||||
|
||||
// prepareInput parses all supplied bindings into typed closures before it
|
||||
// creates an input value. When enforceRequired is false, missing required flags
|
||||
// and operands are allowed so metadata help can validate supplied syntax.
|
||||
func prepareInput[I any](spec CommandSpec[I], flagValues [][]string, operands []string, enforceRequired bool) (preparedInput[I], error) {
|
||||
return prepareInputWithSpellings(spec, flagValues, nil, operands, enforceRequired)
|
||||
}
|
||||
|
||||
func prepareInputWithSpellings[I any](spec CommandSpec[I], flagValues, flagSpellings [][]string, operands []string, enforceRequired bool) (preparedInput[I], error) {
|
||||
return prepareInputWithOccurrences(spec, flagValues, flagSpellings, nil, operands, enforceRequired)
|
||||
}
|
||||
|
||||
func prepareInputWithOccurrences[I any](spec CommandSpec[I], flagValues, flagSpellings [][]string, occurrences []commandmeta.FlagOccurrence, operands []string, enforceRequired bool) (preparedInput[I], error) {
|
||||
if len(flagValues) != len(spec.Flags) {
|
||||
return preparedInput[I]{}, fmt.Errorf("received %d flag value sets for %d bindings", len(flagValues), len(spec.Flags))
|
||||
@@ -272,18 +261,7 @@ func prepareInputWithOccurrences[I any](spec CommandSpec[I], flagValues, flagSpe
|
||||
binding := flag.binding
|
||||
value, err := binding.prepare(flagValues[i])
|
||||
if err != nil {
|
||||
var occurrenceErr *flagOccurrenceError
|
||||
if errors.As(err, &occurrenceErr) {
|
||||
spelling := "--" + binding.meta.Name
|
||||
if occurrenceErr.index >= 0 && occurrenceErr.index < len(flagSpellings[i]) && flagSpellings[i][occurrenceErr.index] != "" {
|
||||
spelling = flagSpellings[i][occurrenceErr.index]
|
||||
}
|
||||
return preparedInput[I]{}, &flagConversionError{
|
||||
binding: binding.meta.Name, spelling: spelling,
|
||||
occurrence: occurrenceErr.index + 1, cause: occurrenceErr.cause,
|
||||
}
|
||||
}
|
||||
return preparedInput[I]{}, fmt.Errorf("flag --%s: %w", binding.meta.Name, err)
|
||||
return preparedInput[I]{}, attributeFlagConversionError(binding.meta.Name, flagSpellings[i], err)
|
||||
}
|
||||
preparedFlags[i] = value
|
||||
for index, occurrence := range value.ordered {
|
||||
@@ -315,7 +293,7 @@ func prepareInputWithOccurrences[I any](spec CommandSpec[I], flagValues, flagSpe
|
||||
if missingRequired != "" {
|
||||
return preparedInput[I]{}, fmt.Errorf("required flag --%s was not supplied", missingRequired)
|
||||
}
|
||||
argumentValues, err := allocateOperands(operands, spec.Arguments, enforceRequired)
|
||||
arguments, err := prepareOperands(operands, spec.Arguments, enforceRequired)
|
||||
if err != nil {
|
||||
return preparedInput[I]{}, err
|
||||
}
|
||||
@@ -327,17 +305,38 @@ func prepareInputWithOccurrences[I any](spec CommandSpec[I], flagValues, flagSpe
|
||||
preparedValues = append(preparedValues, preparedValue[I]{apply: occurrence.apply})
|
||||
}
|
||||
}
|
||||
for i, argument := range spec.Arguments {
|
||||
binding := argument.binding
|
||||
value, err := binding.prepare(argumentValues[i])
|
||||
if err != nil {
|
||||
return preparedInput[I]{}, fmt.Errorf("argument %q: %w", binding.meta.Name, err)
|
||||
}
|
||||
preparedValues = append(preparedValues, value)
|
||||
}
|
||||
preparedValues = append(preparedValues, arguments...)
|
||||
return preparedInput[I]{newInput: spec.NewInput, values: preparedValues}, nil
|
||||
}
|
||||
|
||||
func attributeFlagConversionError(name string, spellings []string, err error) error {
|
||||
var occurrenceErr *flagOccurrenceError
|
||||
if errors.As(err, &occurrenceErr) {
|
||||
spelling := "--" + name
|
||||
if occurrenceErr.index >= 0 && occurrenceErr.index < len(spellings) && spellings[occurrenceErr.index] != "" {
|
||||
spelling = spellings[occurrenceErr.index]
|
||||
}
|
||||
return &flagConversionError{binding: name, spelling: spelling, occurrence: occurrenceErr.index + 1, cause: occurrenceErr.cause}
|
||||
}
|
||||
return fmt.Errorf("flag --%s: %w", name, err)
|
||||
}
|
||||
|
||||
func prepareOperands[I any](operands []string, definitions []Argument[I], enforceRequired bool) ([]preparedValue[I], error) {
|
||||
values, err := allocateOperands(operands, definitions, enforceRequired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
prepared := make([]preparedValue[I], 0, len(definitions))
|
||||
for i, argument := range definitions {
|
||||
value, err := argument.binding.prepare(values[i])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("argument %q: %w", argument.binding.meta.Name, err)
|
||||
}
|
||||
prepared = append(prepared, value)
|
||||
}
|
||||
return prepared, nil
|
||||
}
|
||||
|
||||
func newBindingIdentity() *bindingIdentity { return &bindingIdentity{marker: 1} }
|
||||
|
||||
func allocateOperands[I any](operands []string, definitions []Argument[I], enforceRequired bool) ([][]string, error) {
|
||||
|
||||
Reference in New Issue
Block a user