-
Notifications
You must be signed in to change notification settings - Fork 0
/
inflection.cljc
105 lines (94 loc) · 2.96 KB
/
inflection.cljc
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
(ns dgknght.app-lib.inflection
(:require [clojure.string :as string]
[dgknght.app-lib.core :refer [ensure-string]]
#?(:cljs [goog.string :as gstr])))
(defn humanize
"Accepts a value in kabob case and returns the value in human friendly form"
[value]
(-> value
ensure-string
(string/replace #"[_-]" " ")
(string/replace #" id$" "")
string/capitalize))
(def ^:private title-case-ignore-patterns
[#"^\s+$"
#"^[A-Z]+$"])
(defn- title-case-ignore?
[word]
(some #(re-matches % word) title-case-ignore-patterns))
(defn- title-case-word
[word]
(if (title-case-ignore? word)
word
(string/capitalize word)))
(defn title-case
"Renders the string in title case. E.g.
(title-case \"my important thing\") => \"My Important Thing\""
[s]
(->> (-> s
ensure-string
(string/replace "-" " ")
(string/split #"\b"))
(map title-case-word)
(string/join "")))
(defn ordinal
"Accepts a number and returns a string expressing the value
as an ordinal. E.g., 1 => '1st'"
[number]
(let [rules [{:pattern #"(?:[2-9]|\b|^)1\z"
:suffix "st"}
{:pattern #"(?:[2-9]|\b|^)2\z"
:suffix "nd"}
{:pattern #"(?:[2-9]|\b|^)3\z"
:suffix "rd"}
{:pattern #"."
:suffix "th"}]
s (str number)]
(str s (some #(when (re-find (:pattern %) s)
(:suffix %))
rules))))
(defn- apply-matching-rule
[word {pattern :pattern f :fn}]
(when-let [match (re-find pattern word)]
(f match)))
(defn singular
"Accepts a plural noun and attempts to convert it into singular"
[word]
(let [rules [{:pattern #"(?i)\A(child)ren\z"
:fn second}
{:pattern #"(.+)s\z"
:fn second}]]
(some (partial apply-matching-rule word) rules)))
(defn plural
"Acceps a singular noun and attempts to convert it into plural"
[word]
(let [[kw word] (if (keyword? word)
[true (name word)]
[false word])
rules [{:pattern #".*(?=y\z)"
:fn (fn [match] (str match "ies"))}
{:pattern #".*"
:fn (fn [match] (str match "s"))}]
result (some (partial apply-matching-rule word) rules)]
(if kw
(keyword result)
result)))
(defn- fmt
[msg & args]
#?(:clj (apply format msg args)
:cljs (apply gstr/format msg args)))
(defn conjoin
"Accepts a sequences and returns a comma delimited string
with the specified conjunction between the final two elements"
[conjunction col]
(case (count col)
1 (ensure-string (first col))
2 (fmt "%s %s %s"
(ensure-string (first col))
conjunction
(ensure-string (second col)))
(let [strings (map ensure-string col)]
(fmt "%s, %s %s"
(string/join ", " (butlast strings))
conjunction
(last strings)))))