diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2019-11-03 13:05:11 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2019-11-03 16:01:13 +0000 |
| commit | e2dbd96aa0cd362fbd9410a49aa415459a1c1b98 (patch) | |
| tree | 241feebc82230681504fa41eaaa1d7692c44db8c | |
| parent | make things work (diff) | |
| download | watch-cad-e2dbd96aa0cd362fbd9410a49aa415459a1c1b98.tar.gz watch-cad-e2dbd96aa0cd362fbd9410a49aa415459a1c1b98.zip | |
new state attempt
| -rw-r--r-- | spec/state_spec.moon | 113 | ||||
| -rw-r--r-- | state.moon | 81 |
2 files changed, 142 insertions, 52 deletions
diff --git a/spec/state_spec.moon b/spec/state_spec.moon index b2085c5..5826067 100644 --- a/spec/state_spec.moon +++ b/spec/state_spec.moon @@ -18,45 +18,100 @@ describe "Once", -> assert.is_falsy Once.is_once { a: 3 } describe "State", -> - local S + local state before_each -> state = State! - S = state.state - it "can be indexed infinitely", -> - assert.is_table S.a.b.c.d + it "stores values", -> + assert.is_nil state.values['my key'] + state.values['my key'] = 'my val' + assert.is_equal 'my val', state.values['my key'] - describe ":init", -> - it "stores default until changed", -> - S\init 'test', 2 - assert.is.equal 2, S.test + state.values['more'] = 4 + assert.is_equal 4, state.values['more'] + assert.is_equal 'my val', state.values['my key'] - S.test = 4 - assert.is.equal 4, S.test + it "can be reset", -> + state.values['my key'] = 'my val' + state.values['more'] = 4 - S\init 'test', 2 - assert.is.equal 4, S.test + state\reset! + assert.is_nil state.values['my key'] + assert.is_nil state.values['more'] - describe ":store", -> - it "stores defaults until changed", -> - S\store 'test', nil, 3 - assert.is.equal 3, S.test + describe "cursors", -> + it "can be nested with :get_nested()", -> + assert.is_table state.root\get_nested 'a' + assert.is_table state.root\get_nested('a')\get_nested 'b' - S\store 'test', nil, 4 - assert.is.equal 3, S.test + it "delegate __index to :get_nested", -> + assert.is_table state.root + assert.is_table state.root.a + assert.is_table state.root.a.b.c.d - it "follows live inputs", -> - S\store 'test', 3, 'nope' - assert.is.equal 3, S.test + it "stringify to a key", -> + assert.is_equal '', tostring state.root + assert.is_equal 'a.b.c.d', tostring state.root.a.b.c.d - S\store 'test', 4, 'nope' - assert.is.equal 4, S.test + it ":set() sets the value", -> + cursor = state.root.test + cursor\set 'the val' + assert.is_equal 'the val', state.values[cursor] - it "lets Once() inputs override defaults", -> - S\store 'test', (Once 3), 'nope' - assert.is.equal 3, S.test + it ":set() returns the new value", -> + assert.is_equal 'val', state.root.test\set 'val' - S\store 'test', 'changed' + it ":get() gets the value", -> + cursor = state.root.test + cursor\set 'the val' + assert.is_equal 'the val', cursor\get! + + it ":init() sets the value unless already set", -> + cursor = state.root.test + cursor\init 'initial value' + assert.is_equal 'initial value', cursor! + + cursor\init 'other value' + assert.is_equal 'initial value', cursor! + + it ":init() returns the current value", -> + cursor = state.root.test + assert.is_equal 'initial value', cursor\init 'initial value' + assert.is_equal 'initial value', cursor\init 'other value' + + it "can be called to get the value", -> + cursor = state.root.test + assert.is_nil cursor! + cursor\set 'the val' + assert.is_equal 'the val', cursor! + + it "delegate __eq to string key", -> + assert.is_true state.root.a == state.root.a + assert.is_true state.root.a.b == state.root.a.b + assert.is_false state.root.a == state.root.b + assert.is_false state.root.a.b == state.root.a.c + assert.is_false state.root.a.b == state.root.c.b + + describe ":drive()", -> + it "follows live inputs", -> + cursor = state.root.test + cursor\drive 3 + assert.is_equal 3, cursor! + + cursor\drive 'test' + assert.is_equal 'test', cursor! + + it "initializes with Once() inputs", -> + cursor = state.root.test + cursor\drive Once 'initial' + assert.is_equal 'initial', cursor! + + cursor\drive Once 'other' + assert.is_equal 'initial', cursor! + + it "returns the current value", -> + cursor = state.root.test + assert.is_equal 'initial', cursor\drive Once 'initial' + assert.is_equal 'initial', cursor\drive Once 'other' + assert.is_equal 'live in', cursor\drive 'live in' - S\store 'test', (Once 4), 'nope' - assert.is.equal 'changed', S.test @@ -22,6 +22,53 @@ is_live = (val) -> (not is_once val) and val are_once = all is_once are_live = all is_live +class Cursor + @__base.__index = do + old_index = @__base.__index + (k) => + if v = old_index[k] + return v + + if 'string' == type k + return @get_nested k + + new: (@state, @path='') => + + set: (value) => + @state.values[@path] = value + value + + get: (value) => + @state.values[@path] + + init: (value) => + old = @get! + if old != nil + old + else + @set value + + drive: (live_or_once) => + if val = is_once live_or_once + @init val + else + @set live_or_once + + get_nested: (name) => + if #@path > 0 + name = "#{@path}.#{name}" + + Cursor @state, name + + __call: => @get! + __tostring: => @path + __eq: (other) => @path == other.path + + @is_cursor: (val) -> + return unless val + return unless 'table' == type val + val.__class == @@ + class State @mt: { __index: (t, k) -> @@ -38,33 +85,21 @@ class State default = val rawset @, key, (rawget @, key) or default - -- store and return a piece of state under 'key'. - -- the current and stored value is the first of the following: - -- * 'fixed', if it is a 'live' value - -- * current state, if set - -- * 'fixed', if it is a 'once' value - -- * 'default' - store: (key, fixed, default) => - state = rawget @, key - once = Once.is_once fixed - - next_state = if is_live fixed - fixed - elseif state - state - elseif once - fixed.value - else - default - - with next_state - rawset @, key, next_state - new: => @reset! reset: => - @state = setmetatable {}, @@mt + @values = setmetatable {}, { + __index: (k) => + if Cursor.is_cursor k + k = tostring k + rawget @, k + __newindex: (k, v) => + if Cursor.is_cursor k + k = tostring k + rawset @, k, v + } + @root = Cursor @ { :is_once, :are_once |
