github.com/markusbkk/elvish@v0.0.0-20231204143114-91dc52438621/pkg/eval/options.go (about) 1 package eval 2 3 import ( 4 "reflect" 5 6 "github.com/markusbkk/elvish/pkg/eval/vals" 7 "github.com/markusbkk/elvish/pkg/parse" 8 ) 9 10 // UnknownOption is thrown by a native function when called with an unknown option. 11 type UnknownOption struct { 12 OptName string 13 } 14 15 // Error implements the error interface. 16 func (e UnknownOption) Error() string { 17 return "unknown option: " + parse.Quote(e.OptName) 18 } 19 20 // RawOptions is the type of an argument a Go-native function can take to 21 // declare that it wants to parse options itself. See the doc of NewGoFn for 22 // details. 23 type RawOptions map[string]interface{} 24 25 // Takes a raw option map and a pointer to a struct, and populate the struct 26 // with options. A field named FieldName corresponds to the option named 27 // field-name. Options that don't have corresponding fields in the struct causes 28 // an error. 29 // 30 // Similar to vals.ScanMapToGo, but requires rawOpts to contain a subset of keys 31 // supported by the struct. 32 func scanOptions(rawOpts RawOptions, ptr interface{}) error { 33 _, keyIdx := vals.StructFieldsInfo(reflect.TypeOf(ptr).Elem()) 34 structValue := reflect.ValueOf(ptr).Elem() 35 for k, v := range rawOpts { 36 fieldIdx, ok := keyIdx[k] 37 if !ok { 38 return UnknownOption{k} 39 } 40 err := vals.ScanToGo(v, structValue.Field(fieldIdx).Addr().Interface()) 41 if err != nil { 42 return err 43 } 44 } 45 return nil 46 }