zprint icon indicating copy to clipboard operation
zprint copied to clipboard

Executables, uberjar, and library to beautifully format Clojure and Clojurescript source code and s-expressions.

zprint

zprint is a library and command line tool providing a variety of pretty printing capabilities for both Clojure code and Clojure/EDN structures. It can meet almost anyone's needs. As such, it supports a number of major source code formattng approaches.

cljdoc badge

Recent Additions!

  • You can alias function formatting in the :fn-map. If the value in the :fn-map is a string, then the formatting for that function is used. This makes having one function format like another much easier to configure.
  • Hiccup or HTML output now available! Library -str fns and prebuilt binaries support {:output {:format :hiccup}} and {:output {:format :html}}. EXPERIMENTAL for now -- as always, please let me know of any issues.
  • The library is now thread-safe (only if you format all strings or all structures. You can't intermix them simultaneously.)
  • Tests now also run in babaska (thanks to @borkdude)
  • Tested with Clojure 1.11.1, Clojurescript 1.11.4
  • Implemented {:output {:range? true}} to ease integration with IDE's.
  • New version of rewrite-clj now used for both .clj and .cljs. Many thanks to @lread for picking up support and extensions for rewrite-clj and merging rewrite-cljs with it to create a unified Clojure parsing library. This will fix a number of bugs that were parser related.
  • You can now format values in maps differently, based on the key with which a value is associated. {:map {:key-value-options {key-1 options-map-1 key-2 options-map-2 ...}} lets you specify an options map to be used for formatting the value of any specific key in any map.
  • A number of new styles: :ns-justify, which will nicely format ns macros. :quote-wrap which will cause a quoted list to wrap, and not format each item running down the page, to mention a few.
  • A more nuanced approach to justification, based on the variance of the lengths of the left-hand elements in a binding vector, map, or cond. If the variance is too great, up to two pairs are left out of the justification. If that doesn't bring the variance into line, none of the pairs are justified. {:style :justified} to try it out!
  • The are macro is now formatted readably by default.
  • In-place formatting by file name, $ zprint -w file.clj and $ zprint -w *.clj
  • Check formatting of files without altering them, using -c or --check: $ zprint -c *.clj.
  • Functions in options maps now safely supported in all .zprintrc files using any distributed binaries, using sci.
  • You can now define a style and use it in the same .zprintrc. You can also define one style in terms of another.
  • Output colorized, formatted source to terminal: $ zprint '{:color? true}' <file.clj
  • Format babashka scripts
  • Format ranges of lines in files
  • {:style :dark-color-map} when using dark terminals
  • All changes

See zprint:

  • classic zprint -- ignores whitespace in function definitions and formats code with a variety of heuristics to look as good as hand-formatted code (see examples)
  • respect blank lines -- similar to classic zprint, but blank lines inside of function defintions are retained, while code is otherwise formatted to look beautiful (see examples)
  • indent only -- very different from classic zprint -- no code ever changes lines, it is only correctly indented on whatever line it was already on (see examples)

In addition, zprint is very handy to use at the REPL.

Use zprint:

  • to format whole files
  • while using an editor
  • at the REPL
  • with a team
  • with different formatting for different projects
  • to format a range of lines in a file
  • to format a babashka script
  • to correct indentation but not otherwise reformat a file
  • and have it run even faster
  • from inside a Clojure(script) program

Get zprint:

  • a standalone binary for macOS starts in <50 ms
  • a standalone binary for Linux starts in <50 ms
  • a VS Code extension for zprint
  • an uberjar for any Java enabled platform starts in several seconds
  • an accelerated uberjar for any Java enabled platform starts in about 1s
  • a library to use at the REPL
  • other ways to access zprint

Get something other than the default formatting:

Without learning how to configure zprint:

Maybe one of the existing "styles" will meet your needs. All you have to do is put {:style ...} on the command line or as the third argument to a zprint call. For example, {:style :community} or {:style :respect-bl}.

Some commonly used styles:

  • Format using "community" standards
  • Respect blank lines
  • Indent Only
  • Respect all newlines
  • Detect and format hiccup vectors
  • Justify all pairs
  • Backtranslate quote, deref, var, unquote in structures
  • Detect keywords in vectors, if found respect newlines
  • Sort dependencies in project.clj
  • Support "How to ns"

Learn how to alter zprint's formatting behavior:

  • How do I change zprint's behavior?

I want to change...

  • how user defined functions are formatted
  • the indentation in lists
  • the configuration to track the "community" standard
  • how blank lines in source are handled
  • how map keys are formatted
  • the colors used for formatting source
  • how the second element of a pair is indented
  • how comments are handled
  • how blank lines are handled at the top level
  • how vectors are formatted based on their content
  • how constants are defined when formatting constant pairs
  • the options map by defining functions to format based on content
  • anything else...

Usage

cljdoc badge

Clojure 1.9, 1.10, 1.10.3, 1.11.1:

Leiningen (via Clojars)

Clojars Project

Clojurescript:

zprint has been tested in each of the following environments:

  • figwheel-main 0.2.16 (Clojurescript 1.11.4)
  • shadow-cljs 2.18.0
  • planck 2.26.0 (Clojurescript 1.10.914)

It requires tools.reader at least 1.0.5, which all of the environments above contain.

Clojure 1.8:

The last zprint release built with Clojure 1.8 was [zprint "0.4.15"].

In addition to the zprint dependency, you also need to include the following library when using Clojure 1.8:

[clojure-future-spec "1.9.0-alpha17"]

The zprint Reference

  • Entire reference document
  • What does zprint do?
  • Features
  • The zprint API
  • Configuration
    • Configuration uses an options map
    • Where to put an options map
    • Simplified Configuration -- using :style
      • Respect blank lines
      • Indent Only
      • Format using "community" standards
      • Respect all newlines
      • Detect and format hiccup vectors
      • Justify all pairs
      • Backtranslate quote, deref, var, unquote in structures
      • Detect keywords in vectors, if found respect newlines
      • Sort dependencies in project.clj
      • Support "How to ns"
      • Add newlines between pairs in let binding vectors
      • Add newlines between cond, assoc pairs
      • Add newlines between extend clauses
      • Add newlines between map pairs
      • Prefer hangs and improve performance for deeply nested code and data
    • Options map format
      • Option Validation
      • What is Configurable
    • Generalized Capabilities
    • Syntax Coloring
    • Function Classification for Pretty Printing
      • Changing or Adding Function Classifications
      • Replacing functions with reader-macros
      • Controlling single and multi-line output
      • A note about two-up printing
      • A note on justifying two-up printing
    • Formatting large or deep collections
    • Widely Used Configuration Parameters
    • Configurable Elements
      • :agent
      • :array
      • :atom
      • :binding
      • :comment
      • :delay
      • :extend
      • :fn
      • :future
      • :list
      • :map
      • :object
      • :pair
      • :pair-fn
      • :promise
      • :reader-cond
      • :record
      • :set
      • :spec
      • :style
      • :style-map
      • :tab
      • :vector
      • :vector-fn

Testing and Development

Information on testing and development can be found here.

Contributors

A number of folks have contributed to zprint, not all of whom show up on GitHub because I have integrated the code or suggestions manually. Thanks for all of the great contributions!

  • Tests running in babashka: @borkdude
  • Additional colors and color-map entries: @RingMan
  • Updated rewrite-cljs dependency to 0.4.5 @rundis/
  • Readme updates: @mathiasn, @Quezion, @vemv, @arichiardi, @bhurlow, @kommen.
  • --url and --url-only: @coltnz
  • Use UTF-8 locale to build the native image: @mynomoto
  • Suggestion/encouragement to implement :respect-bl: @griffis
  • Thread safety suggestions: @fazzone
  • :option-fn and :fn-format for enhanced vector formatting: @milankinen
  • Fixed missing require in spec.cljc: @Quezion
  • Corrected readme: @griffis
  • Fixed nested reader conditional: @rgould1
  • Clarified and added useful example for clj usage: @bherrmann7
  • Sublime text plugin instructions: @ekinnear
  • Use body indentation for the ns macro: @pesterhazy
  • Suggested fix for international chars and graalVM native image: @huahaiy

Thanks to everyone who has contributed fixes as well as everyone who has reported an issue. I really appreciate all of the help making zprint better for everybody!

Acknowledgements

At the core of zprint is the rewrite-clj library originally created by Yannick Scherer, ported to Clojurescript by Magnus Rundberget, and recently merged into a single, supported, documented, and updated library by Lee Read. This is a great library! I would not have attempted zprint if rewrite-clj didn't exist to build upon.

Additionally, allowing options maps containing functions to be read from files safely is made possible by sci, the Small Clojure Interpreter by Michael Borkent (@borkdude). This is a very well designed and implemented addition to Clojure that required almost no effort to integrate into zprint.

License

Copyright © 2016-2022 Kim Kinnear

Distributed under the MIT License. See the file LICENSE for details.