cl-format

added
1.2

ns
clojure.pprint

type
function

(cl-format writer format-in & args)

An implementation of a Common Lisp compatible format function. cl-format formats its
arguments to an output stream or string based on the format control string given. It 
supports sophisticated formatting of structured data.

Writer is an instance of java.io.Writer, true to output to *out* or nil to output 
to a string, format-in is the format control string and the remaining arguments 
are the data to be formatted.

The format control string is a string to be output with embedded 'format directives' 
describing how to format the various arguments passed in.

If writer is nil, cl-format returns the formatted result string. Otherwise, cl-format 
returns nil.

For example:
(let [results [46 38 22]]
(cl-format true "There ~[are~;is~:;are~]~:* ~d result~:p: ~{~d~^, ~}~%" 
(count results) results))

Prints to *out*:
There are 3 results: 46, 38, 22

Detailed documentation on format control strings is available in the "Common Lisp the 
Language, 2nd edition", Chapter 22 (available online at:
http://www.cs.cmu.edu/afs/cs.cmu.edu/project/ai-repository/ai/html/cltl/clm/node200.html#SECTION002633000000000000000) 
and in the Common Lisp HyperSpec at 
http://www.lispworks.com/documentation/HyperSpec/Body/22_c.htm

                ;; Formatting integers, with options, in one of many bases.

;; First arg true sends formatted output to *out*
user=> (cl-format true "~5d\
" 3)
    3
nil

;; First arg nil or false causes formatted output to be returned as string
user=> (cl-format nil "~5d" 3)
"    3"

user=> (cl-format nil "Pad with leading zeros ~5,'0d" 3)
"Pad with leading zeros 00003"

user=> (cl-format nil "Pad with leading asterisks ~5,'*d" 3)
"Pad with leading asterisks ****3"

;; If there is a way to specify left-justifying a number in a single
;; format string, please add it here.  It can be done by using one
;; cl-format invocation to get a formatted number as a string, and
;; then use the ~<width>a specifier on the result.
user=> (cl-format nil "~15a" (cl-format nil "~:d" 1234567))
"1,234,567      "

;; To specify left-justifying a number in a single format string, you can use:
user=> (cl-format nil "~15@<~:d~>" 1234567)
"1,234,567      "

user=> (cl-format nil "Always print the sign ~5@d" 3)
"Always print the sign    +3"

user=> (cl-format nil "Use comma group-separator every 3 digits ~12:d" 1234567)
"Use comma group-separator every 3 digits    1,234,567"

user=> (cl-format nil "decimal ~d  binary ~b  octal ~o  hex ~x" 63 63 63 63)
"decimal 63  binary 111111  octal 77  hex 3f"

user=> (cl-format nil "base 7  ~7r  with width and zero pad  ~7,15,'0r" 63 63)
"base 7  120  with width and zero pad  000000000000120"

;; No need for you to do any conversions to use cl-format with BigInt,
;; BigInteger, or BigDecimal.
user=> (cl-format nil "cl-format handles BigInts ~15d" 12345678901234567890)
"cl-format handles BigInts 12345678901234567890"

user=> (cl-format nil "Be aware of auto-conversion  ~8,'0d  ~8,'0d" 2.4 -5/4)
"Be aware of auto-conversion  000002.4  0000-5/4"

;; This might look like a bug, but it is actually behavior specified by the
;; Common Lisp HyperSpec mentioned in the docs above.  If you don't want that
;; behavior (format "%08d" -2) might suit your purposes better.
user=> (cl-format nil "~8,'0d" -2)
"000000-2"
            
                (let [examples [[]
                ["Alice"]
                ["Alice" "Bob"]
                ["Alice" "Bob" "Charlie"]]]
  (doseq [users examples]
    (cljs.pprint/cl-format true "~1{~#[none~;~a~;~a and ~a~:;~@{~#[~;and ~]~a~^, ~}~]~:} ~:*~1{~#[are~;is~:;are~]~:} online" users)))

;; Prints the following:

none are online
Alice is online
Alice and Bob are online
Alice, Bob, and Charlie are online

;; The following guide for Common Lisp format is available here. The examples applies to Clojure as well:
;; http://www.gigamonkeys.com/book/a-few-format-recipes.html
            
                ;; cl-format knows what nil should look like:
user=> (cl-format nil "~s" nil)
"nil"
;; format doesn't:
user=> (format "%s" nil)
"null"