1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
;; Parenscript shortcut
(defmacro script (&rest body)
"Macro expanding to (:script (:raw (ps body))). Great for embedding JS inside page."
`(list :script
(list :raw
(ps ,@body))))
;; Templating macros
(defmacro mu (&rest body)
"Macro writing Mustache syntax, namely the '{{ mustache }}'"
`(list :raw (concatenate 'string "{{ " ,@body " }}")))
(defun keyword-to-chain (string-or-keyword)
(if (keywordp string-or-keyword)
(concatenate 'string "."
(-> string-or-keyword
symbol-name
string-downcase))
string-or-keyword))
(defun muc (&rest chain-of-props)
"Shortcut chaining props in a mustache"
(mu (reduce (lambda (a b)
(concatenate 'string
(keyword-to-chain a)
(keyword-to-chain b)))
chain-of-props)))
(defmacro mublock (name attrs &rest body)
"Macro writing a block where a '{{ end }}' is followed."
`(list
(mu ,name " " ,attrs)
,@(mapcar (lambda (x) `',x) body)
(mu "end")))
(defmacro muwhen (condition &rest body)
`(mublock "if" ,condition ,@body))
(defmacro muif (condition do do-else)
`(muwhen ,condition
,@do
(:RAW `(mu "else"))
,@do-else))
(defun quote-if-string (str)
(if (stringp str)
(concatenate 'string "\"" str "\"")
(write-to-string str)))
;; TODO support function calls as values
(defmacro mudefvar (var val)
`(mu "$"
(string-downcase (symbol-name ',var))
" := "
(quote-if-string ,val)))
|