(def template "{{name}}.{{surname}}
{{#data}}
* {{.}}
{{/data}}")
(introspect template) => {:name "" :surname "" :data []}
是否有内省实施?
答案 0 :(得分:4)
如果问题是如何构建内省函数,instaparse是一种方法:
(require '[instaparse.core :as insta])
(def parse
(insta/parser
"<moustache> = (tagged-block / word / sp)*
<tagged-block> = comment | section | var
comment = <tag-open> <'!'> (word | sp)* <tag-close>
section = section-block-open (current-item / var / comment / word / sp)* <section-block-close>
<section-block-open> = <tag-open> <'#'> name <tag-close>
section-block-close = tag-open '/' name tag-close
var = <tag-open> name <tag-close>
current-item = <tag-open> <'.'> <tag-close>
<word> = #'[^\\s{}]+'
<sp> = #'[\\s]+'
name = #'[^\\s{}]+'
tag-open = '{{'
tag-close = '}}'"))
(def template "{{name}}.{{surname}}
{{#data}}
* {{.}}
{{/data}}")
(parse template) ;=> ([:var [:name "name"]] "." [:var [:name "surname"]] "\n " [:var [:name "#data"]] "\n " "*" " " [:var [:name "."]] "\n " [:var [:name "/data"]])
(defn introspect [parsed]
(->> (tree-seq sequential? seq parsed)
(filter sequential?)
(filter #(#{:var :section} (first %)))
(map (juxt first (comp keyword last second)))
(map #(case (first %)
:var [(second %) ""]
:section [(second %) []]))
(into {})))
(assert (= {:name "" :surname "" :data []}
(introspect (parse template))))
我包括对评论的支持,其他胡子构造应该很容易添加:
(parse "Hello {{people}}!! {{! people could be the world!!}}")
;=> ("Hello" " " [:var [:name "people"]] "!!" " " [:comment " " "people" " " "could" " " "be" " " "the" " " "world!!"])
它并不涵盖整个胡须语法,但我认为这是一个好的开始。