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"}
}
ev := &Evaler{nil, map[string]Namespace{}, searchPaths, st}
// Construct initial global namespace
pid := String(strconv.Itoa(syscall.Getpid()))
paths := NewList()
paths.appendStrings(searchPaths)
global := Namespace{
"pid": NewPtrVariable(pid),
"ok": NewPtrVariable(OK),
"true": NewPtrVariable(Bool(true)),
"false": NewPtrVariable(Bool(false)),
"paths": NewPtrVariable(paths),
ev.global = Namespace{
"pid": NewRoVariable(pid),
"ok": NewRoVariable(OK),
"true": NewRoVariable(Bool(true)),
"false": NewRoVariable(Bool(false)),
"paths": NewRoVariable(PathList{&ev.searchPaths}),
}
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) {
@ -263,7 +265,11 @@ func (ev *Evaler) Global() map[string]Variable {
// returned.
func (ec *EvalCtx) ResolveVar(ns, name string) Variable {
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 {
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 {
buf := new(bytes.Buffer)
buf.WriteRune('[')
for i, v := range *l.inner {
if i > 0 {
buf.WriteByte(' ')
}
buf.WriteString(v.Repr())
var b ListReprBuilder
for _, v := range *l.inner {
b.WriteElem(v.Repr())
}
buf.WriteRune(']')
return buf.String()
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(' ')
}
b.buf.WriteString(v)
}
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.

View File

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