host: scoped reader-feature toggle, clojure.template, java.util.Locale alias
Follow-ups for running reitit alongside default-feature libraries in one app: - __reader-features / __reader-features-set! exposed to Clojure so a namespace can load a clj-targeted lib (reitit, under :clj) WITHOUT forcing the whole process to :clj — set features, require, restore. Honeysql/selmer/ring stay on the default set they were validated under. (jolt vector args coerced to a janet array — janet map over a pvec iterates keys otherwise.) - clojure.template added to the stdlib (verbatim, pure Clojure over clojure.walk) — honeysql's :clj branch requires it. - java.util.Locale registered as a qualified alias (+ ROOT) for selmer's :clj Locale/US use.
This commit is contained in:
parent
6ab76efd19
commit
f3a9b9ab1f
4 changed files with 64 additions and 4 deletions
33
src/jolt/clojure/template.clj
Normal file
33
src/jolt/clojure/template.clj
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
;; Verbatim from clojure.template (Stuart Sierra) — pure Clojure over
|
||||
;; clojure.walk, which jolt ships. Added so honeysql's :clj branch (which
|
||||
;; requires clojure.template) loads under JOLT_FEATURES including clj.
|
||||
(ns clojure.template
|
||||
"Macros that expand to repeated copies of a template expression."
|
||||
(:require [clojure.walk :as walk]))
|
||||
|
||||
(defn apply-template
|
||||
"For use in macros. argv is an argument list, as in defn. expr is
|
||||
a quoted expression using the symbols in argv. values is a sequence
|
||||
of values to be used for the arguments.
|
||||
|
||||
apply-template will recursively replace argument symbols in expr
|
||||
with their corresponding values, returning a modified expr.
|
||||
|
||||
Example: (apply-template '[x] '(+ x x) '[2])
|
||||
;=> (+ 2 2)"
|
||||
[argv expr values]
|
||||
(assert (vector? argv))
|
||||
(assert (every? symbol? argv))
|
||||
(walk/postwalk-replace (zipmap argv values) expr))
|
||||
|
||||
(defmacro do-template
|
||||
"Repeatedly copies expr (in a do block) for each group of arguments
|
||||
in values. values are automatically partitioned by the number of
|
||||
arguments in argv, an argument vector as in defn.
|
||||
|
||||
Example: (macroexpand '(do-template [x y] (+ y x) 2 4 3 5))
|
||||
;=> (do (+ 4 2) (+ 5 3))"
|
||||
[argv expr & values]
|
||||
(let [c (count argv)]
|
||||
`(do ~@(map (fn [a] (apply-template argv expr a))
|
||||
(partition c values)))))
|
||||
|
|
@ -1311,6 +1311,20 @@
|
|||
# Java class jolt doesn't ship (e.g. reitit.Trie). __register-class-statics!
|
||||
# makes (Class/method ...) resolve; __register-class-methods! makes (.method
|
||||
# tagged-value ...) dispatch; __register-class-ctor! makes (Class. ...) build.
|
||||
# Reader-conditional feature toggle, exposed to Clojure so a namespace can
|
||||
# load a clj-targeted library (e.g. reitit, under :clj) WITHOUT forcing the
|
||||
# whole process to :clj — set features, require the lib, restore. Returns the
|
||||
# previous feature set (a list of name strings) for restoration.
|
||||
(ns-intern core "__reader-features"
|
||||
(fn [] (tuple ;(map (fn [k] (string k)) (keys reader-features)))))
|
||||
(ns-intern core "__reader-features-set!"
|
||||
(fn [names]
|
||||
# names arrives as a jolt vector (pvec) or list — coerce to a janet array
|
||||
(def arr (cond (pvec? names) (pv->array names)
|
||||
(or (tuple? names) (array? names)) names
|
||||
@[names]))
|
||||
(reader-features-set! (map (fn [n] (if (keyword? n) n (string n))) arr))
|
||||
nil))
|
||||
(ns-intern core "__register-class-statics!"
|
||||
(fn [nm tbl] (register-class-statics! nm tbl) nil))
|
||||
(ns-intern core "__register-class-methods!"
|
||||
|
|
|
|||
|
|
@ -129,10 +129,12 @@
|
|||
(register-class-statics! "LocalDateTime"
|
||||
@{"ofInstant" (fn [inst zone] (local-dt (ms-of inst)))
|
||||
"now" (fn [] (local-dt (math/floor (* 1000 (os/clock :realtime)))))})
|
||||
(register-class-statics! "Locale"
|
||||
@{"getDefault" (fn [] @{:jolt/type :jolt/locale :id "default"})
|
||||
"ENGLISH" @{:jolt/type :jolt/locale :id "en"}
|
||||
"US" @{:jolt/type :jolt/locale :id "en-US"}})
|
||||
(let [locale-statics @{"getDefault" (fn [] @{:jolt/type :jolt/locale :id "default"})
|
||||
"ENGLISH" @{:jolt/type :jolt/locale :id "en"}
|
||||
"US" @{:jolt/type :jolt/locale :id "en-US"}
|
||||
"ROOT" @{:jolt/type :jolt/locale :id "root"}}]
|
||||
(each nm ["Locale" "java.util.Locale"]
|
||||
(register-class-statics! nm locale-statics)))
|
||||
(register-tagged-methods! :jolt/instant
|
||||
@{"atZone" (fn [self zone] (zoned (self :ms) zone))
|
||||
"toEpochMilli" (fn [self] (self :ms))})
|
||||
|
|
|
|||
|
|
@ -212,3 +212,14 @@
|
|||
"(let [m (HashMap. {:a 1 :b 2})] (.get m :b))"]
|
||||
["HashMap put + size" "2"
|
||||
"(let [m (HashMap. {})] (.put m :x 1) (.put m :y 2) (.size m))"])
|
||||
|
||||
# Reader-feature toggle exposed to Clojure (scoped clj-lib loading): a
|
||||
# namespace can load a clj-targeted library under :clj without forcing the
|
||||
# whole process — set features, require, restore.
|
||||
(defspec "host-interop / reader-feature toggle"
|
||||
["features default to jolt+default" "true"
|
||||
"(contains? (set (__reader-features)) \"jolt\")"]
|
||||
["set + read back" "true"
|
||||
"(do (def prev (__reader-features)) (__reader-features-set! [\"clj\" \"jolt\" \"default\"]) (def r (contains? (set (__reader-features)) \"clj\")) (__reader-features-set! prev) r)"]
|
||||
["restore returns to default" "false"
|
||||
"(do (def prev (__reader-features)) (__reader-features-set! [\"clj\"]) (__reader-features-set! prev) (contains? (set (__reader-features)) \"clj\"))"])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue