diff --git a/CHANGELOG.md b/CHANGELOG.md index a7a3e57..38ad501 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - New table option `:max-width` to resize columns that would be too big, defaults to terminal width if possible. +- Support more shapes of data directly, i.e. vector of vectors, or a + single map. ### Changed - The RenderTable/render-table protocol method signature has changed. diff --git a/src/crockery/core.cljc b/src/crockery/core.cljc index fabdd12..2afa6bb 100644 --- a/src/crockery/core.cljc +++ b/src/crockery/core.cljc @@ -4,7 +4,7 @@ [crockery.gfm :as gfm] [crockery.tsv :as tsv] [crockery.protocols :as p] - [crockery.util :refer [to-column-map normalize-column]])) + [crockery.util :refer [to-column-map normalize-column data->cols-rows]])) (def ^:dynamic *default-options* {:format :org :defaults {:align :left}}) @@ -83,12 +83,13 @@ (let [{:keys [format defaults] :as opts} (merge *default-options* opts) renderer (get (builtin-renderers) format format) ;;_ (assert (satisfies? p/RenderTable renderer)) + [detected-cols data] (data->cols-rows data) cols (into [] (comp (map to-column-map) (map #(merge defaults %)) (map normalize-column)) (or cols (:columns opts) - (-> data first keys)))] + detected-cols))] (p/render-table renderer opts cols data)))) (defn print-table diff --git a/src/crockery/util.cljc b/src/crockery/util.cljc index c74ecee..2659448 100644 --- a/src/crockery/util.cljc +++ b/src/crockery/util.cljc @@ -20,6 +20,35 @@ s (pad-spaces (Math/ceil half-padding))))))) + +(defn- non-string-seq? [coll] + (and (seqable? coll) (not (string? coll)))) + +(defn data->cols-rows [data] + (cond + (map? data) + [[:key :value] + (map (fn [[k v]] {:key k :value v}) data)] + + (non-string-seq? data) + (let [f (first data)] + (cond + (map? f) + [(keys f) + data] + + (non-string-seq? f) + [(map-indexed (fn [i h] {:name i :title h}) f) + (rest data)] + + :else + [[:value] + (map (fn [v] {:value v}) data)])) + + :else + [[:value] + [{:value data}]])) + (defn normalize-column [{:keys [key-fn title title-align align render-title render-cell] :as col}] (let [nm (:name col)] (merge col diff --git a/test/crockery/core_test.clj b/test/crockery/core_test.clj index 3d74f1b..0e0e23a 100644 --- a/test/crockery/core_test.clj +++ b/test/crockery/core_test.clj @@ -94,6 +94,51 @@ people) expected)))) +(deftest test-vec-of-vecs + (let [expected ["|-----------+-----|" + "| Name | Age |" + "|-----------+-----|" + "| Alice | 29 |" + "| Bob | 22 |" + "| Charlotte | 42 |" + "|-----------+-----|"] + data (into [["Name" "Age"]] + (map (juxt :name :age)) + people)] + (is (table? (table-as-string data) expected)))) + +(deftest test-vec-of-strings + (let [expected ["|-------|" + "| Value |" + "|-------|" + "| a |" + "| bbb |" + "| c |" + "|-------|"] + data ["a" "bbb" "c"]] + (is (table? (table-as-string data) expected)))) + +(deftest test-plain-map + (let [expected ["|---------+----------|" + "| Key | Value |" + "|---------+----------|" + "| :what | 1 |" + "| :are | 42 |" + "| :you | testtest |" + "| :Saying | 10.0 |" + "|---------+----------|"] + data {:what "1" :are 42 :you "testtest" :Saying 10.0}] + (is (table? (table-as-string data) expected)))) + +(deftest test-plain-value + (let [data #inst "2014-04-17T12:34:56.789-00:00" + expected ["|--------------------------|" + "| Value |" + "|--------------------------|" + "| 2014-04-17T12:34:56.789Z |" + "|--------------------------|"]] + (is (table? (table-as-string data) expected)))) + (deftest test-alignment (testing "Title alignment can differ" (let [rendered (table-as-string [{:key-fn :name