Fork me on GitHub
#meander
<
2020-08-05
>
markaddleman19:08:21

I needed a simple template system. I think this fits the bill for both simple and easy:

(m/rewrite {:keys     #{::name ::state}
              :template ["here is some data for" ::name
                         {:name  ::name
                          :state ::state}]
              :values   {::name  "Mark"
                         ::state "California"}}
    {:keys     ?keys
     :values   ?values
     :template (m/$ ?ctx (m/pred (partial contains? ?keys) ?key))}
    (m/cata {:keys     ?keys, :values ?values
             :template (m/app ?ctx (m/app ?values ?key))})

    {:template ?result} ?result)

noprompt16:08:40

Another tool you can use for this (not Meander) is clojure.walk/prewalk-replace:

(let [bindings {::name "Mark"
                ::state "California"}
      template ["here is some data for"
                ::name
                {:name  ::name
                 :state ::state}]]
  (clojure.walk/prewalk-replace bindings template))
;; =>
["here is some data for" "Mark" {:name "Mark", :state "California"}]

noprompt17:08:27

Of course, if you don’t want something as blunt as prewalk-replace you can accomplish the same thing with Meander and your own custom rules for more control:

(let [bindings {::name "Mark"
                ::state "California"}
      template ["here is some data for"
                ::name
                {:name  ::name
                 :state ::state}]]
  (m/rewrite [template bindings]
    [[!xs ...] ?bindings]
    [(m/cata [!xs ?bindings]) ...]

    [{?k ?v & ?rest} ?bindings]
    {(m/cata [?k ?bindings]) (m/cata [?v ?bindings]) & (m/cata [?rest ?bindings])}

    [?x {?x ?v :as ?bindings}]
    (m/cata [?v ?bindings])
    
    ?x
    ?x))
;; =>
["here is some data for" "Mark" {:state "California", :name "Mark"}]