- Notifications
You must be signed in to change notification settings - Fork18
The next generation Clojure major mode for Emacs, powered by TreeSitter
License
clojure-emacs/clojure-ts-mode
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
clojure-ts-mode is an Emacs major mode that provides font-lock (syntaxhighlighting), indentation, and navigation support for theClojure(Script) programming language, powered by thetree-sitter-clojuretree-sitter grammar.
clojure-mode has served us wellfor a very long time, but it suffers from a fewlong-standingproblems, related toEmacs limitations baked into its design. The introduction of built-in supportfor Tree-sitter in Emacs 29 presents a natural opportunity to address many ofthem. Enterclojure-ts-mode, which makes use of TreeSitter to provide:
- fast, accurate and more granular font-locking
- fast indentation
- common Emacs functionality like structured navigation,
imenu(an outline of a source buffer), current form inference (used internally by various Emacs modes and utilities), etc
Working with TreeSitter is significantly easier than the legacy Emacs APIs for font-locking andindentation, which makes it easier to contribute toclojure-ts-mode, and to improve it in general.
Keep in mind that the transition toclojure-ts-mode won't happen overnight for several reasons:
- getting to feature parity with
clojure-modewill take some time - tools that depend on
clojure-modewill need to be updated to work withclojure-ts-mode - we still need to support users of older Emacs versions that don't support Tree-sitter
That's whyclojure-ts-mode is being developed independently ofclojure-modeand will one day replace it when the time is right. (e.g. 3 major Emacs versiondown the road, so circa Emacs 32)
You can read more about the vision forclojure-ts-modehere.
Warning
This library is still under active development. Breaking changes should be expected.
The currently provided functionality should cover the needs of most Clojure programmers, but youcan expect to encounter some bugs and missing functionality here and there.
Those will be addressed over the time, as more and more people useclojure-ts-mode.
Forclojure-ts-mode to work, you need Emacs 30+ built with TreeSitter support.To check if your Emacs supports TreeSitter run the following (e.g. by usingM-:):
(treesit-available-p)
Additionally, you'll need to have Git and some C compiler (cc) installed and availablein your$PATH (or Emacs'sexec-path), forclojure-ts-mode to be able to install the requiredTreeSitter grammars automatically.
Tip
As the TreeSitter support in Emacs is still fairly new and under active development itself, for optimalresults you should use the latest stable Emacs release or even the development version of Emacs.See the "Caveats" section for more on the subject.
Note
That's the recommended way to installclojure-ts-mode.
If you havegit and a C compiler (cc) available on your system'sPATH,clojure-ts-mode will install thegrammars
clojure-ts-mode is available onMElPA andNonGNU ELPA.It can be installed with:
(package-install'clojure-ts-mode)
Emacs also includespackage-vc-install, so you can run:
(package-vc-install"https://github.com/clojure-emacs/clojure-ts-mode")to install this package from source.
You can install it by cloning the repository and adding it to your load path.
git clone https://github.com/clojure-emacs/clojure-ts-mode.git
(add-to-list'load-path"~/path/to/clojure-ts-mode/")
Once installed, evaluateclojure-ts-mode.el and you should be ready to go.
Note
clojure-ts-mode install the required grammars automatically, so for mostpeople no manual actions will be required.
clojure-ts-mode makes use of two TreeSitter grammars to work properly:
- The Clojure grammar, mentioned earlier
- markdown-inline, whichwill be used for docstrings if available and if
clojure-ts-use-markdown-inlineis enabled.
If you havegit and a C compiler (cc) available on your system'sPATH,clojure-ts-mode will install thegrammars when you first open a Clojure file andclojure-ts-ensure-grammars isset tot (the default).
Ifclojure-ts-mode fails to automatically install the grammar, you have theoption to install it manually, Please, refer to the installation instructions ofeach required grammar and make sure you're install the versions expected. (seeclojure-ts-grammar-recipes for details)
To reinstall or upgrade TreeSitter grammars, you can execute:
M-x clojure-ts-reinstall-grammars
This will install the latest compatible grammars, even if they are alreadyinstalled.
To see a list of available configuration options doM-x customize-group <RET> clojure-ts.
Most configuration changes will require reverting any activeclojure-ts-mode buffers.
By default,clojure-ts-mode assumes command over all buffers and file extensions previously associated withclojure-mode (and derived major modes likeclojurescript-mode). To disable this remapping, set
(setopt clojure-ts-auto-remapnil)You can also use the commandsclojure-ts-activate /clojure-ts-deactivate to interactively change this behavior.
clojure-ts-mode currently supports 2 different indentation strategies:
semantic, the default, which tries to match the indentation ofclojure-modeandcljfmtfixed,a simple indentation strategy outlined by Tonsky in a blog post
Set the varclojure-ts-indent-style to change it.
(setq clojure-ts-indent-style'fixed)
Tip
You can findthis article comparing semantic and fixed indentation useful.
The indentation of special forms and macros with bodies is controlled viaclojure-ts-semantic-indent-rules. Nearly all special forms and built-in macroswith bodies have special indentation settings in clojure-ts-mode, which arealigned with cljfmt indent rules. You can add/alter the indentation settings inyour personal 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:
(setopt clojure-ts-semantic-indent-rules '(("->". ((:block1))) ("->>". ((:block1)))))
This means that the body of the->/->> is after the first argument.
The default set of rules is defined asclojure-ts--semantic-indent-rules-defaults, any rule can be overridden usingcustomization option.
Two types of rules are supported::block and:inner, mirroring those incljfmt. When a rule is defined as:block n,n represents the number ofarguments preceding the body. When a rule is defined as:inner n, each formwithin the expression's body, nestedn levels deep, is indented by twospaces. These rule definitions fully reflect thecljfmt rules.
For example:
dohas a rule((:block 0)).whenhas a rule((:block 1)).defnandfnhave a rule((:inner 0)).letfnhas a rule((:block 1) (:inner 2 0)).
Note thatclojure-ts-semantic-indent-rules should be set using thecustomization interface orsetopt; otherwise, it will not be appliedcorrectly.
Custom indentation rules can be set for individual projects. To achieve this,you need to create a.dir-locals.el file in the project root. The contentshould look like:
((clojure-ts-mode. ((clojure-ts-semantic-indent-rules. (("with-transaction". ((:block1))) ("with-retry". ((:block1))))))))
In order to apply directory-local variables to existing buffers, they must bereverted.
To highlight entire richcomment expression with the comment font face, set
(setq clojure-ts-comment-macro-font-lock-bodyt)
By default this isnil, so that anything within acomment expression ishighlighted like regular clojure code.
Tip
You can customize the exact level of font-locking via the variablestreesit-font-lock-level (the default value is 3) andtreesit-font-lock-features-list. Checkthissectionof the Emacs manual for more details.
By default markdown syntax is highlighted in the docstrings usingmarkdown_inline grammar. To disable this feature set
(setopt clojure-ts-use-markdown-inlinenil)To make forms inside of(comment ...) forms appear as top-level forms for evaluation and navigation, set
(setq clojure-ts-toplevel-inside-comment-formt)
To change the maximal line length used byM-x prog-fill-reindent-defun (alsobound toM-q by default) to reformat docstrings and comments it's possible tocustomizeclojure-ts-fill-paragraph variable (by default set to the value ofEmacs'fill-paragraph value).
Every new line in the docstrings is indented byclojure-ts-docstring-fill-prefix-width number of spaces (set to 2 by defaultwhich matches theclojure-mode settings).
clojure-ts-mode supports various types of definition that can be navigatedusingimenu, such as:
- namespace
- function
- macro
- var
- interface (forms such as
defprotocol,definterfaceanddefmulti) - class (forms such as
deftype,defrecordanddefstruct) - keyword (for example, spec definitions)
If you are migrating toclojure-ts-mode note thatclojure-mode is still required for cider and clj-refactor packages to work properly.
After installing the package do the following.
- Check the value of
clojure-mode-hookand copy all relevant hooks toclojure-ts-mode-hook.
(add-hook'clojure-ts-mode-hook#'cider-mode)(add-hook'clojure-ts-mode-hook#'enable-paredit-mode)(add-hook'clojure-ts-mode-hook#'rainbow-delimiters-mode)(add-hook'clojure-ts-mode-hook#'clj-refactor-mode)
- Update
.dir-locals.elin all of your Clojure projects to activate directory local variables inclojure-ts-mode.
((clojure-mode (cider-clojure-cli-aliases.":test:repl")) (clojure-ts-mode (cider-clojure-cli-aliases.":test:repl")))
As the TreeSitter Emacs APIs are new and keep evolving there are somedifferences in the behavior ofclojure-ts-mode on different Emacs versions.Here are some notable examples:
- On Emacs 29 the parent mode is
prog-mode, but on Emacs 30+ it's bothprog-modeandclojure-mode(this is very helpful when dealing withderived-mode-pchecks) - Navigation by sexp/lists might work differently on Emacs versions lowerthan 31. Starting with version 31, Emacs uses TreeSitter 'things' settings, ifavailable, to rebind some commands.
- The indentation of list elements with metadata is inconsistent with othercollections. This inconsistency stems from the grammar's interpretation ofnearly every definition or function call as a list. Therefore, modifying theindentation for list elements would adversely affect the indentation ofnumerous other forms.
As of version 0.2.x, the most obvious missing feature are the variousrefactoring commands inclojure-mode.
Yes! Preliminary support forclojure-ts-mode was released inCIDER1.14. Note thatclojure-mode is still needed for some APIs that haven't yet been ported toclojure-ts-mode.
For now, when you take care of the keybindings for the CIDER commands you useand ensurecider-mode is enabled forclojure-ts-mode buffers in your config,most functionality should already work:
(add-hook'clojure-ts-mode-hook#'cider-mode)
Check outthis article for more details.
Note
The dynamic indentation feature in CIDER requires clojure-ts-mode 0.3+.Dynamic font-locking currently doesn't work with clojure-ts-mode.
Currently, there is anopen PR adding support for inf-clojure.
Copyright © 2022-2025 Danny Freeman, Bozhidar Batsov andcontributors.
Distributed under the GNU General Public License; typeC-h C-c to view it.
About
The next generation Clojure major mode for Emacs, powered by TreeSitter
Resources
License
Contributing
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.