Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork247
clojure-emacs/clojure-mode
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
clojure-mode
is an Emacs major mode that provides font-lock (syntaxhighlighting), indentation, navigation and refactoring support for theClojure(Script) programming language.
Important
This documentation tracks themaster
branch ofclojure-mode
. Some of thefeatures and settings discussed here might not be available in older releases(including the current stable release). Please, consult the relevant git tag(e.g.5.20.0) ifyou need documentation for a specificclojure-mode
release.
Available on the majorpackage.el
community maintained repos -MELPA Stable andMELPA repos.
MELPA Stable is the recommended repo as it has the latest stableversion. MELPA has a development snapshot for users who don't mind(infrequent) breakage but don't want to run from a git checkout.
You can installclojure-mode
using the following command:
M-xpackage-install
[RET]clojure-mode
[RET]
or if you'd rather keep it in your dotfiles:
(unless (package-installed-p'clojure-mode) (package-install'clojure-mode))
If the installation doesn't work try refreshing the package list:
M-xpackage-refresh-contents
Theclojure-mode
package actually bundles together several major modes:
clojure-mode
is a major mode for editing Clojure codeclojurescript-mode
is a major mode for editing ClojureScript codeclojurec-mode
is a major mode for editing.cljc
source filesclojuredart-mode
is a major mode for editing ClojureDart.cljd
source filesjank-mode
is a major mode for editing Jank.jank
source filesjoker-mode
is a major mode for editing Joker.joke
source files
All the major modes derive fromclojure-mode
and provide more or less the samefunctionality. Differences can be found mostly in the font-locking -e.g. ClojureScript has some built-in constructs that are not present in Clojure.
The proper major mode is selected automatically based on the extension of thefile you're editing.
Having separate major modes gives you the flexibility to attach different hooksto them and to alter their behavior individually (e.g. add extra font-lockingjust toclojurescript-mode
) .
Note that all modes derive fromclojure-mode
, so things you add toclojure-mode-hook
andclojure-mode-map
will affect all the derived modes aswell.
In the spirit of Emacs, pretty much everything you can think of inclojure-mode
is configurable.
To see a list of available configuration options doM-x customize-group RET clojure
.
The default indentation rules inclojure-mode
are derived from thecommunity Clojure Style Guide.Please, refer to the guide for the general Clojure indentation rules.
If you'd like to use the alternative "fixed/tonsky" indentation style you shouldupdate your configuration accordingly:
(setq clojure-indent-style'always-indent clojure-indent-keyword-style'always-indent clojure-enable-indent-specsnil)
Read on for more details on the available indentation-related configuration options.
By default multi-line docstrings are indented with 2 spaces, as this is asomewhat common standard in the Clojure community. You can however adjust thisby modifyingclojure-docstring-fill-prefix-width
. Set it to 0 if you don'twant multi-line docstrings to be indented at all (which is pretty common in most lisps).
The indentation of function forms is configured by the variableclojure-indent-style
. It takes three possible values:
always-align
(the default)
(some-function1012)(some-function1012)
always-indent
(some-function1012)(some-function1012)
align-arguments
(some-function1012)(some-function1012)
Note
Prior to clojure-mode 5.10, the configuration options forclojure-indent-style
used to bekeywords, but now they are symbols. Keywords will still be supported at least until clojure-mode 6.
Similarly we have theclojure-indent-keyword-style
, which works in the following way:
always-align
(default) - Allargs are vertically aligned with the first arg in case (A),and vertically aligned with the function name in case (B).
(:require [foo.bar] [bar.baz])(:require [foo.bar] [bar.baz])
always-indent
- All args are indented like a macro body.
(:require [foo.bar] [bar.baz])(:x location0)
align-arguments
- Case (A) is indented likealways-align
, andcase (B) is indented like a macro body.
(:require [foo.bar] [bar.baz])(:x location0)
The indentation of special forms and macros with bodies is controlled viaput-clojure-indent
,define-clojure-indent
andclojure-backtracking-indent
.Nearly all special forms and built-in macros with bodies have special indentationsettings inclojure-mode
. You can add/alter the indentation settings in yourpersonal config. Let's assume you want to indent->>
and->
like this:
(->> something ala bala portokala)
You can do so by putting the following in your config:
(put-clojure-indent'->1)(put-clojure-indent'->>1)
This means that the body of the->/->>
is after the first argument.
A more compact way to do the same thing is:
(define-clojure-indent (->1) (->>1))
To indent something like a definition (defn
) you can do something like:
(put-clojure-indent'>defn:defn)
You can also specify different indentation settings for symbolsprefixed with some ns (or ns alias):
(put-clojure-indent'do0)(put-clojure-indent'my-ns/do1)
The bodies of certain more complicated macros and special forms(e.g.letfn
,deftype
,extend-protocol
, etc) are indented usinga contextual backtracking indentation method, require more sophisticatedindent specifications. Here are a few examples:
(define-clojure-indent (implement '(1 (1))) (letfn '(1 ((:defn))nil)) (proxy '(2nilnil (1))) (reify '(:defn (1))) (deftype '(2nilnil (1))) (defrecord '(2nilnil (1))) (specify '(1 (1))) (specify '(1 (1))))
These follow the same rules as the:style/indent
metadata specified bycider-nrepl.For instructions on how to write these specifications, seethis document.The only difference is that you're allowed to use lists instead of vectors.
The indentation ofspecial arguments is controlled byclojure-special-arg-indent-factor
, which by default indents special argumentsa furtherlisp-body-indent
when compared to ordinary arguments.
An example of the default formatting is:
(defrecordMyRecord [my-field])
Note thatdefrecord
has two special arguments, followed by the form's body -namely the record's name and its fields vector.
Settingclojure-special-arg-indent-factor
to 1, results in:
(defrecordMyRecord [my-field])
You can completely disable the effect of indentation specs like this:
(setq clojure-enable-indent-specsnil)
clojure-mode
differentiates between comments like;
,;;
, etc.By defaultclojure-mode
treats;
as inline comments andalways indents those.You can change this behaviour like this:
(add-hook'clojure-mode-hook (lambda () (setq-local comment-column0)))
You might also want to changecomment-add
to 0 in that way, so that Emacs commentfunctions (e.g.comment-region
) would use;
by default instead of;;
.
Tip
Check outthis section of the Clojurestyle guide to understand better the semantics of the different comment levelsand whyclojure-mode
treats them differently by default.
You can vertically align sexps withC-c SPC
. For instance, typingthis combo on the following form:
(defmy-map {:a-key1:other-key2})
Leads to the following:
(defmy-map {:a-key1:other-key2})
This can also be done automatically (as part of indentation) byturning onclojure-align-forms-automatically
. This way it willhappen whenever you select some code and hitTAB
.
clojure-mode
features static font-locking (syntax highlighting) that you canextend yourself if needed. As typical for Emacs, it's based on regularexpressions. You can find the default font-locking rules inclojure-font-lock-keywords
. Here's how you can add font-locking for built-inClojure functions and vars:
(defvarclojure-built-in-vars '(;; clojure.core"accessor""aclone""agent""agent-errors""aget""alength""alias""all-ns""alter""alter-meta!""alter-var-root""amap";; omitted for brevity ))(defvarclojure-built-in-dynamic-vars '(;; clojure.test"*initial-report-counters*""*load-tests*""*report-counters*""*stack-trace-depth*""*test-out*""*testing-contexts*""*testing-vars*";; clojure.xml"*current*""*sb*""*stack*""*state*" ))(font-lock-add-keywords'clojure-mode `((,(concat"(\\(?:\.*/\\)?" (regexp-opt clojure-built-in-varst)"\\>")1font-lock-builtin-face)))(font-lock-add-keywords'clojure-mode `((,(concat"\\<" (regexp-opt clojure-built-in-dynamic-varst)"\\>")0font-lock-builtin-face)))
Note: The packageclojure-mode-extra-font-locking
provides such additionalfont-locking for Clojure built-ins.
As you might imagine one problem with this font-locking approach is that becauseit's based on regular expressions you'll get some false positives here and there(there's no namespace information, and no way forclojure-mode
to know whatvar a symbol resolves to). That's whyclojure-mode
's font-locking defaults areconservative and minimalistic.
Precise font-locking requires additional data that can obtained from a runningREPL (that's how CIDER'sdynamicfont-lockingworks) or from static code analysis.
When it comes to non built-in definitions,clojure-mode
needs to be manuallyinstructed how to handle the docstrings and highlighting. Here's an example:
(put'>defn'clojure-doc-string-elt2)(font-lock-add-keywords'clojure-mode `((,(concat"(\\(?:" clojure--sym-regexp"/\\)?""\\(>defn\\)\\>")1font-lock-keyword-face)))
Note
Theclojure-doc-string-elt
attribute is processed by the functionclojure-font-lock-syntactic-face-function
.
The available refactorings were originally created and maintained by theclj-refactor.el
team. The ones implemented in Elisp only are gradually migratedtoclojure-mode
.
clojure-thread
: Thread another form into the surrounding thread. Both->>
and->
variants are supported.
clojure-unwind
: Unwind a threaded expression. Supports both->>
and->
.
clojure-thread-first-all
: Introduce the thread first macro (->
) and rewritethe entire form. With a prefix argument do not thread the last form.
clojure-thread-last-all
: Introduce the thread last macro and rewrite theentire form. With a prefix argument do not thread the last form.
clojure-unwind-all
: Fully unwind a threaded expression removing the threadingmacro.
clojure-cycle-privacy
: Cycle privacy ofdef
s ordefn
s. Use metadataexplicitly with settingclojure-use-metadata-for-privacy
tot
fordefn
stoo.
clojure-cycle-not
: Add or remove anot
form around the current form.
clojure-cycle-when
: Find the closestwhen
orwhen-not
up the syntax treeand toggle it.
clojure-cycle-if
: Find the closestif
orif-not
up the syntax tree andtoggle it. Also transpose theelse
andthen
branches, keeping the semanticsthe same as before.
Convert any given collection at point to list, quoted list, map, vector or set.
clojure-introduce-let
: Introduce a newlet
form. Put the current form intoits binding form with a name provided by the user as a bound name. If calledwith a numeric prefix put the let form Nth level up in the form hierarchy.
clojure-move-to-let
: Move the current form to the closestlet
's bindingform. Replace all occurrences of the form in the body of the let.
clojure-let-forward-slurp-sexp
: Slurp the next form after thelet
into thelet
. Replace all occurrences of the bound forms in the form added to thelet
form. If called with a prefix argument slurp the next n forms.
clojure-let-backward-slurp-sexp
: Slurp the form before thelet
into thelet
. Replace all occurrences of the bound forms in the form added to thelet
form. If called with a prefix argument slurp the previous n forms.
paredit-convolute-sexp
is advised to replace occurrences of bound forms with their bound names when convolute is used on a let form.
clojure-rename-ns-alias
: Rename an alias inside a namespace declaration,and all of its usages in the buffer
If there is an active selected region, only rename usages of aliases within the region,without affecting the namespace declaration.
clojure-add-arity
: Add a new arity to an existing single-arity or multi-arity function.
- clojure-mode-extra-font-locking provides additional font-lockingfor built-in methods and macros. The font-locking is prettyimprecise, because it doesn't take namespaces into account and itwon't font-lock a function at all possible positions in a sexp, butif you don't mind its imperfections you can easily enable it:
(require'clojure-mode-extra-font-locking)
The code inclojure-mode-font-locking
used to be bundled withclojure-mode
before version 3.0.
You can also use the code in this package as a basis for extending thefont-locking further (e.g. functions/macros from morenamespaces). Generally you should avoid adding special font-lockingfor things that don't have fairly unique names, as this will result inplenty of incorrect font-locking. CIDER users should avoid this package,as CIDER does its own dynamic font-locking, which is namespace-awareand doesn't produce almost any false positives.
clj-refactor provides additional refactoring support.
Enabling
CamelCase
support for editing commands (likeforward-word
,backward-word
, etc) inclojure-mode
is quiteuseful since we often have to deal with Java class and methodnames. The built-in Emacs minor modesubword-mode
provides suchfunctionality:
(add-hook'clojure-mode-hook#'subword-mode)
- The use ofparedit when editing Clojure (or any other Lisp) codeis highly recommended. It helps ensure the structure of your forms isnot compromised and offers a number of operations that work on codestructure at a higher level than just characters and words. To enableit for Clojure buffers:
(add-hook'clojure-mode-hook#'paredit-mode)
- smartparens is an excellent(newer) alternative to paredit. Many Clojure hackers have adopted itrecently and you might want to give it a try as well. To enable
smartparens
use the following code:
(add-hook'clojure-mode-hook#'smartparens-strict-mode)
- RainbowDelimiters is aminor mode which highlights parentheses, brackets, and bracesaccording to their depth. Each successive level is highlighted in adifferent color. This makes it easy to spot matching delimiters,orient yourself in the code, and tell which statements are at agiven depth. Assuming you've already installed
RainbowDelimiters
you canenable it like this:
(add-hook'clojure-mode-hook#'rainbow-delimiters-mode)
- aggressive-indent-mode automatically adjust the indentation of your code,while you're writing it. Using it together with
clojure-mode
is highlyrecommended. Provided you've already installedaggressive-indent-mode
you canenable it like this:
(add-hook'clojure-mode-hook#'aggressive-indent-mode)
Note that it might cause performance issues if you're dealing with largeClojure source files.
One of the fundamental aspects of Lisps in general, and Clojure inparticular, is the notion of interactive programming - building yourprograms by continuously changing the state of the running Lispprogram (as opposed to doing something more traditional like making achange and re-running the program afterwards to see the changes inaction). To get the most of clojure-mode you'll have to combine itwith some tool which will allow you to interact with your Clojure program(a.k.a. process/REPL).
A number of options exist for connecting to arunning Clojure process and evaluating code interactively.
inf-clojure provides basic interaction with a Clojure REPL process.It's very similar in nature and supported functionality toinferior-lisp-mode
for Common Lisp.
CIDER is a powerful Clojure interactive development environment,similar to SLIME for Common Lisp.
If you're into Clojure and Emacs you should definitely check it out.
Tutorials,targeting Emacs beginners, are available atclojure-doc.org andClojure for the Brave and the True.Keep in mind, however, that they might be out-of-date.
clojure-mode
is a capable tool, but it's certainly not perfect. This sectionlists a couple of general design problems/limitations that might affect yourexperience negatively.
clojure-mode
derives a lot of functionality directly fromlisp-mode
(anEmacs major mode for Common Lisp), which simplified the initial implementation,but also made it harder to implement certain functionality. Down the road it'dbe nice to fully decoupleclojure-mode
fromlisp-mode
.
Seethis ticket for a bit more details.
clojure-mode
's indentation engine is a bit slow. You can speed things upsignificantly by disablingclojure-use-backtracking-indent
, but this willbreak the indentation of complex forms likedeftype
,defprotocol
,reify
,letfn
, etc.
We should look into ways to optimize the performance of the backtrackingindentation logic. Seethis ticket for moredetails.
As mentionedabove, thefont-locking is implemented in terms of regular expressions which makes it bothslow and inaccurate.
An extensive changelog is availablehere.
Copyright © 2007-2025 Jeffrey Chu, Lennart Staflin, Phil Hagelberg, BozhidarBatsov, Artur Malabarba, Magnar Sveen andcontributors.
Distributed under the GNU General Public License; typeC-h C-c to view it.
About
Emacs support for the Clojure(Script) programming language
Topics
Resources
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Sponsor this project
Uh oh!
There was an error while loading.Please reload this page.
Packages0
Uh oh!
There was an error while loading.Please reload this page.