In the cljs slack channel (which you should join), someone asked if there is a cljs library for humanizing text. I pointed them to a new (to cljs) feature that’s already available via cljs.pprint: cl-format. (Note that this also applies to clj as it already supported pretty-printing thanks to Tom Faulhaber et al).

cl-format is a cljs version of Common Lisp’s FORMAT function. It provides a ton of functionality, so much so that there’s a full pdf describing it. For a gentler, yet still expansive description, check out a few FORMAT recipes.

Here are a few examples of humanizing text, taken from django.contrib.humanize and HubSpot/humanize.

From django:

  • apnumber - For numbers 1-9, returns the number spelled out. Otherwise, returns the number. This follows Associated Press style.

  • intcomma - Converts an integer to a string containing commas every three digits.

  • intword - Converts a large integer to a friendly text representation.

cljs.user=> (require '[cljs.pprint :refer [cl-format]])
nil
cljs.user=> (defn ap-number [n]
              ;;if (< 0 n 10) use the ~R directive, otherwise use ~A
              (cl-format nil "~:[~a~;~r~]" (< 0 n 10) n))
#<function ...>
cljs.user=> (ap-number -1)
"-1"
cljs.user=> (ap-number 0)
"0"
cljs.user=> (ap-number 1)
"one"
cljs.user=> (ap-number 9)
"nine"
cljs.user=> (ap-number 10)
"10"

cljs.user=> (defn int-comma [n] (cl-format nil "~:d" n))
#<function ...>
cljs.user=> (int-comma 1000)
"1,000"
cljs.user=> (int-comma 1000000)
"1,000,000"
cljs.user=> (int-comma 123456789)
"123,456,789"

cljs.user=> (defn int-word [n] (cl-format nil "~r" n))
#<function ...>
cljs.user=> (int-word 100)
"one hundred"
cljs.user=> (int-word 10000)
"ten thousand"
cljs.user=> (int-word 100000)
"one hundred thousand"
cljs.user=> (int-word 123456789)
"one hundred twenty-three million, four hundred fifty-six thousand, seven hundred eighty-nine"

From Hubspot:

  • capitalize - Capitalizes the first letter in a string, downcasing the tail.

  • capitalizeAll - Capitalize the first letter of every word in a string.

cljs.user=> (defn capitalize [s] (cl-format nil "~@(~a~)" s))
#<function ...>
cljs.user=> (capitalize "some boring string")
"Some boring string"
cljs.user=> (capitalize "WeiRd cAsINg")
"Weird casing"

cljs.user=> (defn capitalize-all [s] (cl-format nil "~:(~a~)" s))
#<function ...>
cljs.user=> (capitalize-all "some boring string")
"Some Boring String"
cljs.user=> (capitalize-all "WeiRd cAsINg")
"Weird Casing"

cl-format also provides support for pluralization, conditional formatting, and a whole host of other things. The pluralization only supports simple cases of adding “s” and “y” => “ies” and all printing is based on English, so it’s not useful in every case. But it’s very nice to have and it’s only a simple (require 'cljs.pprint) away.

Find this post useful? Share the love!

Recent Posts