From 9f49159edf7b5097160754486295d0b8376a0aa5 Mon Sep 17 00:00:00 2001 From: Julien Eluard Date: Thu, 20 Sep 2018 11:06:16 +0200 Subject: [PATCH] [Fixes #51] Destructuring is supported for query results too --- examples/src/pluto/examples.cljs | 15 ++++-- .../assets/extensions/demo/extension.edn | 2 +- src/pluto/reader/blocks.cljc | 48 +++++++++++++------ src/pluto/reader/hooks.cljc | 3 +- test/pluto/reader/block_test.cljc | 29 ++++++----- 5 files changed, 67 insertions(+), 30 deletions(-) diff --git a/examples/src/pluto/examples.cljs b/examples/src/pluto/examples.cljs index 2a02bc6..369972d 100644 --- a/examples/src/pluto/examples.cljs +++ b/examples/src/pluto/examples.cljs @@ -2,6 +2,7 @@ (:require [clojure.string :as string] [pluto.components.html :as html] [pluto.reader :as reader] + [pluto.host :as host] [pluto.storage :as storage] [pluto.storage.http :as http] [pluto.storage.gist :as gist] @@ -23,7 +24,7 @@ (re-frame/reg-event-db :random (fn [db [_ b]] - (assoc db :random b))) + (assoc db :random {:cond? b}))) (re-frame/reg-sub :random-boolean @@ -53,16 +54,24 @@ (storage-for type) {:value id} cb))) +(def hook + (reify host/AppHook + (id [_] :main) + (properties [_] {:view :view}) + (hook-in [_ id {:keys [description scope parameters preview short-preview]} cofx]) + (unhook [_ id {:keys [scope]} {:keys [db] :as cofx}]))) + (defn parse [m] (reader/parse {:capacities {:components html/components - :hooks {'hooks/main {:properties {:view :view}}}}} + :queries #{:random-boolean} + :hooks {:main hook}}} m)) (defn render-extension [m el el-errors] (let [{:keys [data errors]} (parse m)] (when errors (render (errors-list errors) el-errors)) - (render (get-in data ['hooks/main.demo :view]) el))) + (render (get-in data [:hooks :main :demo :parsed :view]) el))) (defn read-extension [o el el-errors] (let [{:keys [data errors]} (reader/read (:content (first o)))] diff --git a/figwheel/resources/public/assets/extensions/demo/extension.edn b/figwheel/resources/public/assets/extensions/demo/extension.edn index aafee59..89d13ea 100644 --- a/figwheel/resources/public/assets/extensions/demo/extension.edn +++ b/figwheel/resources/public/assets/extensions/demo/extension.edn @@ -10,7 +10,7 @@ (let [{name :name} @properties] [view {} [text {} "Hello"] - (let [cond? @queries/random-boolean] + (let [{cond? :cond?} (query [:random-boolean]) #_@queries/random-boolean] (if cond? [text {:style {:color "green"}} name] diff --git a/src/pluto/reader/blocks.cljc b/src/pluto/reader/blocks.cljc index 88e7fb5..4b5b79a 100644 --- a/src/pluto/reader/blocks.cljc +++ b/src/pluto/reader/blocks.cljc @@ -11,21 +11,36 @@ (fn [_ [type]] type)) (defn resolve-query [[_ [sub-keyword sub-args :as sub]]] - @(re-frame/subscribe sub)) + (when-let [o (re-frame/subscribe sub)] + @o)) (defn- query? [binding-value] (and (list? binding-value) (= 'query (first binding-value)))) -(defn resolve-binding [binding-value] +(defn resolve-binding-value [v] (cond - (query? binding-value) (resolve-query binding-value) - :else binding-value)) + (query? v) (resolve-query v) + (not (list? v)) v)) + +(declare destructure) + +(defn resolve-binding-key [k v] + (cond + (symbol? k) k + :else (:data (destructure k v)))) + +(defn assoc-binding [m k v] + (let [resolved-value (resolve-binding-value v)] + (let [o (resolve-binding-key k resolved-value)] + (cond + (symbol? o) + (assoc m o resolved-value) + :else + (merge m o))))) (defn resolve-bindings [env] - (reduce-kv #(assoc %1 %2 (resolve-binding %3)) - {} - env)) + (reduce-kv assoc-binding {} env)) (defn let-block [{:keys [env]} child] (cond @@ -48,19 +63,22 @@ (map? value) (errors/merge-results m (destructure-assoc value (nth s idx))) (sequential? value) (errors/merge-results m (destructure-seq value (nth s idx))))) -(defn bindings-size [bindings] +(defn seq-bindings-size [bindings] (let [size (count bindings)] (if (some #{:as} bindings) (- size 2) size))) +(defn valid-bindings-form? [o] + (or (symbol? o) (vector? o) (map? o) (= :as o))) + (defn destructure-seq [bindings s] (cond (or (not (sequential? bindings)) - (not (every? #(or (symbol? %) (vector? %) (map? %) (= :as %)) bindings)) - (> (bindings-size bindings) (count s))) - {:errors [(errors/error ::errors/invalid-destructuring-format bindings)]} + (not (every? valid-bindings-form? bindings)) + (> (seq-bindings-size bindings) (count s))) + {:errors [(errors/error ::errors/invalid-destructuring-format {:type :sequential :data bindings})]} :else (reduce-kv #(merge-seq-bindings bindings s %1 %2 %3) {} (indexed-bindings bindings)))) @@ -77,8 +95,8 @@ (cond (or (not (map? bindings)) - (not (every? #(or (symbol? %) (vector? %) (map? %) (= :as %)) (keys bindings)))) - {:errors [(errors/error ::errors/invalid-destructuring-format bindings)]} + (not (every? valid-bindings-form? (keys bindings)))) + {:errors [(errors/error ::errors/invalid-destructuring-format {:type :assoc :data bindings})]} :else (reduce-kv #(merge-assoc-bindings s %1 %2 %3) {} bindings))) @@ -93,7 +111,9 @@ (defn merge-bindings [m k v] (cond (properties? v) (assoc-in m [:data 'properties] k) - (symbol? k) (assoc-in m [:data k] v) + (or (symbol? k) + (query? v)) + (assoc-in m [:data k] v) :else (if-let [o (destructure k v)] (errors/merge-results m o) diff --git a/src/pluto/reader/hooks.cljc b/src/pluto/reader/hooks.cljc index 186046a..a719a05 100644 --- a/src/pluto/reader/hooks.cljc +++ b/src/pluto/reader/hooks.cljc @@ -122,7 +122,7 @@ (errors/merge-errors (if data (assoc-in %1 [:data (:name (normalize-property %2))] data) %1) errors)) {} props)) -(defn parse-hook [hook v opts m] +(defn parse-hook [hook v opts m] (parse-properties (map->properties (host/properties hook)) v opts m)) (defn parse [opts m] @@ -131,6 +131,7 @@ hook-root (root-id hook-key) hook (get-in opts [:capacities :hooks hook-root]) {:keys [data errors]} (parse-hook hook data opts m)] + (errors/merge-errors (-> acc (assoc-in [:data :hooks hook-root hook-id :parsed] data) diff --git a/test/pluto/reader/block_test.cljc b/test/pluto/reader/block_test.cljc index 51c02f7..a45edc4 100644 --- a/test/pluto/reader/block_test.cljc +++ b/test/pluto/reader/block_test.cljc @@ -1,6 +1,6 @@ (ns pluto.reader.block-test (:refer-clojure :exclude [destructure]) - (:require [clojure.test :refer [is deftest]] + (:require [clojure.test :refer [is deftest testing]] [pluto.reader.errors :as errors] [pluto.reader.blocks :as blocks])) @@ -52,13 +52,20 @@ (is (= {:data '{a 1}} (blocks/bindings->env '[[a] [1]])))) (deftest let-block - (is (= {:data [blocks/let-block {:env {'s "Hello"}} 's]} - (blocks/parse {} '(let [s "Hello"] s)))) - (is (= {:data [blocks/let-block {:env {'s "Hello"}} ['test {} 's]]} - (blocks/parse {} (list 'let ['s "Hello"] ['test {} 's])))) - (is (= {:data [blocks/let-block {:env nil} - ['test {} 's]] - :errors [{::errors/type ::errors/invalid-destructuring-format ::errors/value ['s "Hello" 1]}]} - (blocks/parse {} (list 'let ['s "Hello" 1] ['test {} 's])))) - (is (= {:data [blocks/let-block {:env {'a 1}} ['test {} 's]]} - (blocks/parse {} (list 'let ['{a :a} {:a 1}] ['test {} 's]))))) + (testing "parse" + (is (= {:data [blocks/let-block {:env {'s "Hello"}} 's]} + (blocks/parse {} '(let [s "Hello"] s)))) + (is (= {:data [blocks/let-block {:env {'{a :a} '(query [:aa])}} 'a]} + (blocks/parse {:capacities {:queries #{:aa}}} '(let [{a :a} (query [:aa])] a)))) + (is (= {:data [blocks/let-block {:env {'s "Hello"}} ['test {} 's]]} + (blocks/parse {} (list 'let ['s "Hello"] ['test {} 's])))) + (is (= {:data [blocks/let-block {:env nil} + ['test {} 's]] + :errors [{::errors/type ::errors/invalid-destructuring-format ::errors/value ['s "Hello" 1]}]} + (blocks/parse {} (list 'let ['s "Hello" 1] ['test {} 's])))) + (is (= {:data [blocks/let-block {:env {'a 1}} ['test {} 'a]]} + (blocks/parse {} (list 'let ['{a :a} {:a 1}] ['test {} 'a])))))) + +(deftest let-block-resolution + (is (= ['test {} 1] (blocks/let-block {:env {'a 1}} ['test {} 'a]))) + (is (= ['test {} 1] (blocks/let-block {:env '{{a :a} (query [:aa])}} '[test {} a])))) \ No newline at end of file