savepoint

phoen
Daniel Barlow 2022-02-20 12:02:36 +00:00
parent 64cd3a986c
commit 022ce6da03
2 changed files with 86 additions and 0 deletions

51
just/observable-test.fnl Normal file
View File

@ -0,0 +1,51 @@
(local fennel (require :fennel))
(local observable (require :observable))
(macro expect [form]
`(do
(assert ,form ,(view [:failed form]))
(print ,(view [:passed form]))))
(macro expect-error [form]
`(let [(ok?# msg#) (pcall (fn [] ,form))]
(assert (not ok?#) msg#)
(print ,(view [:passed (list :error form)]))))
(local app-state
(observable.new
{
:foo 27
:bar 54
:nest {
:name "beatles"
:artists [:john :paul: :ringo :george ]
}
}))
(expect (= (app-state:get [:foo]) 27))
(expect (= (app-state:get [:nest :name]) "beatles"))
(let [s (observable.new {:foo 43})]
;; s:get on a non-leaf returns the subtree. use table.concat
;; for comparison of values
(expect (= (table.concat (s:get [])) (table.concat {:foo 43}))))
(let [s (observable.new {:foo 43})]
;; update existing entry
(s:update [:foo] 84)
(expect (= (s:get [:foo]) 84))
;; create new entry
(s:update [:baz] 48)
(expect (= (s:get [:baz]) 48))
;; doesn't create new nested keys
(expect-error (s:update [:nonexistent :path] 22)))
(let [s (observable.new {:foo {:bar 43}})]
(var win false)
;; observers live on subtrees, not individual nodes
(s:observe [:foo] #(set win true))
(s:update [:foo :bar] 42)
(expect (and win)))

35
just/observable.fnl Normal file
View File

@ -0,0 +1,35 @@
(local {: view} (require :fennel))
(fn concat [dest src]
(table.move dest 1 (# dest) (# src) src))
(fn update [data self path value]
(let [[first & rest] path]
(if (next rest)
(update (. data first) self rest value)
(do
(if data._subscribers
(each [_ f (pairs data._subscribers)] (f)))
(tset data first value)))))
(fn get [data self path]
(let [[first & rest] path]
(if (not first) data
(next rest) (get (. data first) self rest)
(. data first))))
(fn observe [data self path fun]
(let [el (get data self path)]
(when el
(if el._subscribers
(el._subscribers:insert fun)
(tset el :_subscribers [fun])))))
(fn new [data]
{
:observe (partial observe data)
:update (partial update data)
:get (partial get data)
})
{: new }