summaryrefslogtreecommitdiff
path: root/src/assets/viz/1/clojure/string.cljs
diff options
context:
space:
mode:
authorBrian Picciano <mediocregopher@gmail.com>2021-01-21 17:22:53 -0700
committerBrian Picciano <mediocregopher@gmail.com>2021-01-21 17:22:53 -0700
commitbcf9b230be6d74c71567fd0771b31d47d8dd39c7 (patch)
tree2d0fc16142d55bbd5876ac6b8174c2857883b40e /src/assets/viz/1/clojure/string.cljs
parentd57fd70640948cf20eeb41b56e8d4e23e616cec0 (diff)
build the blog with nix
Diffstat (limited to 'src/assets/viz/1/clojure/string.cljs')
-rw-r--r--src/assets/viz/1/clojure/string.cljs258
1 files changed, 258 insertions, 0 deletions
diff --git a/src/assets/viz/1/clojure/string.cljs b/src/assets/viz/1/clojure/string.cljs
new file mode 100644
index 0000000..4cf5ede
--- /dev/null
+++ b/src/assets/viz/1/clojure/string.cljs
@@ -0,0 +1,258 @@
+; Copyright (c) Rich Hickey. All rights reserved.
+; The use and distribution terms for this software are covered by the
+; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+; which can be found in the file epl-v10.html at the root of this distribution.
+; By using this software in any fashion, you are agreeing to be bound by
+; the terms of this license.
+; You must not remove this notice, or any other, from this software.
+
+(ns clojure.string
+ (:refer-clojure :exclude [replace reverse])
+ (:require [goog.string :as gstring])
+ (:import [goog.string StringBuffer]))
+
+(defn- seq-reverse
+ [coll]
+ (reduce conj () coll))
+
+(def ^:private re-surrogate-pair
+ (js/RegExp. "([\\uD800-\\uDBFF])([\\uDC00-\\uDFFF])" "g"))
+
+(defn reverse
+ "Returns s with its characters reversed."
+ [s]
+ (-> (.replace s re-surrogate-pair "$2$1")
+ (.. (split "") (reverse) (join ""))))
+
+(defn- replace-all
+ [s re replacement]
+ (.replace s (js/RegExp. (.-source re) "g") replacement))
+
+(defn- replace-with
+ [f]
+ (fn [& args]
+ (let [matches (drop-last 2 args)]
+ (if (= (count matches) 1)
+ (f (first matches))
+ (f (vec matches))))))
+
+(defn replace
+ "Replaces all instance of match with replacement in s.
+ match/replacement can be:
+
+ string / string
+ pattern / (string or function of match)."
+ [s match replacement]
+ (cond
+ (string? match)
+ (.replace s (js/RegExp. (gstring/regExpEscape match) "g") replacement)
+
+ (instance? js/RegExp match)
+ (if (string? replacement)
+ (replace-all s match replacement)
+ (replace-all s match (replace-with replacement)))
+
+ :else (throw (str "Invalid match arg: " match))))
+
+(defn replace-first
+ "Replaces the first instance of match with replacement in s.
+ match/replacement can be:
+
+ string / string
+ pattern / (string or function of match)."
+ [s match replacement]
+ (.replace s match replacement))
+
+(defn join
+ "Returns a string of all elements in coll, as returned by (seq coll),
+ separated by an optional separator."
+ ([coll]
+ (loop [sb (StringBuffer.) coll (seq coll)]
+ (if-not (nil? coll)
+ (recur (. sb (append (str (first coll)))) (next coll))
+ (.toString sb))))
+ ([separator coll]
+ (loop [sb (StringBuffer.) coll (seq coll)]
+ (if-not (nil? coll)
+ (do
+ (. sb (append (str (first coll))))
+ (let [coll (next coll)]
+ (when-not (nil? coll)
+ (. sb (append separator)))
+ (recur sb coll)))
+ (.toString sb)))))
+
+(defn upper-case
+ "Converts string to all upper-case."
+ [s]
+ (.toUpperCase s))
+
+(defn lower-case
+ "Converts string to all lower-case."
+ [s]
+ (.toLowerCase s))
+
+(defn capitalize
+ "Converts first character of the string to upper-case, all other
+ characters to lower-case."
+ [s]
+ (if (< (count s) 2)
+ (upper-case s)
+ (str (upper-case (subs s 0 1))
+ (lower-case (subs s 1)))))
+
+;; The JavaScript split function takes a limit argument but the return
+;; value is not the same as the Java split function.
+;;
+;; Java: (.split "a-b-c" #"-" 2) => ["a" "b-c"]
+;; JavaScript: (.split "a-b-c" #"-" 2) => ["a" "b"]
+;;
+;; For consistency, the three arg version has been implemented to
+;; mimic Java's behavior.
+
+(defn- pop-last-while-empty
+ [v]
+ (loop [v v]
+ (if (identical? "" (peek v))
+ (recur (pop v))
+ v)))
+
+(defn- discard-trailing-if-needed
+ [limit v]
+ (if (and (== 0 limit) (< 1 (count v)))
+ (pop-last-while-empty v)
+ v))
+
+(defn- split-with-empty-regex
+ [s limit]
+ (if (or (<= limit 0) (>= limit (+ 2 (count s))))
+ (conj (vec (cons "" (map str (seq s)))) "")
+ (condp == limit
+ 1 (vector s)
+ 2 (vector "" s)
+ (let [c (- limit 2)]
+ (conj (vec (cons "" (subvec (vec (map str (seq s))) 0 c))) (subs s c))))))
+
+(defn split
+ "Splits string on a regular expression. Optional argument limit is
+ the maximum number of splits. Not lazy. Returns vector of the splits."
+ ([s re]
+ (split s re 0))
+ ([s re limit]
+ (discard-trailing-if-needed limit
+ (if (identical? "/(?:)/" (str re))
+ (split-with-empty-regex s limit)
+ (if (< limit 1)
+ (vec (.split (str s) re))
+ (loop [s s
+ limit limit
+ parts []]
+ (if (== 1 limit)
+ (conj parts s)
+ (let [m (re-find re s)]
+ (if-not (nil? m)
+ (let [index (.indexOf s m)]
+ (recur (.substring s (+ index (count m)))
+ (dec limit)
+ (conj parts (.substring s 0 index))))
+ (conj parts s))))))))))
+
+(defn split-lines
+ "Splits s on \n or \r\n."
+ [s]
+ (split s #"\n|\r\n"))
+
+(defn trim
+ "Removes whitespace from both ends of string."
+ [s]
+ (gstring/trim s))
+
+(defn triml
+ "Removes whitespace from the left side of string."
+ [s]
+ (gstring/trimLeft s))
+
+(defn trimr
+ "Removes whitespace from the right side of string."
+ [s]
+ (gstring/trimRight s))
+
+(defn trim-newline
+ "Removes all trailing newline \\n or return \\r characters from
+ string. Similar to Perl's chomp."
+ [s]
+ (loop [index (.-length s)]
+ (if (zero? index)
+ ""
+ (let [ch (get s (dec index))]
+ (if (or (identical? \newline ch)
+ (identical? \return ch))
+ (recur (dec index))
+ (.substring s 0 index))))))
+
+(defn ^boolean blank?
+ "True is s is nil, empty, or contains only whitespace."
+ [s]
+ (gstring/isEmptySafe s))
+
+(defn escape
+ "Return a new string, using cmap to escape each character ch
+ from s as follows:
+
+ If (cmap ch) is nil, append ch to the new string.
+ If (cmap ch) is non-nil, append (str (cmap ch)) instead."
+ [s cmap]
+ (let [buffer (StringBuffer.)
+ length (.-length s)]
+ (loop [index 0]
+ (if (== length index)
+ (. buffer (toString))
+ (let [ch (.charAt s index)
+ replacement (get cmap ch)]
+ (if-not (nil? replacement)
+ (.append buffer (str replacement))
+ (.append buffer ch))
+ (recur (inc index)))))))
+
+(defn index-of
+ "Return index of value (string or char) in s, optionally searching
+ forward from from-index or nil if not found."
+ ([s value]
+ (let [result (.indexOf s value)]
+ (if (neg? result)
+ nil
+ result)))
+ ([s value from-index]
+ (let [result (.indexOf s value from-index)]
+ (if (neg? result)
+ nil
+ result))))
+
+(defn last-index-of
+ "Return last index of value (string or char) in s, optionally
+ searching backward from from-index or nil if not found."
+ ([s value]
+ (let [result (.lastIndexOf s value)]
+ (if (neg? result)
+ nil
+ result)))
+ ([s value from-index]
+ (let [result (.lastIndexOf s value from-index)]
+ (if (neg? result)
+ nil
+ result))))
+
+(defn ^boolean starts-with?
+ "True if s starts with substr."
+ [s substr]
+ (gstring/startsWith s substr))
+
+(defn ^boolean ends-with?
+ "True if s ends with substr."
+ [s substr]
+ (gstring/endsWith s substr))
+
+(defn ^boolean includes?
+ "True if s includes substr."
+ [s substr]
+ (gstring/contains s substr))