mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-12 17:27:50 +08:00
6c6797b4c1
Some of the uses are replaced by plain English phrases like "such as", and the remaining have the trailing commas removed.
57 lines
1.6 KiB
Go
57 lines
1.6 KiB
Go
package eval
|
|
|
|
import (
|
|
"reflect"
|
|
|
|
"src.elv.sh/pkg/eval/vals"
|
|
"src.elv.sh/pkg/parse"
|
|
)
|
|
|
|
// UnknownOption is thrown by a native function when called with an unknown option.
|
|
type UnknownOption struct {
|
|
OptName string
|
|
}
|
|
|
|
// Error implements the error interface.
|
|
func (e UnknownOption) Error() string {
|
|
return "unknown option: " + parse.Quote(e.OptName)
|
|
}
|
|
|
|
// RawOptions is the type of an argument a Go-native function can take to
|
|
// declare that it wants to parse options itself. See the doc of NewGoFn for
|
|
// details.
|
|
type RawOptions map[string]any
|
|
|
|
// Takes a raw option map and a pointer to a struct, and populate the struct
|
|
// with options. A field named FieldName corresponds to the option named
|
|
// field-name. Options that don't have corresponding fields in the struct causes
|
|
// an error.
|
|
//
|
|
// Similar to vals.ScanMapToGo, but requires rawOpts to contain a subset of keys
|
|
// supported by the struct.
|
|
func scanOptions(rawOpts RawOptions, ptr any) error {
|
|
_, keyIdx := vals.StructFieldsInfo(reflect.TypeOf(ptr).Elem())
|
|
structValue := reflect.ValueOf(ptr).Elem()
|
|
for k, v := range rawOpts {
|
|
fieldIdx, ok := keyIdx[k]
|
|
if !ok {
|
|
return UnknownOption{k}
|
|
}
|
|
|
|
// An option with no value (e.g. `&a-opt`) has `$true` as its default value. However, if
|
|
// the option struct member is a string we want an empty string as the default value.
|
|
switch b := v.(type) {
|
|
case bool:
|
|
if b && structValue.Field(fieldIdx).Type().Name() == "string" {
|
|
v = ""
|
|
}
|
|
}
|
|
|
|
err := vals.ScanToGo(v, structValue.Field(fieldIdx).Addr().Interface())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|