Formatting Codeλ︎
Spacemacs automatically formats code as its written.
, =
or M-RET =
is the format menu in Spacemacs across all languages
TAB
indents the current line of code (or selected region). Not that TAB
may also trigger auto-completion too.
Clojure Style Guide
The Clojure Style Guide is a detailed guide to common code styles and idioms. Adopting a style guide that follows most of these recommentations will help ensure code is easier to read and maintain by future Clojure developers
Cider format toolsλ︎
, = b
(cider-format-buffer
) - format the Clojure code in the current buffer.
, = l
(clojure-align
) - vertically align the current line within the context of the top level form or selected area
Vertically align the values in a map
Clojure automatic align
clojure-indent-style 'align-arguments
clojure layer variable automatically aligns arguments when triggering indentation, i.e. pressing Tab
practicalli/spacemacs-config already containes this variable in the clojure layer
Indentation of function forms Vertically align s-expressions
Aggressive Indent mode and Clojure LSP clash
aggressive-indent-mode
set as a clojure layer variable will automatically adjust indentation as code is entered into the buffer.
Aggressive indent mode and Clojure LSP live linting will interact with each others changes and cause very strange side effects. Either use Clojure LSP live linting or aggressive indent mode, but never both together.
Enable aggressive indent mode by adding the a hook in the dotspacemacs/user-config
section of the Spacemacs user configuration
(add-hook 'clojure-mode-hook #'aggressive-indent-mode)
Clojure LSPλ︎
Clojure LSP uses cljfmt which has a large number of very strict rules, although all rules can be tailored or disabled as required.
Add format rules to .config/clojure-lsp/cljfmt.edn
file, adding :cljfmt-config-path "cljfmt.edn"
setting in .config/clojure-lsp/config.edn
to make use of those rules.
cljfmt rules from Practicalli Clojure LSP Config
practicalli/clojure-lsp-config provides a cljfmt configuration used by Clojure LSP to automatically format code in the current buffer.
Several of the more strict cljfmt rules have been disabled to help keep code readable, e.g. allowing more than one blank line between code expressions.
{;; Clojure format
;; https://github.com/weavejester/cljfmt
:cljfmt
{;; correct indentation - see cljfm indents
:indentation? true
;; remove whitespace surrounding inner forms
:remove-surrounding-whitespace? true
;; remove trailing whitespace in lines
:remove-trailing-whitespace? true
;; insert whitespace missing from between elements
:insert-missing-whitespace? true
;; Delete more than one consecutive blank line - annoying
:remove-consecutive-blank-lines? false
;; Remove spaces not used for indentation
:remove-multiple-non-indenting-spaces? true
;; break hashmaps onto multiple lines
:split-keypairs-over-multiple-lines? true
;; Use #re for regex indents configuration
;; :cljfmt {:indents {#re ".*" ns [[:inner 0] [:inner 1]]}}
:indents {}}}
Command Line formatλ︎
cljstyle is a binary tool for checking and updating formatting for all Clojure files, following the Clojure style guide and very similar to the format of cljfmt tool from Clojure LSP.
cljstyle releases page contains operating system specific binary files. Download and install the appropriate file in the operating system execution path.
Recommended Linux install location
Extract the cljstyle
binary from cljstyle_xxx_linux.tar.gz
archive file to $HOME/.local/bin/
which should already be on the operating system path.
Check the format of all clojure files and print a report that includes diff view of recommended format changes
Or automatically update all Clojure files with any changes to their formatting (recommend adding or committing changes into version control first, to help identify format changes and roll back any undesirable formatting)
Using cljstyle and zprint for clojure formatting
Continuous Integrationλ︎
Setup Clojure GitHub Action includes cljstyle and zprint as optional tools to run as part of a continuous integration workflow.
Example GitHub workflow for code quality
name: Test and Package project
on:
pull_request:
push:
branches:
- main
jobs:
clojure:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Cache Clojure Dependencies
uses: actions/cache@v3
with:
path:
- ~/.m2
- ~/.gitlibs
key: cache-${{ hashFiles('**/deps.edn') }}
restore-keys: clojure-deps-
- name: Prepare java
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Install clojure tools
uses: DeLaGuardo/setup-clojure@9.5
with:
cli: 1.11.1.1165 # Clojure CLI based on tools.deps
cljstyle: 0.15.0 # cljstyle
clj-kondo: 2022.10.05 # Clj-kondo
- name: Run Unit tests
run: clojure -X:test/run
- name: "Lint with clj-kondo"
run: clj-kondo --lint deps.edn src resources test --config .clj-kondo/config-ci.edn
- name: "Check Clojure Style"
run: cljstyle check --report
Practicalli GitHub Workflow for a Clojure project Build and run Clojure with Multi-stage Dockerfile