Support shared variable.

This fixes #15. Only string is supported ATM.
This commit is contained in:
Qi Xiao 2016-02-26 04:05:47 +01:00
parent cec194c537
commit 92fb6e5161
4 changed files with 106 additions and 0 deletions

View File

@ -349,6 +349,8 @@ func (ev *Evaler) Global() Namespace {
return map[string]Variable(ev.global)
}
var ErrStoreUnconnected = errors.New("store unconnected")
// ResolveVar resolves a variable. When the variable cannot be found, nil is
// returned.
func (ec *EvalCtx) ResolveVar(ns, name string) Variable {
@ -372,6 +374,11 @@ func (ec *EvalCtx) ResolveVar(ns, name string) Variable {
return NewRoVariable(ExternalCmd{name[len(FnPrefix):]})
}
return envVariable{name}
case "shared":
if ec.store == nil {
throw(ErrStoreUnconnected)
}
return sharedVariable{ec.store, name}
default:
use(ec, ns, nil)
return ec.modules[ns][name]

19
eval/shared.go Normal file
View File

@ -0,0 +1,19 @@
package eval
import "github.com/elves/elvish/store"
type sharedVariable struct {
store *store.Store
name string
}
func (sv sharedVariable) Set(val Value) {
err := sv.store.SetSharedVar(sv.name, ToString(val))
maybeThrow(err)
}
func (sv sharedVariable) Get() Value {
value, err := sv.store.GetSharedVar(sv.name)
maybeThrow(err)
return String(value)
}

35
store/sharedVar.go Normal file
View File

@ -0,0 +1,35 @@
package store
import (
"database/sql"
"errors"
)
var ErrNoVar = errors.New("no such variable")
func init() {
initTable["shared"] = func(db *sql.DB) error {
_, err := db.Exec(`create table if not exists shared_var (name text unique primary key, value text)`)
return err
}
}
func (s *Store) GetSharedVar(n string) (string, error) {
row := s.db.QueryRow(`select value from shared_var where name = ?`, n)
var value string
err := row.Scan(&value)
if err == sql.ErrNoRows {
err = ErrNoVar
}
return value, err
}
func (s *Store) SetSharedVar(n, v string) error {
_, err := s.db.Exec(`insert or replace into shared_var (name, value) values (?, ?)`, n, v)
return err
}
func (s *Store) DelSharedVar(n string) error {
_, err := s.db.Exec(`delete from shared_var where name = ?`, n)
return err
}

45
store/sharedVar_test.go Normal file
View File

@ -0,0 +1,45 @@
package store
import "testing"
func TestSharedVar(t *testing.T) {
varname := "foo"
value1 := "lorem ipsum"
value2 := "o mores, o tempora"
// Getting an nonexistent variable should return ErrNoVar.
_, err := tStore.GetSharedVar(varname)
if err != ErrNoVar {
t.Error("want ErrNoVar, got", err)
}
// Setting a variable for the first time creates it.
err = tStore.SetSharedVar(varname, value1)
if err != nil {
t.Error("want no error, got", err)
}
v, err := tStore.GetSharedVar(varname)
if v != value1 || err != nil {
t.Errorf("want %q and no error, got %q and %v", value1, v, err)
}
// Setting an existing variable updates its value.
err = tStore.SetSharedVar(varname, value2)
if err != nil {
t.Error("want no error, got", err)
}
v, err = tStore.GetSharedVar(varname)
if v != value2 || err != nil {
t.Errorf("want %q and no error, got %q and %v", value2, v, err)
}
// After deleting a variable, access to it cause ErrNoVar.
err = tStore.DelSharedVar(varname)
if err != nil {
t.Error("want no error, got", err)
}
_, err = tStore.GetSharedVar(varname)
if err != ErrNoVar {
t.Error("want ErrNoVar, got", err)
}
}