Skip to content

Commit

Permalink
Merge branch 'release-0.9.0'
Browse files Browse the repository at this point in the history
Conflicts:
	CHANGELOG.md
	README.md
	project.clj
  • Loading branch information
greglook committed Oct 13, 2015
2 parents 5491c2c + 1456614 commit a008fb0
Show file tree
Hide file tree
Showing 15 changed files with 772 additions and 629 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@ Release Notes

This page documents the high-level changes in each release of Puget.

## 0.9.0 (2015-10-13)

- Upgrade to Clojure 1.7 and fipp 0.6.2.
- Separate total-order comparator into
[mvxcvi/arrangement](https://github.com/greglook/clj-arrangement).
- Reordered args to `color/document` and `color/text`.
- Drop `puget.data/ExtendedNotation` protocol and switched to type-dispatched
print-handler approach.
- Rename `:sort-key` option to `:sort-mode`.
- Remove `:escape-types` functionality in favor of `:print-handlers`.
- Add more `:print-fallback` possibilities.
- Add `CanonicalPrinter` as a minimalist alternative to `PrettyPrinter`.

## 0.8.1 (2015-04-25)

- Remove `tagged-literal` code which conflicts with the built-in `clojure.core`
Expand Down
152 changes: 80 additions & 72 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
Puget
=====

[![Build Status](https://travis-ci.org/greglook/puget.svg?branch=develop)](https://travis-ci.org/greglook/puget)
[![Coverage Status](https://coveralls.io/repos/greglook/puget/badge.png?branch=develop)](https://coveralls.io/r/greglook/puget?branch=develop)
[![Dependency Status](https://www.versioneye.com/user/projects/53718bfb14c1589a89000144/badge.png)](https://www.versioneye.com/clojure/mvxcvi:puget/0.8.1)
[![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?style=flat)](https://www.versioneye.com/clojure/mvxcvi:puget)
[![API codox](http://b.repl.ca/v1/doc-API-blue.png)](https://greglook.github.io/puget/api/)
[![marginalia docs](http://b.repl.ca/v1/doc-marginalia-blue.png)](https://greglook.github.io/puget/marginalia/uberdoc.html)

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
[Fast Idiomatic Pretty-Printer](https://github.com/brandonbloom/fipp) library to
render it. Puget offers two main features which set it apart from FIPP and
Clojure's native pretty-printing functions: [syntax coloring](#syntax-coloring)
and [canonical printing](#canonical-representation).
Puget is a Clojure library for printing Clojure and
[EDN](https://github.com/edn-format/edn) values. Under the hood, Puget formats
data into a _print document_ and uses the [Fast Idiomatic
Pretty-Printer](https://github.com/brandonbloom/fipp) library to render it.

Puget offers two main features which set it apart from FIPP and Clojure's native
pretty-printing functions: [syntax coloring](#syntax-coloring) and [canonical
printing](#canonical-representation). Custom rendering is supported using type
dispatch to select [print handlers](#type-extensions).

## Installation

Expand All @@ -23,6 +26,25 @@ Leiningen, add the following dependency to your project definition:

See [Whidbey](https://github.com/greglook/whidbey) for nREPL and Leiningen integration.

## Usage

Puget's printing is controlled by a map of options which include print width,
sorting mode, color scheme and style, whether to print metadata, and so on. The
default options are held in the dynamic var `puget.printer/*options*`. This can
be bound with the `with-options` macro for convenience.

These options are used to construct a _printer_ object to render values with.
You can create these manually with `pretty-printer` or `canonical-printer`, then
use them with `render-out` or `render-str` for maximum control.

These options are used to construct a printer record, which is either the
`PrettyPrinter` or `CanonicalPrinter`. The printers can be used directly to
render values with `render-out` or `render-str` if maximal repeatability is
desired.

Otherwise, the `pprint` and `pprint-str` functions will automatically create a
`PrettyPrinter` using the dynamic options and any provided configuration.

## Syntax Coloring

Puget's first main feature is colorizing the printed data using ANSI escape
Expand All @@ -38,13 +60,8 @@ function always prints with colored output enabled:
![colorization example](screenshot.png)

The `:color-markup` option defaults to `:ansi`, but can be set to `:html-inline`
or `:html-classes` to use HTML `span` elements for color markup:

- `:html-inline` uses inline styles to apply style attributes directly to
each `span`'s content based on the `:color-scheme`;
- `:html-classes` sets the `class` of each `span` based on its syntax element
type (e.g., "delimiter", "keyword", "number") to allow the style for its
content be specified elsewhere via CSS.
or `:html-classes` to use HTML `span` elements for color markup. Finally, the
`:color-scheme` map controls how various elements are highlighted.

## Canonical Representation

Expand All @@ -53,83 +70,74 @@ short, if two data values are equal, they should be printed identically. This is
important for data deduplication and in situations where the printed data is
hashed.

Towards this end, Puget defines a _total ordering_ on Clojure values, meaning
that it provides a comparator that can provide an ordering for any two values,
even if they have different types. This ordering is used to sort the values in
sets and the keys in maps so that they are always printed the same way.
By default, Puget uses the
[arrangement](https://github.com/greglook/clj-arrangement) library to sort the
values in sets and the keys in maps so they are always printed the same way.
This can be disabled with the `:sort-mode` option, or enabled only for
collections under a certain size.

By default, values with types which have no canonical representation defined
will be printed in the same style as Clojure's pretty-print. In strict mode,
Puget will throw an exception for these values instead.
Most printing is done with the `puget.printer.PrettyPrinter` class, but the
library also offers the `CanonicalPrinter` for serializing data in a stricter
(and more compact) fashion.

```clojure
(require '[puget.printer :as puget])
=> (require '[puget.printer :as puget])

(def usd (java.util.Currency/getInstance "USD"))
=> (puget/pprint #{'x :a :z 3 1.0})
#{1.0 3 :a :z x}

(puget/pprint usd)
;; #<java.util.Currency@4cc4ee24 USD>
=> (def usd (java.util.Currency/getInstance "USD"))
#'user/usd

(puget/pprint usd {:strict true})
;; IllegalArgumentException: No canonical representation for class java.util.Currency: USD
```
=> (puget/pprint usd)
#<java.util.Currency@4cc4ee24 USD>

Whether or not the entries in collections are sorted can be controlled with the
`:sort-keys` option.
=> (puget/render-out (puget/canonical-printer) usd)
; IllegalArgumentException: No defined representation for class java.util.Currency: USD
```

## EDN Tagged Values
## Type Extensions

All of Clojure's primitive types are given their standard canonical print
representations. To handle non-standard data types, EDN specifies _tags_ which
can alter how the reader interprets the following value. Accordingly, Puget
provides a `TaggedValue` protocol in the `puget.data` namespace. This lets novel
datatypes provide a 'canonical' representation of themselves as a tag symbol
followed by some interpretation of the value.
representations. To handle non-standard data types, Puget supports a mechanism
to dispatch to custom _print handlers_. These take precedence over the standard
rendering mechanisms.

This can be used to provide an EDN tagged-literal representation for certain
types, or just avoid trying to pretty-print types which the engine struggles
with (such as attempting to render a Datomic database).

Puget extends this protocol to support the `#inst` and `#uuid` built-ins from
the EDN standard. In addition, it supports `#puget/bin` for base64-encoded binary
data, and `#puget/uri` for specifying Uniform Resource Identifiers.
The `puget.dispatch` namespace has functions to help build handler lookup
functions; most commonly, a chained inheritance-based lookup provides semantics
similar to Clojure's multimethod dispatch.

To give your own types a tag extension, use the `extend-tagged-*` functions. For
example, to extend `#inst` tagging to Joda `DateTime` objects:
As an example, extending `#inst` formatting to clj-time's `DateTime`:

```clojure
(require '(clj-time [core :as t] [format :as f]))
=> (require '[clj-time.core :as t]
'[clj-time.format :as f])

(t/now)
=> (puget/pprint (t/now))
#<org.joda.time.DateTime 2014-05-14T00:58:40.922Z>

(require 'puget.data)

(puget.data/extend-tagged-value
org.joda.time.DateTime 'inst
(partial f/unparse (f/formatters :date-time)))
=> (def time-handlers
{org.joda.time.DateTime
(puget/tagged-handler
'inst
(partial f/unparse (f/formatters :date-time)))}})
#'user/time-handlers

(t/now)
=> (puget/pprint (t/now) {:print-handlers time-handlers})
#inst "2014-05-14T01:05:53.885Z"
```

## Further Customization

Puget's printing is controlled by a map of options which include print width,
the color scheme, whether to be strict about value representations, whether to
print metadata, etc. The default options are held in the dynamic var
`puget.printer/*options*`. This can be bound with the `with-options` macro for
convenience, or a map can be passed directly into Puget's print functions to
override the defaults.

Puget's colors are defined by the `:color-scheme` key, which maps syntax element
keywords to a vector of ANSI style keywords to apply. Some example elements and
their default colors:

```clojure
:boolean [:green]
:delimiter [:bold :red]
:keyword [:bold :yellow]
:number [:cyan]
:string [:bold :magenta]
:symbol nil
```
If no handler is specified for a given type and it's not a built-in EDN type,
Puget refers to the `:print-fallback` option. The default `:pretty` prints a
colored representation of the unknown value (note this is not valid EDN!),
while `:print` will fall back to the standard `pr-str`. Alternately, `:error`
will throw an exception for types with no defined representation. Finally, a
function may be provided which will be passed the current printer and the
unknown value to render.

## License

Expand Down
11 changes: 7 additions & 4 deletions project.clj
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
(defproject mvxcvi/puget "0.8.1"
(defproject mvxcvi/puget "0.9.0"
: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"]

:plugins [[lein-cloverage "1.0.2"]]
:plugins
[[lein-cloverage "1.0.6"]]

:dependencies [[org.clojure/clojure "1.6.0"]
[fipp "0.5.2"]]
:dependencies
[[fipp "0.6.2"]
[mvxcvi/arrangement "1.0.0"]
[org.clojure/clojure "1.7.0"]]

:cljfmt {:indents {with-options [[:block 1]]}}

Expand Down
26 changes: 21 additions & 5 deletions src/puget/color.clj
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
(ns puget.color
"This namespace defines multimethods to add color markup to text.")
"Coloring multimethods to format text by adding markup.
#### Color Options
`:print-color`
When true, ouptut colored text from print functions.
`:color-markup`
- `:ansi` for color terminal text (default)
- `:html-inline` for inline-styled html
- `:html-classes` for html with semantic classes
`:color-scheme`
Map of syntax element keywords to color codes.
")

;; ## Coloring Multimethods

(defn dispatch
"Dispatches to coloring multimethods. Element should be a key from
the color-scheme map."
[element text options]
[options element text]
(when (:print-color options)
(:color-markup options)))

Expand All @@ -31,10 +48,9 @@
;; text unaltered.

(defmethod document nil
[element text options]
[options element text]
text)


(defmethod text nil
[element text options]
[options element text]
text)
9 changes: 6 additions & 3 deletions src/puget/color/ansi.clj
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
(ns puget.color.ansi
"This namespace defines functions to apply ANSI color codes to text."
"Coloring implementation that applies ANSI color codes to text designed to be
output to a terminal.
Use with a `:color-markup` of `:ansi`."
(:require
[clojure.string :as str]
[puget.color :as color]))
Expand Down Expand Up @@ -65,14 +68,14 @@


(defmethod color/document :ansi
[element text options]
[options element text]
(if-let [codes (-> options :color-scheme (get element) seq)]
[:span [:pass (esc codes)] text [:pass (escape :none)]]
text))


(defmethod color/text :ansi
[element text options]
[options element text]
(if-let [codes (-> options :color-scheme (get element) seq)]
(str (esc codes) text (escape :none))
text))
16 changes: 10 additions & 6 deletions src/puget/color/html.clj
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
(ns puget.color.html
"This namespace defines methods for the `:html-inline` and `:html-classes`
otptions for `:color-markup`."
"Coloring implementation that wraps text in HTML tags to apply color.
Supports the following modes for `:color-markup`:
- `:html-inline` applies inline `style` attributes to the tags.
- `:html-classes` adds semantic `class` attributes to the tags."
(:require
[clojure.string :as str]
[puget.color :as color]))
Expand Down Expand Up @@ -73,7 +77,7 @@


(defmethod color/document :html-inline
[element text options]
[options element text]
(if-let [codes (-> options :color-scheme (get element) seq)]
[:span [:pass "<span " (style codes) ">"]
(escape-html-document text)
Expand All @@ -82,19 +86,19 @@


(defmethod color/text :html-inline
[element text options]
[options element text]
(if-let [codes (-> options :color-scheme (get element) seq)]
(str "<span " (style codes) ">" (escape-html-text text) "</span>")
(escape-html-text text)))


(defmethod color/document :html-classes
[element text options]
[options element text]
[:span [:pass "<span class=\"" (name element) "\">"]
(escape-html-document text)
[:pass "</span>"]])


(defmethod color/text :html-classes
[element text options]
[options element text]
(str "<span class=\"" (name element) "\">" (escape-html-text text) "</span>"))
Loading

0 comments on commit a008fb0

Please sign in to comment.