-
Notifications
You must be signed in to change notification settings - Fork 7
/
spec.clj
74 lines (66 loc) · 2.09 KB
/
spec.clj
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
(ns org.purefn.kurosawa.spec
(:require [clojure.spec.alpha :as spec]
[org.purefn.kurosawa.transform :as xform])
(:refer-clojure :exclude (def)))
;; Docs are here
(defonce ^:private registry-ref (atom {}))
(defn register
"Do not call this directly, use `def`"
[name doc]
(swap! registry-ref assoc name doc))
(defmacro
^{:doc "Registers a spec with optional given docstring. Also calls out
clojure's spec registry to register the spec, if name is
registerable."
:arglists '([name doc-string? spec])}
def
[name & attr]
(let [doc (when (string? (first attr))
(first attr))
spec (if (string? (first attr))
(second attr)
(first attr))]
`(do (when (and (ident? ~name) (namespace ~name))
(spec/def ~name ~spec))
(when ~doc
(register ~name ~doc)))))
(defn doc
"Returns the docstring for a given spec name."
[name]
(get @registry-ref name))
(defn with-doc
"For given spec name, looks up spec (or uses provided) and, if
docstring is available for that name, returns spec with the
docstring as `:doc` metadata."
([name]
(with-doc name (spec/get-spec name)))
([name spec]
(when spec
(let [spec-doc (doc name)]
(cond-> spec
spec-doc (vary-meta assoc :doc spec-doc))))))
(defn get-spec
"Wraps Clojure spec's lookup function, but the returned spec will have
the docstring as metadata."
[name]
(with-doc name))
(defn registry
"Returns the registry map, keyed by spec name, with documentation metadata
on each spec."
[]
(into {}
(map (fn [[k spec]]
[k (with-doc k spec)]))
(spec/registry)))
(defn namespace-specs
"Returns a collection of all the specs for a given namespace - in
other words, the specs that have keyword names and the keyword is
in the given namespace. Each will have their docstring as
metadata."
[ns]
(let [ns (str ns)]
(into {}
(comp (filter (comp #{ns} namespace key))
(map (fn [[k spec]]
[k (with-doc k spec)])))
(spec/registry))))