2018-02-15 17:16:41 +08:00
|
|
|
package eval
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"reflect"
|
|
|
|
|
2018-09-27 08:48:44 +08:00
|
|
|
"github.com/elves/elvish/eval/vals"
|
2018-02-15 17:16:41 +08:00
|
|
|
"github.com/elves/elvish/parse"
|
|
|
|
"github.com/elves/elvish/util"
|
|
|
|
)
|
|
|
|
|
2018-09-28 00:35:35 +08:00
|
|
|
var ErrNoOptAccepted = errors.New("function does not accept any options")
|
|
|
|
|
2018-02-15 21:25:17 +08:00
|
|
|
type RawOptions map[string]interface{}
|
|
|
|
|
2018-09-28 00:35:35 +08:00
|
|
|
// Scan takes a pointer to a struct and scan options into it. A field named
|
|
|
|
// FieldName corresponds to the option named field-name, unless the field has a
|
|
|
|
// explicit "name" tag. Fields typed ParsedOptions are ignored.
|
2018-02-15 21:25:17 +08:00
|
|
|
func (rawOpts RawOptions) Scan(ptr interface{}) {
|
|
|
|
ptrValue := reflect.ValueOf(ptr)
|
2018-02-15 17:16:41 +08:00
|
|
|
if ptrValue.Kind() != reflect.Ptr || ptrValue.Elem().Kind() != reflect.Struct {
|
2018-02-15 21:25:17 +08:00
|
|
|
throwf("internal bug: need struct ptr to scan options, got %T", ptr)
|
2018-02-15 17:16:41 +08:00
|
|
|
}
|
|
|
|
struc := ptrValue.Elem()
|
|
|
|
|
|
|
|
// fieldIdxForOpt maps option name to the index of field in struc.
|
|
|
|
fieldIdxForOpt := make(map[string]int)
|
|
|
|
for i := 0; i < struc.Type().NumField(); i++ {
|
|
|
|
// ignore unexported fields
|
|
|
|
if !struc.Field(i).CanSet() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
f := struc.Type().Field(i)
|
|
|
|
optName := f.Tag.Get("name")
|
|
|
|
if optName == "" {
|
|
|
|
optName = util.CamelToDashed(f.Name)
|
|
|
|
}
|
|
|
|
fieldIdxForOpt[optName] = i
|
|
|
|
}
|
|
|
|
|
2018-02-15 21:25:17 +08:00
|
|
|
for k, v := range rawOpts {
|
2018-02-15 17:16:41 +08:00
|
|
|
fieldIdx, ok := fieldIdxForOpt[k]
|
|
|
|
if !ok {
|
|
|
|
throwf("unknown option %s", parse.Quote(k))
|
|
|
|
}
|
2018-09-27 08:48:44 +08:00
|
|
|
err := vals.ScanToGo(v, struc.Field(fieldIdx).Addr().Interface())
|
|
|
|
if err != nil {
|
|
|
|
throw(err)
|
|
|
|
}
|
2018-02-15 17:16:41 +08:00
|
|
|
}
|
|
|
|
}
|