[Fixes #51] Destructuring is supported for query results too

This commit is contained in:
Julien Eluard 2018-09-20 11:06:16 +02:00
parent 95e44c9eee
commit 9f49159edf
No known key found for this signature in database
GPG Key ID: 6FD7DB5437FCBEF6
5 changed files with 67 additions and 30 deletions

View File

@ -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)))]

View File

@ -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]

View File

@ -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)

View File

@ -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)

View File

@ -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]))))