Last active
May 25, 2023 04:34
-
-
Save lotuc/fba421f74ea8610494118bc899f9f1b5 to your computer and use it in GitHub Desktop.
Clojure Utilities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns camel-snake-kebab-rexport | |
(:require | |
[camel-snake-kebab.core :as csk] | |
[camel-snake-kebab.internals.string-separator | |
:refer [split classify-char StringSeparator]])) | |
;;; kebab patch | |
;;; https://gist.github.com/lotuc/fba421f74ea8610494118bc899f9f1b5#file-camel_snake_kebab_utils-clj | |
(defn generic-split [ss] | |
(let [cs (mapv classify-char ss) | |
ss-length (.length ^String ss)] | |
(loop [result (transient []), start 0, current 0] | |
(let [next (inc current) | |
result+new (fn [end] | |
(if (> end start) | |
(conj! result (.substring ^String ss start end)) | |
result))] | |
(cond (>= current ss-length) | |
(or (seq (persistent! (result+new current))) | |
;; Return this instead of an empty seq: | |
[""]) | |
(= (nth cs current) :whitespace) | |
(recur (result+new current) next next) | |
(let [[a b c] (subvec cs current)] | |
;; This expression is not pretty, | |
;; but it compiles down to sane JavaScript. | |
(or (and (not= a :upper) (= b :upper)) | |
(and (= a :number) (not= b :number)) ; changed here. | |
(and (= a :upper) (= b :upper) (= c :lower)))) | |
(recur (result+new next) next next) | |
:else | |
(recur result start next)))))) | |
(def separator (reify StringSeparator (split [_ s] (generic-split s)))) | |
(comment | |
(split separator "md5") | |
(csk/->kebab-case-keyword "md5" {:separator separator}) | |
(csk/->kebab-case-keyword "md5")) | |
(defmacro ^:private reexport [& names] | |
`(do | |
~@(for [n names] | |
`(defn ~n [s# & rest#] | |
(~(symbol "csk" (name n)) | |
s# (merge {:separator separator} rest#)))))) | |
(reexport | |
->PascalCase | |
->Camel_Snake_Case | |
->camelCase | |
->SCREAMING_SNAKE_CASE | |
->snake_case | |
->kebab-case | |
->HTTP-Header-Case | |
->PascalCaseKeyword | |
->camelCaseKeyword | |
->SCREAMING_SNAKE_CASE_KEYWORD | |
->snake_case_keyword | |
->kebab-case-keyword | |
->Camel_Snake_Case_Keyword | |
->HTTP-Header-Case-Keyword | |
->PascalCaseString | |
->camelCaseString | |
->SCREAMING_SNAKE_CASE_STRING | |
->snake_case_string | |
->kebab-case-string | |
->Camel_Snake_Case_String | |
->HTTP-Header-Case-String | |
->PascalCaseSymbol | |
->camelCaseSymbol | |
->SCREAMING_SNAKE_CASE_SYMBOL | |
->snake_case_symbol | |
->kebab-case-symbol | |
->Camel_Snake_Case_Symbol | |
->HTTP-Header-Case-Symbol) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Problem | |
;; md5 becomes md-5, which is not intended. | |
;; **Do such a global patch maybe problematic** | |
;; maybe just wrap your own converter | |
;; Some thirdparty libraries depends on the original behavior. | |
;; A dirty patch which changes the default separator. | |
;; https://github.com/clj-commons/camel-snake-kebab/blob/ac08444c94aca4cba25d86f3b3faf36596809380/src/camel_snake_kebab/internals/misc.cljc#LL6C53-L6C53 | |
;; https://github.com/clj-commons/camel-snake-kebab/blob/ac08444c94aca4cba25d86f3b3faf36596809380/src/camel_snake_kebab/internals/string_separator.cljc#L64 | |
;; https://github.com/clj-commons/camel-snake-kebab/issues/42#issuecomment-352219297 | |
#_{:clj-kondo/ignore [:unused-namespace]} | |
(require '[camel-snake-kebab.core :as csk]) | |
(require '[camel-snake-kebab.internals.string-separator | |
:refer [classify-char StringSeparator]]) | |
(defn generic-split [ss] | |
(let [cs (mapv classify-char ss) | |
ss-length #?(:clj (.length ^String ss) | |
:cljs (.-length ss))] | |
(loop [result (transient []), start 0, current 0] | |
(let [next (inc current) | |
result+new (fn [end] | |
(if (> end start) | |
(conj! result (.substring ^String ss start end)) | |
result))] | |
(cond (>= current ss-length) | |
(or (seq (persistent! (result+new current))) | |
;; Return this instead of an empty seq: | |
[""]) | |
(= (nth cs current) :whitespace) | |
(recur (result+new current) next next) | |
(let [[a b c] (subvec cs current)] | |
;; This expression is not pretty, | |
;; but it compiles down to sane JavaScript. | |
(or (and (not= a :upper) (= b :upper)) | |
(and (= a :number) (not= b :number)) ;; Note this is what we changed. | |
(and (= a :upper) (= b :upper) (= c :lower)))) | |
(recur (result+new next) next next) | |
:else | |
(recur result start next)))))) | |
#_{:clj-kondo/ignore [:unresolved-namespace]} | |
(alter-var-root | |
#'camel-snake-kebab.internals.string-separator/generic-separator | |
(fn [_] (reify StringSeparator | |
(split [_ s] (generic-split s))))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; References | |
;; - https://github.com/Olical/clojure-giants-shoulders | |
{:paths ["src"] | |
:deps | |
{;; re-export vars & more | |
potemkin/potemkin {:mvn/version "0.4.6"}} | |
:aliases | |
{:dev | |
{:extra-paths ["envs/dev"] | |
:extra-deps | |
{com.lambdaisland/classpath {:mvn/version "0.4.44"} ;; watch deps.edn & reload dependencies | |
flames/flames {:mvn/version "0.5.0"}}} | |
;; list outdated dependencies: clojure -M:outdated | |
:outdated | |
{:deps {com.github.liquidz/antq {:mvn/version "2.4.1070"}} | |
:main-opts ["-m" "antq.core"]} | |
}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; https://github.com/clj-commons/potemkin/issues/31 | |
#?(:clj (require '[potemkin :refer [import-vars]]) | |
:cljs | |
(do | |
(defmacro import-def | |
"import a single fn or var | |
(import-def a b) => (def b a/b) | |
" | |
[from-ns def-name] | |
(let [from-sym# (symbol (str from-ns) (str def-name))] | |
`(def ~def-name ~from-sym#))) | |
(defmacro import-vars | |
"import multiple defs from multiple namespaces | |
works for vars and fns. not macros. | |
(same syntax as potemkin.namespaces/import-vars) | |
(import-vars | |
[m.n.ns1 a b] | |
[x.y.ns2 d e f]) => | |
(def a m.n.ns1/a) | |
(def b m.n.ns1/b) | |
... | |
(def d m.n.ns2/d) | |
... etc | |
" | |
[& imports] | |
(let [expanded-imports | |
(for [[from-ns & defs] imports d defs] | |
`(import-def ~from-ns ~d))] | |
`(do ~@expanded-imports))))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(require '[malli.core :as m]) | |
(require '[malli.transform :as mt]) | |
(require '[malli.util :as mu]) | |
(defn transform-keys | |
[schema t] | |
(let [t' (partial map (fn [[k p s]] [(t k) p s])) | |
w #(cond-> % | |
(m/entries %) | |
(mu/transform-entries t'))] | |
(m/walk schema (m/schema-walker w)))) | |
(comment | |
(transform-keys [:map [:a :string]] name) ; => [:map ["a" :string]] | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment