Skip to content

Instantly share code, notes, and snippets.

@yogthos
Created March 5, 2015 16:02
Show Gist options
  • Save yogthos/5bacdfae6472262bada0 to your computer and use it in GitHub Desktop.
Save yogthos/5bacdfae6472262bada0 to your computer and use it in GitHub Desktop.
ascii table renderer for clj-pdf table format
(ns ascii-table)
(defn transpose [m]
(apply mapv vector m))
(defn col-width [rows text-width]
(let [num-cols (-> rows first count)]
(int (/ (- text-width 2 (dec num-cols)) num-cols))))
(defn height [length width]
(if (<= length width)
1
(int (+ (/ length width) (if (pos? (mod length width)) 1 0)))))
(defn pad-text [width text]
(let [delta (- width (count text))]
(if (pos? delta)
(concat text (repeat delta " "))
text)))
(defn partition-col [col width]
(let [partitioned (vec (partition-all width col))]
(map (partial apply str)
(update-in partitioned [(dec (count partitioned))] (partial pad-text width)))))
(defn set-column-height [width padding row]
(let [text-length (apply max (map count row))
num-lines (height text-length width)]
(for [col row]
(let [col-height (height (count col) width)]
(concat (partition-col col width)
(repeat (- num-lines col-height) padding))))))
(defn col-to-text [col & [text]]
(cond
(coll? col)
(apply str (map col-to-text (if (map? (second col)) (drop 2 col) (rest col))))
:else
(if text (str text " " col) col)))
(defn cols-to-text [row]
(map col-to-text row))
(defn to-table [[_ {:keys [header]} & rows] text-width]
(let [rows (map cols-to-text (if header (cons header rows) rows))
width (col-width rows text-width)
padding (clojure.string/join (repeat width " "))]
(map (partial set-column-height width padding) rows)))
(defn ascii-table [table width]
(let [sb (StringBuilder.)
rows (to-table table width)
col-count (count (first rows))
col-width (count (first (ffirst rows)))
width (+ (inc col-count) (* col-count col-width))]
(.append sb (apply str (repeat width "-")))
(.append sb "\n")
(doseq [row rows]
(doseq [col (transpose row)]
(.append sb "|")
(doseq [line (interpose "|" col)]
(.append sb line))
(.append sb "|\n"))
(.append sb (apply str (repeat width "-")))
(.append sb "\n"))
(.toString sb)))
;;example usage
#_(def data
[:table {:header ["Row 1" "Row 2" "Row 3"] :width 50 :border false :cell-border false}
[[:cell {:colspan 2} "Foo"] "Bar" "baz"]
["12345678910" "bar1" "baz1"]
["foo2" "bar212345566" "baz2"]
["foo4" "bar212345566" "ba234324z2"]])
#_(spit "table.txt" (ascii-table data 80))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment