Formatting
We have tried to make Calva's formatter so that it just works. It is enabled by default for Clojure files, and with the default configuration it mostly follows Bozhidar Batsov's Clojure Style Guide. Calva uses cljfmt for the formatting.
Tab formats the current surrounding form
Calva's code formatter sets the default keybinding of its Format Current Form command to tab
. Meaning that most often when things look a bit untidy, you can press tab
to make things look pretty. Good to know, right? For performance reasons it only formats the current enclosing form, so sometimes you want to move the cursor up/out a form (ctrl+up
) first. See The Paredit Guide for more on moving the cursor structurally through your code.
With the default settings, Calva's formatting behaves like so:
- indents as you type (when entering new lines)
- formats the current enclosing form when you hit
tab
- formats pasted code
- formats according to community standards
- formats the current form, aligning map keys and values, when you press
ctrl+alt+l
- formats
(comment ...)
forms special, see rich comments
Infer parens at will
Calva has a command that will ”heal” the bracket structure if it is correctly indented using Parinfer Infer parens. This command is default bound to ctrl+alt+p i
.
Also: If you have Format on Save enabled in VS Code, it will be Calva doing the formatting for Clojure files.
Calva's formatting is mostly about indenting, but it also (again, defaults):
- trims whitespace at the end of the line
- trims whitespace inside brackets
- this also folds trailing brackets (a k a the paren trail) up on the same line
- inserts whitespace between forms
Not a fan of some default setting? The formatter is quite configurable.
Format current form command variants
There are three special commands for formatting the current form:
1. Format and Align Current Form
Aligns associative structures and bindings in two columns. See more below.
2. Format Current Form and trim space between forms
This formats the text, and trims consecutive, non-indent, whitespace on a line to just one space. Something like:
(let [a :b]
(str "foo" "bar" "baz"
"a" a))
Becomes:
(let [a :b]
(str "foo" "bar" "baz"
"a" a))
Basically, it behaves like if :remove-multiple-non-indenting-spaces? true
was added to the cljfmt
config. Which, in fact, is what happens. Calva merges that onto your cljfmt config when this command is used.
3. Replace Current Form (or Selection) with Pretty Printed Form
This command will run the code of the Current Form through Calva's pretty printer (the engine named calva
, which is using zprint) and replace the current form inline in the editor with the pretty printed results.
Unlike with the ”real” Calva Formatter, which never breaks up lines, this one will follow your pretty printing options and break up lines if you have set maxWidth
to something that calls for breaking up lines.
Applies to the other Current Form
Unlike the other Format commands, which applies to the current enclosing form, this one applies to the Current Form, same as with evaluations. That is because this is not really part of the Calva formatter, but rather is a convenience command for tidying up code or data.
Configuration
You can adjust the above mentioned defaults, and the default indents, by configuring the formatting using cljfmt's configuration EDN.
This configuration can either be provided via a file or via clojure-lsp (see Clojure LSP Settings).
Providing configuration via a config file
Calva will look for the configuration in one of the default cljfmt paths ('.cljfmt.edn', '.cljfmt.clj', 'cljfmt.edn', or 'cljfmt.clj' in the workspace root). If your file is somewhere else use the calva.fmt.configPath
to tell Calva where to find it. The path should either be absolute, or relative to the workspace root directory. If your config file is somewhere in the workspace root, Calva will hot reload it when you update it.
Wherever the config file is, a suggested path for providing your configuration is to start changing the Calva formatting defaults by pasting the following map into a file and save it.
{:remove-surrounding-whitespace? true
:remove-trailing-whitespace? true
:remove-consecutive-blank-lines? false
:insert-missing-whitespace? true
:remove-multiple-non-indenting-spaces? false}
If the file is in the workspace, you can quickly test how different settings affect the formatting. Try:
- Adding
:align-associative? true
to the config - then save
- then hit
tab
, and see what happens.
:align-associative?
is experimental
This particular setting is experimental and known to cause trouble together with namespaced keywords. Consider using ctrl+alt+l
instead of tab
as your formatting command, instead of enabling this setting. See below for more info about this. See more below about this.
No Leiningen config support
The cljfmt docs mention the :cljfmt
config key of Leiningen projects. Calva does not yet read the config from there, so if your Leiningen project has such a configuration, you will need to copy it out into a file.
Providing configuration via clojure-lsp
If you work in a team where some members use clojure-lsp for formatting, you can make Calva format using the same configuration by telling setting calva.fmt.configPath
to CLOJURE-LSP
(case sensitive).
Note that doing this you will not have hot reload of the formatting configuration, and of course you will be depending on that clojure-lsp is running and functioning.
Indentation rules
The cljfmt
indents are highly configurable. They, and the rest of the configuration options, are masterly detailed here.
Calva is an extra good tool for experimenting with these settings. cljfmt
doesn't care about keys in the map that it doesn't know about so you can sneak in test code there to quickly see how it will get formatted by certain rules. Try this, for instance:
{:remove-surrounding-whitespace? true
:remove-trailing-whitespace? true
:remove-consecutive-blank-lines? false
:insert-missing-whitespace? false
:indents ^:replace {#"^\w" [[:inner 0]]}
:test-code
(concat [2]
(map #(inc (* % 2))
(filter #(aget sieved %)
(range 1 hn))))}
Save, then hit tab
, and the code should get formatted like so:
:test-code
(concat [2]
(map #(inc (* % 2))
(filter #(aget sieved %)
(range 1 hn))))
That's somewhat similar to Nikita Prokopov's Better Clojure Formatting suggestion. (Please be aware that this setting might not be sufficient to get complete Tonsky Formatting, please share any settings you use to get full compliance.)
Rich Comments
To encourage use of (comment ...)
forms for development, the default settings give these forms get a special treatment when formatting. Use the calva.fmt.keepCommentTrailParenOnOwnLine
setting to control this behaviour. See Rich Comments first.
Etecetera
About aligning associative forms
Calva loooks in the config map for the key :align-associative?
and if it is true
it will use an old version of cljfmt which is patched with functionality for doing this alignment. Note, though:
- The implementation is a bit buggy and can do a bit crazy formatting on certain forms.
- The older version of cljfmt lacks updates for some new Clojure features and also some bugs fixed since the fork are not applied.
You are hereby warned, and let us also remind you about the Format and Align Current Form command which lets you apply this formatting a bit more surgically, and on demand.
This old version of cljfmt is inlined in the Calva repository along with the discontinued rewrite-cljs
project. Regard it as frozen code. If you want Calva's formatter to have full support for newer Clojure constructs and the bugs in the alignment code fixed, contribute to cljfmt. See this issue for starting to collect context.