Clojure Quality toolsλ︎
Syntax & Idiom checkλ︎
clj-kondo is a lint tool that highlights syntactic errors and suggests idioms for Clojure, ClojureScript and EDN.
Use clj-kondo with your preferred editor to warning about errors as you type so issues can be fixed as soon as they occur, enhancing your joy of Clojure.
clj-kondo can also be used as a command line tool for checking projects in development environments and continuous integration service, such as the setup-clojure GitHub action.
Clojure LSP includes clj-kondo
Clojure LSP install includes clj-kondo, removing the need for a separate install of clj-kondo
Clj-kondo config contains additional configuration for using clj-kondo with libraries that extend the Clojure language via macros.
Command Lineλ︎
Run clj-kondo
with the --lint option and specify a file or path
To analyse a specific file
Analyse a project, running the clj-kondo command from the root of the project
GitHub workflowλ︎
Add clj-kondo linting to continuous integration workflow checks for syntax errors with Clojure files.
Setup Clojure Clojure Lint & Reviewdog Setup clj-kondo
Setup Clojure with clj-kondo and cljstyle checks
---
name: "Quality Checks"
on:
pull_request:
push:
branches:
- live
jobs:
tests:
name: "Check Code Quality"
runs-on: ubuntu-latest
steps:
- run: echo "🚀 Job automatically triggered by ${{ github.event_name }}"
- run: echo "🐧 Job running on ${{ runner.os }} server"
- run: echo "🐙 Using ${{ github.ref }} branch from ${{ github.repository }} repository"
- name: "Checkout code"
uses: actions/checkout@v3.3.0
- run: echo "🐙 ${{ github.repository }} repository was cloned to the runner."
- name: "Install tools"
uses: DeLaGuardo/setup-clojure@10.1
with:
cljstyle: 0.15.0
clj-kondo: 2022.11.02
- name: "Lint Clojure"
run: clj-kondo --lint deps.edn --config '{:output {:pattern "::{{level}} file={{filename}},line={{row}},col={{col}}::{{message}}"}}'
- name: "Check Clojure Style"
run: cljstyle check --report
- run: echo "🎨 style and format of Clojure code checked"
- run: echo "🍏 Job status is ${{ job.status }}."
Setup clojure-lsp Action
Setup Clojure-LSP contains clj-kondo so can also be used within a continuous integration workflow as well as provide .
Format Check and Fixλ︎
Code is easier to read and work with when it is consistent format that follows common rules.
Clojure community style guide provides a common style for Clojure code. While most style recommendations are widely used, others are more contentious. Ultimately the development team for the project should define a workable set of style rules that makes them productions, ideally using much of those rules from the style guide.
A consistent format between editors also minimises version control changes not related to code design. The following format tools for clojure can all be configured to be consistent with each other (although zprint defaults will require more customisation):
- cljfmt - library, also included in Clojure LSP
- cljstyle - binary and library (re-write of cljfmt)
- zprint - binary & library
Tooling that uses the Clojure Style Guide
Emacs clojure-mode
and Clojure LSP (via cljfmt) format code following the most common Clojure style guide rules, although cljfmt rules are quite strick so Practicalli disables many of them.
cljstyle default configuration follows the majority of styles and has the same defaults as cljfmt. Practicalli Clojure CLI Config tweaks a few rules to make code more readable and allow for repl design experiments.
cljstyleλ︎
Cljstyle is a rewrite of cljfmt, designed to be easier to configure. The default rules implement many of the style rules from the Clojure community style guide and is compatible with cljfmt.
Call with the check
option to report formatting issues, providing a coloured diff view of the format changes
Call with fix
option to automatically update all Clojure files with fixes, indicating which files have changed.
Cljstyle will examine all files in the current directory and any sub-directories.
.cljstyle
configuration file in the root of the project can override the default customisation, including indentation rules.
cljstyle config used by Practicalli
Clojure App template repository contains the .cljstyle
configuration file used for all Practicalli projects
Install the latest binary release from the cljstyle GitHub repository onto the operating system path, e.g. $HOME/.local/bin
fix
option automatically updates all source code files that have format issues.
cljstyle can be used as a library without installing the cljstyle binary. Practicalli Clojure CLI Config defines the :format/cljstyle
alias which should be passed wither the check
or format
option
Check all the Clojure files (.clj .cljc .edn .cljs) in the current project
Clojure Alias for cljstyle
:format/cljstyle
{:extra-deps
{mvxcvi/cljstyle {:git/url "https://github.com/greglook/cljstyle.git"
:git/sha "14c18e5b593c39bc59f10df1b894c31a0020dc49"}}
:main-opts ["-m" "cljstyle.main" "check"]}
:format/cljstyle!
{:extra-deps
{mvxcvi/cljstyle {:git/url "https://github.com/greglook/cljstyle.git"
:git/sha "14c18e5b593c39bc59f10df1b894c31a0020dc49"}}
:main-opts ["-m" "cljstyle.main" "fix"]}
Use a Makefile to run common commands such as checking style, running tests, building uberjars, etc.
Practicalli Clojure App template repository contains an example Makefile that contains common tasks for Clojure development
This example calls the cljstyle binary, but could be changed to call the clojure -M:format/cljstyle check
and clojure -M:format/cljstyle fix
aliases instead.
# ------- Code Quality --------------- #
format-check: ## Run cljstyle to check the formatting of Clojure code
$(info --------- cljstyle Runner ---------)
cljstyle check
format-fix: ## Run cljstyle and fix the formatting of Clojure code
$(info --------- cljstyle Runner ---------)
cljstyle fix
# ------------------------------------ #
Stage changes before automatically fixing format
Practicalli suggests staging (or committing) changes before running cljstyle fix
to easily undo undesired changes or simply confirm what changes have been made
Practicall configuration
Practicalli updated the default cljstyle configuration with the following changes
Configure list indent to one character
Do not warn about duplicate var names (def, defn names) - excluded to stop warning about REPL experiments and design journal rich comments that contain alternative designs.
cljfmtλ︎
cljfmt is not available as a separate binary, although it a fixed part of the Clojure LSP server implementation.
whist typing Clojure code, Clojure LSP will format using cljfmt rules
Define a cljfmt configuration via Clojure LSP to define rules and indentation settings for all projects.
Or specify cljfmt configuration within the Clojure LSP configuration file
Practicalli Clojure LSP config - LSP and cljfmt
Practicalli Clojure LSP config provides an example config.edn configuration file for Clojure LSP that uses a cljfmt.edn configuration file for a minimum set of Clojure format rules
The default cljfmt rules feel overly strict and Practicalli configuration disables the more draconian rules to make code far more readable
zprintλ︎
zprint is a highly configurable format tool for both Clojure code and Clojure/EDN structures, available as a library and command line tool
zprint has advanced features over cljstyle and cljfmt, although may require some additional configuration work especially to format consistently with these tools.
No built-in diff option
zprint requires an external diff tool to see the format changes made, as zprint only reports on the files changed and not the content of those files that has changed.
zprint can write changes to a new file and a file comparison made. Or files can be staged / committed in a local Git repository before running zprint and a Git client used to see the diff.
Once the desirable styles and configuration are established there is less need for an external diff tool, although its always useful to have a quick way to check what format tools are doing.
Download zprint for Linux or MacOSX using the latest binary released on the GitHub repository
Move the binary to the executable path for the operating system, updating the name to zprint
(or use a symbolic link)
A more detailed zprint report checking all the Clojure files a project, including files in the route directory and all sub-directories (i.e. **/*.cjl
pattern)
Update formatting for all the files in a projects, showing details of the files processed and changed
zprint can be used as a library without installing the binary. Practicalli Clojure CLI Config defines the :format/zprint
alias which checks the format of a file and reports which files required
Clojure Alias for zprint
Add :format/zprint
alias to check format and :format/zprint!
to write format changes to a given file or filename pattern
:format/zprint
{:extra-deps {zprint/zprint {:mvn/version "1.2.4"}}
:main-opts ["-m" "zprint.main"
"{:style :indent-only}"
"--list-formatted-summary-check"]}
:format/zprint!
{:extra-deps {zprint/zprint {:mvn/version "1.2.4"}}
:main-opts ["-m" "zprint.main"
"{:style :indent-only}"
"--list-formatted-summary-write"]}
Configure zprint
It is assumed that the majority of format needs are met by one of the following style rule sets
{:style :indent-only}
only formats indentation, less likely to change the general style of code{:style :community}
a quite strict adhearence to the Clojure Community Guide (which Practicalli finds a little to strict)
Unless the code is really messy (e.g. not written in a clojure aware editor with live linting) then {:style :indent-only}
is a simple starting point.
If the team have adopted most if not all community styles, then {:style :community}
may be a more appropriate start point. Use --explain-all flag with the zprint command to see all the rules that are applied with a partiular style and modify as appropriate
$HOME/.zprintrc
is used for the configuration applied to all files, although this can be overridden in each project (or even as zprint comments in particular files)