1. High Performance Prebuilt Binaries
2. Java Uberjar
3. Clojure CLI
4. Lein zprint
5. zprint-clj (node based)
Changing the formatting approach using comments in the file
There are several ways to use zprint to format entire source files.
- High performance: startup is fast < 50ms
- Available for macOS and Linux
- Does not require Java -- available as standalone binaries
- Accepts source on stdin, produces formatted source on stdout
- Will also format or check format on named files "in place"
- Reads configuration from
~/.zprintrc
- Accepts options map on command line
zprintm '{:width 90}` < myfile.clj > myfile.out.clj
will read myfile.clj, format the source for a width of 90 characters (the default is 80), and write the result back into myfile.out.clj.
Alternatively:
zprintm '{:width 90}' -w myfile.clj
will read myfile.clj, format the source for a width of 90 characters (the default is 80), and write the result back into myfile.clj if it is different than the source.
You can also format all of the clojure files in a directory with:
zprint -w *.clj
This will format each of the .clj
files, and if there are any errors,
it will report the error for that file, and continue on processing
the rest of the files. If there are errors formatting any file, the
contents of that file remain unchanged. The exit status is contains
the number of files with errors.
Similarly, you can check the formatting on any files with the -c
switch:
zprint -c *.clj
will check the formatting on all of the files with a .clj
extension
in the current directory. The exit status will be the number of files
which require formatting.
For both the -w
and -c
switches (which "write" and "check" the
specified files, respectively), there are additional options that
can be specified to produce explanatory output. These options
must be combined with the -w
or -c
switches to be recognized.
They are (shown combined with the -w
switch here, but they also
work with -c
):
-lw
List the files being processed before they are opened-fw
report on all files that needed to be Formatted-sw
output a Summary when processing is completed
These can be combined:
-lfsw
List files as they are processed, output about
those that required Formatting, and output
a Summary at the end of the entire operation.
The exit status is unchanged by any of these additional switches:
- for
-w
it is the number of files where there was some failure of formatting - for
-c
it is the number of files requiring formattting
For example:
% ./zprintm-1.2.2 -lfsc src/zprint/*.cljc
Processing file src/zprint/ansi.cljc
Processing file src/zprint/config.cljc
Formatting required in file src/zprint/config.cljc
Processing file src/zprint/core.cljc
Formatting required in file src/zprint/core.cljc
Processing file src/zprint/finish.cljc
Processing file src/zprint/focus.cljc
Processing file src/zprint/macros.cljc
Processing file src/zprint/main.cljc
Formatting required in file src/zprint/main.cljc
Processing file src/zprint/range.cljc
Processing file src/zprint/redef.cljc
Processing file src/zprint/rewrite.cljc
Processing file src/zprint/smacros.cljc
Processing file src/zprint/spec.cljc
Formatting required in file src/zprint/spec.cljc
Processing file src/zprint/sutil.cljc
Processing file src/zprint/zfns.cljc
Processing file src/zprint/zprint.cljc
Formatting required in file src/zprint/zprint.cljc
Processing file src/zprint/zutil.cljc
Processed 16 files, 5 of which require formatting.
The exit status was 5 following the above operation.
Here is another example, using the same files, where the formatting width is changed to 90:
% ./zprintm-1.2.2 '{:width 90}' -lfsc src/zprint/*.cljc
Processing file src/zprint/ansi.cljc
Processing file src/zprint/config.cljc
Formatting required in file src/zprint/config.cljc
Processing file src/zprint/core.cljc
Formatting required in file src/zprint/core.cljc
Processing file src/zprint/finish.cljc
Formatting required in file src/zprint/finish.cljc
Processing file src/zprint/focus.cljc
Formatting required in file src/zprint/focus.cljc
Processing file src/zprint/macros.cljc
Formatting required in file src/zprint/macros.cljc
Processing file src/zprint/main.cljc
Formatting required in file src/zprint/main.cljc
Processing file src/zprint/range.cljc
Formatting required in file src/zprint/range.cljc
Processing file src/zprint/redef.cljc
Formatting required in file src/zprint/redef.cljc
Processing file src/zprint/rewrite.cljc
Formatting required in file src/zprint/rewrite.cljc
Processing file src/zprint/smacros.cljc
Processing file src/zprint/spec.cljc
Formatting required in file src/zprint/spec.cljc
Processing file src/zprint/sutil.cljc
Formatting required in file src/zprint/sutil.cljc
Processing file src/zprint/zfns.cljc
Processing file src/zprint/zprint.cljc
Formatting required in file src/zprint/zprint.cljc
Processing file src/zprint/zutil.cljc
Formatting required in file src/zprint/zutil.cljc
Processed 16 files, 13 of which require formatting.
Despite being previously formatted for a width of 80, not all of the files formatted differently for a width of 90, though all but 3 did. Those three are short files with nothing that would change were they formatted for a width of 90.
Get prebuilt binaries for:
As you might expect:
zprint -h
is your friend!
% ./zprintm-1.2.2 -h
zprint-1.2.2
zprint <options-map> <input-file >output-file
zprint <switches> <input-file >output-file
zprint -w input-and-output-file(s)
zprint <options-map> -w input-and-output-file(s)
zprint <switches> -w input-and-output-file(s)
Where zprint is any of:
zprintm-1.2.2
zprintl-1.2.2
java -jar zprint-filter-1.2.2
<options-map> is a Clojure map containing zprint options. Must be first.
Note that since it contains spaces, it must be
wrapped in quotes, for example:
'{:width 120}'
Use the -e switch to see the total options
map, which will show you what is configurable.
<switches> which do no formatting, only one allowed:
-h --help Output this help text.
-v --version Output the version of zprint.
-e --explain Output non-default configuration values, showing
where any non-default values where set.
--explain-all Output full configuration, including all default
values, while showing where non-default values set.
<switches> which control configuration, only one allowed:
-d --default Accept no configuration input.
-u --url URL Load options from URL.
--url-only URL Load only options found from URL,
ignore all .zprintrc, .zprint.edn files.
<switches> which process named files: May follow a configuration switch
or an options map, but not both!
-w --write FILE read, format, and write to FILE (or FILEs),
-w *.clj is supported.
-c --check FILE read and check format of FILE (or FILEs)
-c *.clj is supported.
Variations on -w, --write and -c, -check:
-lw --list-write FILE like -w, but indicate which files processed.
-fw --formatted-write FILE like -w, but indicate which files changed.
-sw --summary-write FILE like -w, but include a summary of the number
of files processed and how many required a
format change, as well as any errors.
Combinations are allowed, w/write and c/check must always be last,
and order matters for -- switches. Examples:
-lfw, -lfsw, -fsw, -flw, -sflw, etc.
--list-formatted-write, --list-formatted-summary-write, etc.
All combinations of -w and --write switches are also allowed
with -c and --check switches:
-lfc, -lfsc, -fsc, -flc, -sflc, etc.
--list-formatted-check, --list-formatted-summary-check, etc.
The -w ,-c, and -e switches are the only switches where you may also
have an options map!
- Works anywhere you can install Java
- Startup in a few seconds
- Java appcds will cache startup info, making startup about 1s
- Accept source on stdin, produces formatted source on stdout
- Reads configuration from
~/.zprintrc
- Accept options map on command line
Uberjar example:
java -jar zprint-filter '{:width 90}' < myfile.clj > myfile.out.clj
or
java -jar zprint-filter '{:width 90}' -w myfile.clj
will read myfile.clj, format the source, and write the result back into myfile.clj
You can also format all of the clojure files in a directory with:
java -jar zprint-filter -w *.clj
This will format each of the .clj files, and if there are any errors, it will report the error for that file, and continue on processing the rest of the files. If there are errors formatting any file, the contents of that file remain unchanged.
Get the:
- uberjar starts in several seconds
- accelerated uberjar starts in about 1s
Add the following to the :aliases
section of $HOME/.clojure/deps.edn
file or to a project's deps.edn
.
For example:
$ cat > deps.edn <<< $'
{:aliases {:zprint {:extra-deps
{org.clojure/clojure
{:mvn/version "1.9.0"},
zprint {:mvn/version
"1.2.2"}},
:main-opts ["-m" "zprint.main"]}},
:deps {org.clojure/clojure {:mvn/version "1.9.0"},
zprint {:mvn/version "1.2.2"}}}'
$ clj -A:zprint < deps.edn
$ clj -m zprint.main <deps.edn
Then you can use the following as filter and pretty printer:
cat /path/to/file.clj | clojure -A:zprint
Note: If you are going to be doing this a lot (and can't use the the high performance prebuilt binaries -- #1, above) the accelerated uberjar will startup much faster and run as fast once it has started.
- Leiningen plugin:
[lein-zprint "1.2.2"]
- Accepts configuration from
:zprint
key in project.clj - Will (optionally) replace existing source files with reformatted versions
- Reads configuration from
~/.zprintrc
- Accept options map on command line
For example, you might use it like this:
lein zprint '{:width 90}' src/myproj/*.clj
Processing file: src/myproj/myfile.clj
Processing file: src/myproj/myotherfile.clj
Get it: put [lein-zprint "1.2.2"]
in the vector that is the value of
the :plugins
key in project.clj
:
(defproject zpuse "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
:url "https://www.eclipse.org/legal/epl-2.0/"}
:plugins [[lein-zprint "1.2.2"]]
:dependencies [[org.clojure/clojure "1.10.0"]]
:repl-options {:init-ns zpuse.core})
There is a node based zprint program, zprint-clj.
npm i -g zprint-clj
$ zprint-clj -V
0.8.0
$ zprint-clj -h
Usage: zprint-clj [options]
Options:
-V, --version output the version number
-c, --check "<pattern>" Checks formatting without writing to output,
zprint-clj -c "./out/**/*.{clj,cljs,cljc,edn}"
-i, --input "<pattern>" Input file, directory or glob pattern.
If no output specified writes to stdout.
-o, --out "<path>" Output path, file or directory
--hang Enable hang mode (better formatting, but 2x slowdown)
-h, --help output usage information
$zprint-clj -i "myfile.clj" -o "myfile.1.clj"
Note that the default for this tool is (effectively) {:style :no-hang}
, which
means that it will never hang anything. This doesn't produce the best looking
code, but it does run much faster (about like the graalVM binaries, in
fact).
If you can use the pre-built binaries mentioned above, you would probably be wise to do so, since they startup as fast or faster than Javascript/Clojurescript based programs, and run considerably faster.
Casual testing indicates that, on a mid 2012 MacBook Air, zprint-clj 0.8.0 starts up in about 222ms, while zprintm-0.5.4 starts up in about 20ms (after you have used it once).
In additional casual testing, the "... but 2x slowdown" comment in the help, above, seems accurate.
Comparing zprint-clj 0.8.0 with the graalVM binary zprintm-0.5.4, using the
defaults, both took about 5 seconds to process a large file (5241 loc).
The difference is that zprintm-0.5.4 did this with the normal defaults, that
is, it produced code formatted to look as good or better than hand formatted
code since hangs were enabled by default. The defaults for zprint-clj are
{:style :no-hang}
, so the resulting formatting was
not as nice. The same file run through zprint-clj with --hang
, to generate
output equivalent to zprintm-0.5.4 took about 12 seconds.
You can alter the way that zprint formats a single function or any part of an entire file by including comments in the file which contain zprint comment formatting directives.