-
Notifications
You must be signed in to change notification settings - Fork 48
/
macros.cljc
29 lines (25 loc) · 1.42 KB
/
macros.cljc
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
(ns ^:no-doc camel-snake-kebab.internals.macros
#?(:cljs (:refer-clojure :exclude [resolve]))
(:require [camel-snake-kebab.internals.alter-name :refer [alter-name]]
[camel-snake-kebab.internals.misc :refer [convert-case]]))
#?(:cljs
(defn resolve [sym]
;; On self-hosted ClojureScript, macros are evaluated under the `:cljs` conditional branch
;; In that case, we need to use `eval` in order to resolve variables instead of `resolve`
(eval `(~'var ~sym))))
(defn type-preserving-function [case-label first-fn rest-fn sep]
`(defn ~(symbol (str "->" case-label)) [s# & rest#]
(let [convert-case# #(apply convert-case ~first-fn ~rest-fn ~sep % rest#)]
(alter-name s# convert-case#))))
(defn type-converting-functions [case-label first-fn rest-fn sep]
(letfn [(make-name [type-label]
(->> (str case-label " " type-label)
(convert-case (resolve first-fn) (resolve rest-fn) sep)
(str "->")
(symbol)))]
(for [[type-label type-converter] {"string" `identity "symbol" `symbol "keyword" `keyword}]
`(defn ~(make-name type-label) [s# & rest#]
(~type-converter (apply convert-case ~first-fn ~rest-fn ~sep (name s#) rest#))))))
(defmacro defconversion [case-label first-fn rest-fn sep]
`(do ~(type-preserving-function case-label first-fn rest-fn sep)
~@(type-converting-functions case-label first-fn rest-fn sep)))