zprint
Introduction
Writing code should be about expression your intent more than painstakingly aligning and wrapping a stream of characters. Some languages get this right out of the box, and some have extensive tooling maintained by generous entities.
In the case of Clojure there are four options that I am aware of:
- Do it yourself by bashing tirelessly away on your keyboard;
- cljfmt;
- cljstyle;
- zprint.
For reasons I’m not going to go into I’m using zprint and provide the configuration necessary to format things just the way I like.
Configuration
The reference documentation contains a lot of information. Of particular interest to me is the :fn-map
and its names.
:arg1->
:arg1-body
:arg1-extend
:arg1-force-nl
:arg1-mixin
:arg1-pair-body
:arg1-pair
:arg1
:arg2-fn
:arg2-pair
:arg2
:binding
:extend
:flow-body
:flow
:fn
:force-nl-body
:force-nl
:gt2-force-nl
:gt3-force-nl
:hang
:noarg1-body
:none-body
:none
:pair-fn
$HOME/.zprint.edn
{:search-config? true :width 80}
$PWD/.zprint.edn
{:extend {:flow? true :indent 0 :nl-separator? true} :fn-map {"are" [:none {:list {:indent-only? true} :next-inner {:list {:indent-only? false}}}] "s/cat" [:binding {:binding {:force-nl? false}}] "s/fdef" :arg1-force-nl "testing" :arg1-force-nl "try" :flow} :map {:comma? false :sort-in-code? true :sort? true} :set {:sort-in-code? true :sort? true} :style [:binding-nl :extend-nl :hiccup :how-to-ns :justified :map-nl :pair-nl] :width 80}
Test
Explain
zprint --help
Some Clojure
(ns fmt (:require [com.stuartsierra.component :as component] [clojure.string :as str] [clojure.spec.alpha :as s] [clojure.test :refer [are deftest is testing]])) (defprotocol IPretty (pretty [this])) (defn- init-state [_app] {:zprint/cool? true}) (defrecord App [db] component/Lifecycle (start [this] (if (some? db) this (let [state (init-state this)] ;; Some side effects would typically take place now. (assoc this :db (atom (assoc state ::fmt "please")))))) (stop [this] (dissoc this :db)) IPretty (pretty [this] true)) (s/fdef string->string :args (s/cat :string string?) :ret string?) (defn string->string [string] (cond-> string (str/ends-with? string "bar") (subs 0 (rand-int (dec (count string)))))) (deftest string->string-works (is (= #{"a" "b" "c"} #{"a" "b" "c"})) (testing "who knows what" (is (= {} (string->string "okay")))) (are [in out] (= out (string->string in)) "foo" "foo" "foobar" "tests don't like rand-int"))