{"id":13591362,"url":"https://github.com/clj-commons/pretty","last_synced_at":"2026-06-23T14:00:50.122Z","repository":{"id":46694679,"uuid":"13689238","full_name":"clj-commons/pretty","owner":"clj-commons","description":"Library for helping print things prettily, in Clojure - ANSI fonts, formatted exceptions","archived":false,"fork":false,"pushed_at":"2026-04-27T19:33:40.000Z","size":4166,"stargazers_count":621,"open_issues_count":2,"forks_count":29,"subscribers_count":16,"default_branch":"main","last_synced_at":"2026-05-29T01:03:22.432Z","etag":null,"topics":["ansi-colors","clojure","feedback"],"latest_commit_sha":null,"homepage":"https://cljdoc.org/d/org.clj-commons/pretty","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/clj-commons.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":null,"license":"LICENSE-asl.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2013-10-18T20:53:32.000Z","updated_at":"2026-04-27T19:33:41.000Z","dependencies_parsed_at":"2024-03-27T20:48:38.442Z","dependency_job_id":"c408521e-817f-4c3d-9ceb-2f9243d6b282","html_url":"https://github.com/clj-commons/pretty","commit_stats":null,"previous_names":["clj-commons/pretty","avisonovate/pretty"],"tags_count":85,"template":false,"template_full_name":null,"purl":"pkg:github/clj-commons/pretty","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clj-commons%2Fpretty","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clj-commons%2Fpretty/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clj-commons%2Fpretty/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clj-commons%2Fpretty/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/clj-commons","download_url":"https://codeload.github.com/clj-commons/pretty/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clj-commons%2Fpretty/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34692781,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-23T02:00:07.161Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ansi-colors","clojure","feedback"],"created_at":"2024-08-01T16:00:56.612Z","updated_at":"2026-06-23T14:00:50.116Z","avatar_url":"https://github.com/clj-commons.png","language":"Clojure","funding_links":[],"categories":["Clojure"],"sub_categories":[],"readme":"[![Clojars](https://img.shields.io/clojars/v/org.clj-commons/pretty.svg)](http://clojars.org/org.clj-commons/pretty)\n[![CI](https://github.com/clj-commons/pretty/actions/workflows/clojure.yml/badge.svg)](https://github.com/clj-commons/pretty/actions/workflows/clojure.yml)\n[![cljdoc badge](https://cljdoc.org/badge/org.clj-commons/pretty)](https://cljdoc.org/d/org.clj-commons/pretty/)\n\n*Sometimes, neatness counts*\n\nIf you are trying to puzzle out a stack trace, \npick a critical line of text out of a long stream of console output,\nor compare two streams of binary data, a little bit of formatting can go a long way.\n\nThat's what `org.clj-commons/pretty` is for.  It adds support for pretty output where it counts:\n\n* Readable output for exceptions\n* General ANSI font and background color support\n* Readable output for binary sequences\n\n![Example](docs/images/formatted-exception.png)\n\n\nOr, compare an example from\n[Pedestal](http://github.com/pedestal/pedestal)'s test suite:\n\n![No Pretty](docs/images/pedestal-without-pretty.png)\n\nOr, same thing, but with Pretty enabled:\n\n![With Pretty](docs/images/pedestal-with-pretty.png)\n\nThe 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.\n\nPretty can even identify the parts of your stack traces that repeat (so common with Clojure code), and\nomit the repetition:\n\n![Repeats](docs/images/exception-repeat.png)\n\n### Enabling Pretty\n\nPretty exceptions are enabled by invoking the function `clj-commons.pretty.repl/install-pretty-exceptions`.  This\nredefines a number of Vars to replace the default implementations with prettier ones.  This is something you could\nset up in your `user.clj` namespace.\n\n### Pretty with Leiningen\n\nIn shared projects, many people have different ideas about what's best when it comes to error reporting.\nIf you want to be able to use Pretty but have your project's dependencies be \"clean\", you can use \na [Leiningen](https://leiningen.org/) profile for this purpose.\n\nFor example, create a file `~/.lein/profiles.d/debug.clj`:\n\n```clojure\n{:dependencies\n [[org.clj-commons/pretty \"3.5.0\"]]\n :injections\n [(require '[clj-commons.pretty.repl :as repl])\n  (repl/install-pretty-exceptions)]}\n```\nYou can then run your REPL as `lein with-profiles +debug` and have your pretty\nexceptions without adding pretty-specific code or dependencies to your project.\n\nTIP: I also set up other tools I depend on, such as \n[clj-reload](https://github.com/tonsky/clj-reload), in the same profile.\n\n### Pretty with clj\n\n```clojure\n{:aliases\n { :debug\n  {:extra-deps {org.clj-commons/pretty {:mvn/version \"3.5.0\"}}\n   :main-opts [\"--main\" \"clj-commons.pretty-repl\"]}}}\n```\nExecuting `clj -M:debug` will execute the function `clj-commons.pretty-repl/-main` which will set up\npretty exceptions before passing any remaining command line argments to `clojure.main/main`.\n\nAlternately, for use with the -X option:\n\n```clojure\n{:aliases\n {:debug\n  {:extra-deps {org.clj-commons/pretty {:mvn/version \"3.5.0\"}}\n   :exec-fn clj-commons.pretty.repl/main}\n  \n  :test\n  {:extra-paths [\"test\"]\n   :extra-deps {io.github.cognitect-labs/test-runner\n                {:git/tag \"v0.5.1\" :git/sha \"dfb30dd\"}}\n   :exec-fn cognitect.test-runner.api/test\n   :exec-args {:fn cognitect.test-runner.api/test}}}}\n```\n\nThis allows testing with pretty as `clj -X:test:debug`.\n\n`clj -X:test` is normal execution, and the `clj` tool will directly invoke the `cognitect.test-runner.api/test` function.\n`clj -X:test:debug` will overwrite the :exec-fn to invoke the `clj-commons.pretty.repl/main` function, which will\nset up pretty exceptions before delegating to the function specified with the :fn option.\n\nThe value for :fn must be a fully qualified function name.\n\nBoth of these approaches are doable but clumsy, so a solution involving nREPL directly will likely be better.\n\n\n### Pretty with nREPL\n\n[nREPL](https://nrepl.org) is the framework that allows an IDE such as [Emacs](https://cider.mx/) \nor [Cursive](https://cursive-ide.com/), or even a CLI such as\nLeiningen, to interoperate with a running REPL in a subprocess.\n\nPretty includes an nREPL middleware function, `clj-commons.pretty.nrepl/wrap-pretty`, that will install pretty exception reporting into the REPL.  \n\nThe nREPL documentation describes how to enable such middleware\ninside [project.clj or deps.edn](https://nrepl.org/nrepl/usage/server.html#starting-a-server) or\nin [.nrepl/nrepl.edn](https://nrepl.org/nrepl/usage/server.html#server-configuration) (for instance, when developing\nwith [Cursive](https://cursive-ide.com/userguide/repl.html#configuring-middleware-for-nrepl-repls))\n\n## Beyond Exceptions\n\nPretty can print out a sequence of bytes; it includes color-coding inspired by\n[hexyl](https://github.com/sharkdp/hexyl):\n\n![Binary Output](docs/images/binary-output.png)\n\nPretty can also print out a delta of two byte sequences, using background color\nto indicate where the two sequences differ.\n\n![Binary Delta](docs/images/binary-delta.png)\n\nPretty can output pretty tabular data:\n\n```\n(def routes\n  [{:method     :get\n    :path       \"/\"\n    :route-name :root-page}\n   {:method     :post\n    :path       \"/reset\"\n    :route-name :reset}\n   {:method     :get\n    :path       \"/status\"\n    :route-name :status}])\n    \n(print-table\n  [:method\n   :path\n   {:key :route-name :title \"Name\" :title-align :left}]\n  routes)\n\n```\n\n![Table Output](docs/images/default-table.png)\n\nThe `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:\n\n```\n(print-table\n    {:columns [:method\n               :path\n               {:key :route-name :title \"Name\" :title-align :left}]\n     :style   table/skinny-style}\n    routes)\nMethod |   Path  | Name      \n-------+---------+-----------\n  :get |       / | :root-page\n :post |  /reset | :reset    \n  :get | /status | :status   \n=\u003e nil\n```\n\nPretty can also format text with annotations, useful when reporting errors while\nparsing arbitrary text:\n\n![Annotations](docs/images/annotations.png)\n\n## Compatibility\n\nPretty is compatible with Clojure 1.10 and above.\n\nParts of Pretty can be used with [Babashka](https://book.babashka.org/#introduction), such as the `clj-commons.ansi`\nnamespace; however, Babashka runs in an interpreter and its approach to exceptions is\nincompatible with JVM exceptions.\n\n## License\n\nThe majority of this code is available under the terms of the Apache Software License 1.0; some portions\nare available under the terms of the Eclipse Public Licence 1.0.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclj-commons%2Fpretty","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclj-commons%2Fpretty","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclj-commons%2Fpretty/lists"}