elvish/eval/variable.go
2016-09-11 03:18:04 +02:00

136 lines
2.4 KiB
Go

package eval
import (
"errors"
"os"
"strings"
)
var (
ErrRoCannotBeSet = errors.New("read-only; cannot be set")
)
// Variable represents an elvish variable.
type Variable interface {
Set(v Value)
Get() Value
}
type ptrVariable struct {
valuePtr *Value
validator func(Value) error
}
func NewPtrVariable(v Value) Variable {
return NewPtrVariableWithValidator(v, nil)
}
func NewPtrVariableWithValidator(v Value, vld func(Value) error) Variable {
return ptrVariable{&v, vld}
}
func (iv ptrVariable) Set(val Value) {
if iv.validator != nil {
if err := iv.validator(val); err != nil {
throw(errors.New("invalid value: " + err.Error()))
}
}
*iv.valuePtr = val
}
func (iv ptrVariable) Get() Value {
return *iv.valuePtr
}
type roVariable struct {
value Value
}
func NewRoVariable(v Value) Variable {
return roVariable{v}
}
func (rv roVariable) Set(val Value) {
throw(ErrRoCannotBeSet)
}
func (rv roVariable) Get() Value {
return rv.value
}
type cbVariable struct {
set func(Value)
get func() Value
}
// MakeVariableFromCallback makes a variable from a set callback and a get
// callback.
func MakeVariableFromCallback(set func(Value), get func() Value) Variable {
return &cbVariable{set, get}
}
func (cv *cbVariable) Set(val Value) {
cv.set(val)
}
func (cv *cbVariable) Get() Value {
return cv.get()
}
type roCbVariable func() Value
// MakeRoVariableFromCallback makes a read-only variable from a get callback.
func MakeRoVariableFromCallback(get func() Value) Variable {
return roCbVariable(get)
}
func (cv roCbVariable) Set(Value) {
throw(ErrRoCannotBeSet)
}
func (cv roCbVariable) Get() Value {
return cv()
}
// elemVariable is an element of a IndexSetter.
type elemVariable struct {
container IndexSetter
index Value
}
func (ev elemVariable) Set(val Value) {
ev.container.IndexSet(ev.index, val)
}
func (ev elemVariable) Get() Value {
return ev.container.IndexOne(ev.index)
}
type envVariable struct {
name string
}
func newEnvVariable(name string) envVariable {
return envVariable{name}
}
func (ev envVariable) Set(val Value) {
os.Setenv(ev.name, ToString(val))
}
func (ev envVariable) Get() Value {
return String(os.Getenv(ev.name))
}
type pathEnvVariable struct {
envVariable
ppaths *[]string
}
func (pev pathEnvVariable) Set(val Value) {
s := ToString(val)
os.Setenv(pev.name, s)
paths := strings.Split(s, ":")
*pev.ppaths = paths
}