Syncing from $env:PATH to $paths and ev.searchPaths.

This addresses #139.
This commit is contained in:
Qi Xiao 2016-02-18 19:30:08 +01:00
parent ce4d6ff7f2
commit cc412f8684
4 changed files with 94 additions and 18 deletions

View File

@ -54,22 +54,24 @@ func NewEvaler(st *store.Store) *Evaler {
searchPaths = []string{"/bin"} searchPaths = []string{"/bin"}
} }
ev := &Evaler{nil, map[string]Namespace{}, searchPaths, st}
// Construct initial global namespace // Construct initial global namespace
pid := String(strconv.Itoa(syscall.Getpid())) pid := String(strconv.Itoa(syscall.Getpid()))
paths := NewList() paths := NewList()
paths.appendStrings(searchPaths) paths.appendStrings(searchPaths)
global := Namespace{ ev.global = Namespace{
"pid": NewPtrVariable(pid), "pid": NewRoVariable(pid),
"ok": NewPtrVariable(OK), "ok": NewRoVariable(OK),
"true": NewPtrVariable(Bool(true)), "true": NewRoVariable(Bool(true)),
"false": NewPtrVariable(Bool(false)), "false": NewRoVariable(Bool(false)),
"paths": NewPtrVariable(paths), "paths": NewRoVariable(PathList{&ev.searchPaths}),
} }
for _, b := range builtinFns { for _, b := range builtinFns {
global[FnPrefix+b.Name] = NewPtrVariable(b) ev.global[FnPrefix+b.Name] = NewRoVariable(b)
} }
return &Evaler{global, map[string]Namespace{}, searchPaths, st} return ev
} }
func (e *Evaler) AddModule(name string, ns Namespace) { func (e *Evaler) AddModule(name string, ns Namespace) {
@ -263,7 +265,11 @@ func (ev *Evaler) Global() map[string]Variable {
// returned. // returned.
func (ec *EvalCtx) ResolveVar(ns, name string) Variable { func (ec *EvalCtx) ResolveVar(ns, name string) Variable {
if ns == "env" { if ns == "env" {
return newEnvVariable(name) ev := envVariable{name}
if name == "PATH" {
return pathEnvVariable{ev, &ec.searchPaths}
}
return ev
} }
if mod, ok := ec.modules[ns]; ok { if mod, ok := ec.modules[ns]; ok {
return mod[name] return mod[name]

41
eval/pathList.go Normal file
View File

@ -0,0 +1,41 @@
package eval
import (
"errors"
"github.com/elves/elvish/parse"
)
// PathList wraps a list of search paths into a readonly list-like Value.
type PathList struct {
inner *[]string
}
func (l PathList) Kind() string {
return "list"
}
func (l PathList) Repr() string {
var b ListReprBuilder
for _, v := range *l.inner {
b.WriteElem(parse.Quote(v))
}
return b.String()
}
func (l PathList) IndexOne(idx Value) Value {
// XXX copied from index.go
i := intIndex(idx)
if i < 0 {
i += len(*l.inner)
}
if i < 0 || i >= len(*l.inner) {
throw(ErrIndexOutOfRange)
}
return String((*l.inner)[i])
}
func (l PathList) IndexSet(idx, v Value) {
throw(errors.New("assignment to $paths not implemented; assign to $env:PATH instead"))
}

View File

@ -190,16 +190,32 @@ func (l List) appendStrings(ss []string) {
} }
func (l List) Repr() string { func (l List) Repr() string {
buf := new(bytes.Buffer) var b ListReprBuilder
buf.WriteRune('[') for _, v := range *l.inner {
for i, v := range *l.inner { b.WriteElem(v.Repr())
if i > 0 {
buf.WriteByte(' ')
} }
buf.WriteString(v.Repr()) return b.String()
}
type ListReprBuilder struct {
buf bytes.Buffer
}
func (b *ListReprBuilder) WriteElem(v string) {
if b.buf.Len() == 0 {
b.buf.WriteByte('[')
} else {
b.buf.WriteByte(' ')
} }
buf.WriteRune(']') b.buf.WriteString(v)
return buf.String() }
func (b *ListReprBuilder) String() string {
if b.buf.Len() == 0 {
return "["
}
b.buf.WriteByte(']')
return b.buf.String()
} }
// Map is a map from string to Value. // Map is a map from string to Value.

View File

@ -3,6 +3,7 @@ package eval
import ( import (
"errors" "errors"
"os" "os"
"strings"
) )
var ( var (
@ -76,3 +77,15 @@ func (ev envVariable) Set(val Value) {
func (ev envVariable) Get() Value { func (ev envVariable) Get() Value {
return String(os.Getenv(ev.name)) 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
}