Skip to content

Commit

Permalink
Merge branch 'release-0.5.2'
Browse files Browse the repository at this point in the history
Conflicts:
	README.md
	project.clj
  • Loading branch information
greglook committed May 26, 2014
2 parents f029ce7 + 07055e2 commit 27591c3
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 184 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Puget

[![Build Status](https://travis-ci.org/greglook/puget.svg?branch=master)](https://travis-ci.org/greglook/puget)
[![Coverage Status](https://coveralls.io/repos/greglook/puget/badge.png?branch=master)](https://coveralls.io/r/greglook/puget?branch=master)
[![Dependency Status](https://www.versioneye.com/user/projects/53718bfb14c1589a89000144/badge.png)](https://www.versioneye.com/clojure/mvxcvi:puget/0.5.1)
[![Dependency Status](https://www.versioneye.com/user/projects/53718bfb14c1589a89000144/badge.png)](https://www.versioneye.com/clojure/mvxcvi:puget/0.5.2)

Puget is a Clojure library for printing [EDN](https://github.com/edn-format/edn)
values. Under the hood, Puget formats data into a _print document_ and uses the
Expand All @@ -20,7 +20,7 @@ To use this version with Leiningen, add the following dependency to your project
definition:

```clojure
[mvxcvi/puget "0.5.1"]
[mvxcvi/puget "0.5.2"]
```

## Syntax Coloring
Expand Down
6 changes: 4 additions & 2 deletions project.clj
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
(defproject mvxcvi/puget "0.5.1"
(defproject mvxcvi/puget "0.5.2"
:description "Colorizing canonical Clojure printer for EDN values."
:url "https://github.com/greglook/puget"
:license {:name "Public Domain"
:url "http://unlicense.org/"}

:deploy-branches ["master"]

:dependencies
[[org.clojure/clojure "1.6.0"]
[org.clojure/data.codec "0.1.0"]
[fipp "0.4.1"]]
[fipp "0.4.2"]]

:profiles
{:coverage
Expand Down
95 changes: 5 additions & 90 deletions src/puget/data.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,95 +4,9 @@
[clojure.data.codec.base64 :as b64])
(:import
(java.net URI)
(java.text SimpleDateFormat)
(java.util Date TimeZone UUID)))


;; TOTAL-ORDERING COMPARATOR

(defn- type-priority
"Determines the 'priority' of the given value based on its type:
- nil
- Boolean
- Number
- Character
- String
- Keyword
- Symbol
- List
- Vector
- Set
- Map
- (all other types)"
[x]
(let [predicates [nil? false? true? number? char? string?
keyword? symbol? list? vector? set? map?]
priority (->> predicates
(map vector (range))
(some (fn [[i p]] (when (p x) i))))]
(or priority (count predicates))))


(defn- compare-seqs
"Compare sequences using the given comparator. If any element of the
sequences orders differently, it determines the ordering. Otherwise, if the
prefix matches, the longer sequence sorts later."
[order xs ys]
(or (some #(when-not (= 0 %) %)
(map order xs ys))
(- (count xs) (count ys))))


(defn total-order
"Comparator function that provides a total-ordering of EDN values. Values of
different types sort in order of their types, per `type-priority`. `false`
is before `true`, numbers are ordered by magnitude regardless of type, and
characters, strings, keywords, and symbols are ordered lexically.
Sequential collections are sorted by comparing their elements one at a time.
If the sequences have equal leading elements, the longer one is ordered later.
Sets are compared by cardinality first, then elements in sorted order.
Finally, maps are compared by their entries in sorted order of their keys.
All other types are sorted by class name. If the class implements
`Comparable`, the instances of it are compared using `compare`. Otherwise, the
values are ordered by print representation."
[a b]
(if (= a b) 0
(let [pri-a (type-priority a)
pri-b (type-priority b)]
(cond
(< pri-a pri-b) -1
(> pri-a pri-b) 1

(some #(% a) #{number? char? string? keyword? symbol?})
(compare a b)

(map? a)
(compare-seqs total-order
(sort-by first total-order (seq a))
(sort-by first total-order (seq b)))

(set? a)
(let [size-diff (- (count a) (count b))]
(if (not= size-diff 0)
size-diff
(compare-seqs total-order a b)))

(coll? a)
(compare-seqs total-order a b)

:else
(let [class-diff (compare (.getName (class a))
(.getName (class b)))]
(if (not= class-diff 0)
class-diff
(if (instance? java.lang.Comparable a)
(compare a b)
(compare (pr-str a) (pr-str b)))))))))



;; TAGGED VALUE PROTOCOL

(defprotocol TaggedValue
Expand Down Expand Up @@ -153,10 +67,11 @@
(defn- format-utc
"Produces an ISO-8601 formatted date-time string from the given Date."
[^Date date]
(let [date-format (doto (java.text.SimpleDateFormat.
"yyyy-MM-dd'T'HH:mm:ss.SSS-00:00")
(.setTimeZone (TimeZone/getTimeZone "GMT")))]
(.format date-format date)))
(->
"yyyy-MM-dd'T'HH:mm:ss.SSS-00:00"
java.text.SimpleDateFormat.
(doto (.setTimeZone (TimeZone/getTimeZone "GMT")))
(.format date)))


(extend-tagged-value Date 'inst format-utc)
Expand Down
83 changes: 83 additions & 0 deletions src/puget/order.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
(ns puget.order
"Total ordering comparator for Clojure values.")


(defn- type-priority
"Determines the 'priority' of the given value based on its type:
- nil
- Boolean
- Number
- Character
- String
- Keyword
- Symbol
- List
- Vector
- Set
- Map
- (all other types)"
[x]
(let [predicates [nil? false? true? number? char? string?
keyword? symbol? list? vector? set? map?]
priority (->> predicates
(map vector (range))
(some (fn [[i p]] (when (p x) i))))]
(or priority (count predicates))))


(defn- compare-seqs
"Compare sequences using the given comparator. If any element of the
sequences orders differently, it determines the ordering. Otherwise, if the
prefix matches, the longer sequence sorts later."
[order xs ys]
(or (first (remove zero? (map order xs ys)))
(- (count xs) (count ys))))


(defn rank
"Comparator function that provides a total ordering of EDN values. Values of
different types sort in order of their types, per `type-priority`. `false`
is before `true`, numbers are ordered by magnitude regardless of type, and
characters, strings, keywords, and symbols are ordered lexically.
Sequential collections are sorted by comparing their elements one at a time.
If the sequences have equal leading elements, the longer one is ordered later.
Sets are compared by cardinality first, then elements in sorted order.
Finally, maps are compared by their entries in sorted order of their keys.
All other types are sorted by class name. If the class implements
`Comparable`, the instances of it are compared using `compare`. Otherwise, the
values are ordered by print representation."
[a b]
(if (= a b) 0
(let [pri-a (type-priority a)
pri-b (type-priority b)]
(cond
(< pri-a pri-b) -1
(> pri-a pri-b) 1

(some #(% a) #{number? char? string? keyword? symbol?})
(compare a b)

(map? a)
(compare-seqs rank
(sort-by first rank (seq a))
(sort-by first rank (seq b)))

(set? a)
(let [size-diff (- (count a) (count b))]
(if (zero? size-diff)
(compare-seqs rank a b)
size-diff))

(coll? a)
(compare-seqs rank a b)

:else
(let [class-diff (compare (.getName (class a))
(.getName (class b)))]
(if (zero? class-diff)
(if (instance? java.lang.Comparable a)
(compare a b)
(compare (pr-str a) (pr-str b)))
class-diff))))))
35 changes: 18 additions & 17 deletions src/puget/printer.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
"Functions for canonical colored printing of EDN values."
(:require
[clojure.string :as str]
[fipp.printer :refer [defprinter]]
[fipp.printer :as fipp]
(puget
[ansi :as ansi]
[data :as data])))
[data :as data]
[order :as order])))


;; CONTROL VARS
Expand Down Expand Up @@ -151,7 +152,7 @@

(defmethod canonize clojure.lang.IPersistentSet
[s]
(let [entries (sort data/total-order (seq s))]
(let [entries (sort order/rank (seq s))]
[:group
(color-doc :delimiter "#{")
[:align (interpose :line (map canonize entries))]
Expand All @@ -161,9 +162,7 @@
(defn- canonize-map
[m]
(let [canonize-kv (fn [[k v]] [:span (canonize k) " " (canonize v)])
entries (->> (seq m)
(sort-by first data/total-order)
(map canonize-kv))]
entries (->> (seq m) (sort-by first order/rank) (map canonize-kv))]
[:group
(color-doc :delimiter "{")
[:align (interpose [:span *map-delimiter* :line] entries)]
Expand Down Expand Up @@ -214,16 +213,22 @@

;; PRINT FUNCTIONS

(defprinter pprint canonize {:width 80})
(def ^:private default-opts
"Default Puget printing options."
{:width 80})


(defn pprint
([value]
(pprint value default-opts))
([value opts]
(fipp/pprint-document (canonize value) opts)))


(defn pprint-str
"Pretty-print a value to a string."
([value]
(-> value
pprint
with-out-str
str/trim-newline))
(pprint-str value default-opts))
([value opts]
(-> value
(pprint opts)
Expand All @@ -234,8 +239,7 @@
(defn cprint
"Like pprint, but turns on colored output."
([value]
(binding [*colored-output* true]
(pprint value)))
(cprint value default-opts))
([value opts]
(binding [*colored-output* true]
(pprint value opts))))
Expand All @@ -244,10 +248,7 @@
(defn cprint-str
"Pretty-prints a value to a colored string."
([value]
(-> value
cprint
with-out-str
str/trim-newline))
(cprint-str value default-opts))
([value opts]
(-> value
(cprint opts)
Expand Down

0 comments on commit 27591c3

Please sign in to comment.