Last active
May 15, 2019 18:03
-
-
Save NoamB/6e940775dfa63c73ee9c to your computer and use it in GitHub Desktop.
camelize-dasherize mini library
This file contains hidden or 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 util.camelize-dasherize | |
(:import (clojure.lang IPersistentMap Keyword)) | |
(:require [clojure.string :as s] | |
[clojure.zip :as zip])) | |
; TODO: regex is slow, should try iterating the string. | |
(defn dasherize-string | |
"Converts an underscored or camelized string | |
into an dasherized one." | |
[s] | |
(when s | |
(-> s | |
(s/replace #"([A-Z][a-z]+)" (fn [[match c]] | |
(if c (str "-" (s/lower-case c)) ""))) | |
(s/replace #"([A-Z]+)" "-$1") | |
(s/replace #"[-_\s]+" "-") | |
(s/replace #"^-" "")))) | |
(defn camelize-string | |
"Converts a string from dash-case to camelCase." | |
[^String s] | |
(when s | |
(some-> s | |
(s/replace #"[-_\s]+(.)?" | |
(fn [[match c]] | |
(if c (s/upper-case c) "")))))) | |
;(time (dotimes [x 400000] (dasherize-keyword :clientOSVersion))) | |
;"Elapsed time: 915.063554 msecs" | |
(defn dasherize-keyword | |
[k] | |
(when k | |
(keyword (dasherize-string (name k))))) | |
;(time (dotimes [x 400000] (camelize-keyword :client-OS-version))) | |
;"Elapsed time: 537.186386 msecs" | |
(defn camelize-keyword | |
[k] | |
(when k | |
(keyword (camelize-string (name k))))) | |
(defn camelize-map-1 [m] | |
(into {} (map (fn [[k v]] | |
[(camelize-keyword k) v]) m))) | |
(defn dasherize-map-1 [m] | |
(into {} (map (fn [[k v]] | |
[(dasherize-keyword k) v]) m))) | |
(defn camelize-map-recur [m] | |
(into {} (map (fn [[k v]] | |
[(camelize-keyword k) (if (map? v) (camelize-map-recur v) v)]) m))) | |
(defn dasherize-map-recur [m] | |
(into {} (map (fn [[k v]] | |
[(dasherize-keyword k) (if (map? v) (dasherize-map-recur v) v)]) m))) | |
(defn map-zipper [m] | |
(zip/zipper | |
(fn [x] (or (map? x) (map? (nth x 1)))) | |
(fn [x] (seq (if (map? x) x (nth x 1)))) | |
(fn [x children] | |
(if (map? x) | |
(into {} children) | |
(assoc x 1 (into {} children)))) | |
m)) | |
(defn edit-map-keys-zip [m f] | |
(loop [loc (map-zipper m)] | |
(if (zip/end? loc) | |
(zip/root loc) | |
(recur (zip/next | |
(if (vector? (zip/node loc)) | |
(zip/edit loc #(do [(f (first %)) (second %)])) | |
loc)))))) | |
(defn camelize-map-zip [m] | |
(edit-map-keys-zip m camelize-keyword)) | |
(defn dasherize-map-zip [m] | |
(edit-map-keys-zip m dasherize-keyword)) | |
(defprotocol ICamelizable | |
(camelize [this])) | |
(defprotocol IDasherizable | |
(dasherize [this])) | |
(extend-protocol ICamelizable | |
String | |
(camelize [this] | |
(camelize-string this)) | |
Keyword | |
(camelize [this] | |
(camelize-keyword this)) | |
IPersistentMap | |
(camelize [this] | |
(camelize-map-zip this))) | |
(extend-protocol IDasherizable | |
String | |
(dasherize [this] | |
(dasherize-string this)) | |
Keyword | |
(dasherize [this] | |
(dasherize-keyword this)) | |
IPersistentMap | |
(dasherize [this] | |
(dasherize-map-zip this))) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
What is the difference between
(s/replace #"([A-Z][a-z]+)" (fn [[match c]] (if c (str "-" (s/lower-case c)) "")))
and(s/lower-case s)
? The latter seems to do the same thing, but more simple