pretty is a free, open source collaboration & feedback project written in Clojure and released under Apache-2.0. It has 624 GitHub stars, 29 forks and 3 open issues, and was last pushed 11 days ago. On this registry it ranks #14 of 20 tracked projects in Collaboration & Feedback, with 5 head-to-head comparisons available. It gained 1 stars over the last 3 tracked days.

What is pretty?

pretty is an Apache-2.0 Clojure library, published on Clojars as org.clj-commons/pretty, that formats exception output, ANSI fonts and binary data so developers can read console and REPL output more easily.

What it is

It installs as an ordinary Clojars dependency maintained under the clj-commons organisation, and it is deliberately narrow in scope: readable output for exceptions, general ANSI font and background colour support, and readable output for binary sequences. It is a library rather than a service, so there is no server to run and no data store to configure.

The problem it solves is the wall of text a Clojure developer meets when a stack trace appears. Long, repetitious stack traces are common in Clojure, and the default output buries file names and line numbers and prints names that do not match the source being read. Pretty replaces the default implementations with prettier ones: important parts are highlighted, unnecessary details are omitted, names stay closer to the source, and repeated sections are detected and dropped. The README shows this with a Pedestal test suite example, with and without Pretty enabled.

Key capabilities

  • Pretty exceptions install through clj-commons.pretty.repl/install-pretty-exceptions, which redefines a number of Vars to replace the default implementations.
  • General ANSI font and background colour support, matching the ansi-colors topic.
  • Readable output for binary sequences, useful when comparing two streams of binary data.
  • Detection and omission of repeated stack trace sections.
  • Highlighting of essential trace details such as file names and line numbers, with unnecessary details left out.
  • Command-line entry points clj-commons.pretty-repl/-main and clj-commons.pretty.repl/main, which set up pretty exceptions before passing remaining arguments to clojure.main/main.

Who uses it and how

  • Clojure developers debugging in a REPL or terminal who want to scan output in chronological order and pick out the essential lines.
  • Teams whose members disagree about error reporting: a per-developer Leiningen profile at ~/.lein/profiles.d/debug.clj adds the dependency and injection without adding pretty-specific code or dependencies to the shared project, run as lein with-profiles +debug.
  • Tools.deps users, who add a :debug alias with :extra-deps {org.clj-commons/pretty {:mvn/version "3.5.0"}} and run clj -M:debug, or use :exec-fn clj-commons.pretty.repl/main.
  • Test workflows, where clj -X:test:debug overwrites the :exec-fn so pretty exceptions are installed before delegating to the function named by :fn.
  • IDE workflows over nREPL, such as Emacs with CIDER or Cursive, which the README says is likely a better route than the alias and profile approaches it calls clumsy.

Getting started

Add org.clj-commons/pretty version 3.5.0 from Clojars and call clj-commons.pretty.repl/install-pretty-exceptions, from a user.clj namespace, a Leiningen profile, or a deps.edn alias. Documentation lives at cljdoc: https://cljdoc.org/d/org.clj-commons/pretty.

How it compares

The facts name no paid products that this library replaces, and no directly comparable formatting library either, so it stands alone in this registry. The contrast the README draws is against Clojure's default exception output, showing the same Pedestal test output with and without Pretty, and the library sits alongside REPL tooling such as nREPL, CIDER and Cursive rather than competing with it.

When to use it — and when not to

Nothing needs to be operated, since there is no database, storage layer or SMTP involved; the library only changes how output is printed. The catch is that install-pretty-exceptions redefines Vars and so changes exception reporting for the whole session, which is why the README isolates the dependency in a personal profile for shared projects. It is a poor fit for anyone who does not work in a Clojure REPL or console, and the README excerpt available here is cut off mid-sentence in its nREPL section, so that integration is not fully documented in these facts.

project readme (upstream, from github) — read inline

Clojars CI cljdoc badge

Sometimes, neatness counts

If you are trying to puzzle out a stack trace, pick a critical line of text out of a long stream of console output, or compare two streams of binary data, a little bit of formatting can go a long way.

That's what org.clj-commons/pretty is for. It adds support for pretty output where it counts:

  • Readable output for exceptions
  • General ANSI font and background color support
  • Readable output for binary sequences

Example

Or, compare an example from Pedestal's test suite:

No Pretty

Or, same thing, but with Pretty enabled:

With Pretty

The point is, you can scan down to see things in chronological order; the important parts are highlighted, the names are the same (or closer) to your source code, unnecessary details are omitted, and it's much easier to pick out other essential parts easily, such as file names and line numbers.

Pretty can even identify the parts of your stack traces that repeat (so common with Clojure code), and omit the repetition:

Repeats

Enabling Pretty

Pretty exceptions are enabled by invoking the function clj-commons.pretty.repl/install-pretty-exceptions. This redefines a number of Vars to replace the default implementations with prettier ones. This is something you could set up in your user.clj namespace.

Pretty with Leiningen

In shared projects, many people have different ideas about what's best when it comes to error reporting. If you want to be able to use Pretty but have your project's dependencies be "clean", you can use a Leiningen profile for this purpose.

For example, create a file ~/.lein/profiles.d/debug.clj:

{:dependencies
 [[org.clj-commons/pretty "3.5.0"]]
 :injections
 [(require '[clj-commons.pretty.repl :as repl])
  (repl/install-pretty-exceptions)]}

You can then run your REPL as lein with-profiles +debug and have your pretty exceptions without adding pretty-specific code or dependencies to your project.

TIP: I also set up other tools I depend on, such as clj-reload, in the same profile.

Pretty with clj

{:aliases
 { :debug
  {:extra-deps {org.clj-commons/pretty {:mvn/version "3.5.0"}}
   :main-opts ["--main" "clj-commons.pretty-repl"]}}}

Executing clj -M:debug will execute the function clj-commons.pretty-repl/-main which will set up pretty exceptions before passing any remaining command line argments to clojure.main/main.

Alternately, for use with the -X option:

{:aliases
 {:debug
  {:extra-deps {org.clj-commons/pretty {:mvn/version "3.5.0"}}
   :exec-fn clj-commons.pretty.repl/main}
  
  :test
  {:extra-paths ["test"]
   :extra-deps {io.github.cognitect-labs/test-runner
                {:git/tag "v0.5.1" :git/sha "dfb30dd"}}
   :exec-fn cognitect.test-runner.api/test
   :exec-args {:fn cognitect.test-runner.api/test}}}}

This allows testing with pretty as clj -X:test:debug.

clj -X:test is normal execution, and the clj tool will directly invoke the cognitect.test-runner.api/test function. clj -X:test:debug will overwrite the :exec-fn to invoke the clj-commons.pretty.repl/main function, which will set up pretty exceptions before delegating to the function specified with the :fn option.

The value for :fn must be a fully qualified function name.

Both of these approaches are doable but clumsy, so a solution involving nREPL directly will likely be better.

Pretty with nREPL

nREPL is the framework that allows an IDE such as Emacs or Cursive, or even a CLI such as Leiningen, to interoperate with a running REPL in a subprocess.

Pretty includes an nREPL middleware function, clj-commons.pretty.nrepl/wrap-pretty, that will install pretty exception reporting into the REPL.

The nREPL documentation describes how to enable such middleware inside project.clj or deps.edn or in .nrepl/nrepl.edn (for instance, when developing with Cursive)

Beyond Exceptions

Pretty can print out a sequence of bytes; it includes color-coding inspired by hexyl:

Binary Output

Pretty can also print out a delta of two byte sequences, using background color to indicate where the two sequences differ.

Binary Delta

Pretty can output pretty tabular data:

(def routes
  [{:method     :get
    :path       "/"
    :route-name :root-page}
   {:method     :post
    :path       "/reset"
    :route-name :reset}
   {:method     :get
    :path       "/status"
    :route-name :status}])
    
(print-table
  [:method
   :path
   {:key :route-name :title "Name" :title-align :left}]
  routes)

Table Output

The print-table function has many options to easily adjust the output to your needs, including fonts, text alignment, and line annotations. It also supplies several different table styles:

(print-table
    {:columns [:method
               :path
               {:key :route-name :title "Name" :title-align :left}]
     :style   table/skinny-style}
    routes)
Method |   Path  | Name      
-------+---------+-----------
  :get |       / | :root-page
 :post |  /reset | :reset    
  :get | /status | :status   
=> nil

Pretty can also format text with annotations, useful when reporting errors while parsing arbitrary text:

Annotations

Compatibility

Pretty is compatible with Clojure 1.10 and above.

Parts of Pretty can be used with Babashka, such as the clj-commons.ansi namespace; however, Babashka runs in an interpreter and its approach to exceptions is incompatible with JVM exceptions.

License

The majority of this code is available under the terms of the Apache Software License 1.0; some portions are available under the terms of the Eclipse Public Licence 1.0.

Frequently asked questions

Is pretty free to use?

pretty is open source under the Apache-2.0 licence. There is no licence fee and no seat count — you can self-host it or, where the project offers one, pay a vendor for a managed version instead.

What does pretty do?

Library for helping print things prettily, in Clojure - ANSI fonts, formatted exceptions

What is pretty written in?

pretty is primarily written in Clojure. Its source is publicly available at https://github.com/clj-commons/pretty, and it has 624 GitHub stars.