NonGNU-devel ELPA - clojure-ts-mode

clojure-ts-mode Atom Feed

Description
Major mode for Clojure code
Latest
clojure-ts-mode-0.2.4snapshot0.20250326.192250.tar (.sig), 2025-Mar-26, 250 KiB
Maintainer
Danny Freeman <danny@dfreeman.email>
Website
http://github.com/clojure-emacs/clojure-ts-mode
Browse ELPA's repository
CGit or Gitweb
Badge

To install this package from Emacs, use package-install or list-packages.

Full description

NonGNU ELPA MELPA Stable MELPA License GPL 3 Lint Status

Clojure Tree-Sitter Mode

clojure-ts-mode is an Emacs major mode that provides font-lock (syntax highlighting), indentation, and navigation support for the Clojure(Script) programming language, powered by the tree-sitter-clojure tree-sitter grammar.

Rationale

clojure-mode has served us well for a very long time, but it suffers from a few long-standing problems, related to Emacs limitations baked into its design. The introduction of built-in support for Tree-sitter in Emacs 29 presents a natural opportunity to address many of them. Enter clojure-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 and indentation, which makes it easier to contribute to clojure-ts-mode, and to improve it in general.

Keep in mind that the transition to clojure-ts-mode won't happen overnight for several reasons:

  • getting to feature parity with clojure-mode will take some time
  • tools that depend on clojure-mode will need to be updated to work with clojure-ts-mode
  • we still need to support users of older Emacs versions that don't support Tree-sitter

That's why clojure-ts-mode is being developed independently of clojure-mode and will one day replace it when the time is right. (e.g. 3 major Emacs version down the road, so circa Emacs 32)

You can read more about the vision for clojure-ts-mode here.

Current Status

[!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 you can expect to encounter some bugs and missing functionality here and there.

Those will be addressed over the time, as more and more people use clojure-ts-mode.

Installation

Requirements

For clojure-ts-mode to work, you need Emacs 30+ built with TreeSitter support. To check if your Emacs supports tree sitter run the following (e.g. by using M-:):

(treesit-available-p)

Additionally, you'll need to have Git and some C compiler (cc) installed and available in your $PATH (or Emacs's exec-path), for clojure-ts-mode to be able to install the required TreeSitter grammars automatically.

[!TIP]

As the TreeSitter support in Emacs is still fairly new and under active development itself, for optimal results you should use the latest stable Emacs release or even the development version of Emacs. See the "Caveats" section for more on the subject.

Install clojure-ts-mode

[!NOTE]

That's the recommended way to install clojure-ts-mode.

If you have git and a C compiler (cc) available on your system's PATH, clojure-ts-mode will install the grammars

clojure-ts-mode is available on MElPA and NonGNU ELPA. It can be installed with

(package-install 'clojure-ts-mode)
package-vc

Emacs 29 also includes package-vc-install, so you can run

(package-vc-install "https://github.com/clojure-emacs/clojure-ts-mode")

to install this package from source.

Manual installation

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, evaluate clojure-ts-mode.el and you should be ready to go.

Install tree-sitter grammars

[!NOTE]

clojure-ts-mode install the required grammars automatically, so for most people 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, which will be used for docstrings if available and if clojure-ts-use-markdown-inline is enabled.

If you have git and a C compiler (cc) available on your system's PATH, clojure-ts-mode will install the grammars when you first open a Clojure file and clojure-ts-ensure-grammars is set to t (the default).

If clojure-ts-mode fails to automatically install the grammar, you have the option to install it manually, Please, refer to the installation instructions of each required grammar and make sure you're install the versions expected. (see clojure-ts-grammar-recipes for details)

Configuration

To see a list of available configuration options do M-x customize-group <RET> clojure-ts.

Most configuration changes will require reverting any active clojure-ts-mode buffers.

Remapping of clojure-mode buffers

By default, clojure-ts-mode assumes command over all buffers and file extensions previously associated with clojure-mode (and derived major modes like clojurescript-mode). To disable this remapping, set

(setopt clojure-ts-auto-remap nil)

You can also use the commands clojure-ts-activate / clojure-ts-deactivate to interactively change this behavior.

Indentation

clojure-ts-mode currently supports 2 different indentation strategies:

Set the var clojure-ts-indent-style to change it.

(setq clojure-ts-indent-style 'fixed)

[!TIP]

You can find this article comparing semantic and fixed indentation useful.

Customizing semantic indentation

The indentation of special forms and macros with bodies is controlled via clojure-ts-semantic-indent-rules. Nearly all special forms and built-in macros with bodies have special indentation settings in clojure-ts-mode, which are aligned with cljfmt indent rules. You can add/alter the indentation settings in your 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 '(("->" . (:block 1))
                                           ("->>" . (:block 1))))

This means that the body of the ->/->> is after the first argument.

The default set of rules is defined as clojure-ts--semantic-indent-rules-defaults, any rule can be overridden using customization option.

There are 2 types of rules supported: :block and :inner, similarly to cljfmt. If rule is defined as :block n, n means a number of arguments after which begins the body. If rule is defined as :inner n, each form in the body is indented with 2 spaces regardless of n value (currently all default rules has 0 value).

For example: - do has a rule :block 0. - when has a rule :block 1. - defn and fn have a rule :inner 0.

Font Locking

To highlight entire rich comment expression with the comment font face, set

(setq clojure-ts-comment-macro-font-lock-body t)

By default this is nil, so that anything within a comment expression is highlighted like regular clojure code.

[!TIP]

You can customize the exact level of font-locking via the variables treesit-font-lock-level (the default value is 3) and treesit-font-lock-features-list. Check this section of the Emacs manual for more details.

Highlight markdown syntax in docstrings

By default markdown syntax is highlighted in the docstrings using markdown_inline grammar. To disable this feature set

(setopt clojure-ts-use-markdown-inline nil)
Navigation and Evaluation

To make forms inside of (comment ...) forms appear as top-level forms for evaluation and navigation, set

(setq clojure-ts-toplevel-inside-comment-form t)
Fill paragraph

To change the maximal line length used by M-x prog-fill-reindent-defun (also bound to M-q by default) to reformat docstrings and comments it's possible to customize clojure-ts-fill-paragraph variable (by default set to the value of Emacs' fill-paragraph value).

Every new line in the docstrings is indented by clojure-ts-docstring-fill-prefix-width number of spaces (set to 2 by default which matches the clojure-mode settings).

Migrating to clojure-ts-mode

If you are migrating to clojure-ts-mode note that clojure-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-hook and copy all relevant hooks to clojure-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.el in all of your Clojure projects to activate directory local variables in clojure-ts-mode.
((clojure-mode
  (cider-clojure-cli-aliases . ":test:repl"))
 (clojure-ts-mode
  (cider-clojure-cli-aliases . ":test:repl")))

Caveats

As the TreeSitter Emacs APIs are new and keep evolving there are some differences in the behavior of clojure-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 both prog-mode and clojure-mode (this is very helpful when dealing with derived-mode-p checks)
  • Navigation by sexp/lists might work differently on Emacs versions lower than 31. Starting with version 31, Emacs uses TreeSitter 'things' settings, if available, to rebind some commands.

Frequently Asked Questions

What clojure-mode features are currently missing?

As of version 0.2.x, the most obvious missing feature are the various refactoring commands in clojure-mode.

Does clojure-ts-mode work with CIDER?

Yes! Preliminary support for clojure-ts-mode was released in CIDER 1.14. Make sure to grab the latest CIDER from MELPA/GitHub. Note that clojure-mode is still needed for some APIs that haven't yet been ported to clojure-ts-mode.

For now, when you take care of the keybindings for the CIDER commands you use and ensure cider-mode is enabled for clojure-ts-mode buffers in your config, most functionality should already work:

(add-hook 'clojure-ts-mode-hook #'cider-mode)

Check out this article for more details.

Does clojure-ts-mode work with inf-clojure?

Currently, there is an open PR adding support for inf-clojure.

License

Copyright © 2022-2025 Danny Freeman and contributors.

Distributed under the GNU General Public License; type C-h C-c to view it.

Old versions

clojure-ts-mode-0.2.4snapshot0.20250325.70315.tar.lz2025-Mar-2544.2 KiB
clojure-ts-mode-0.2.4snapshot0.20250310.123844.tar.lz2025-Mar-1044.0 KiB
clojure-ts-mode-0.2.3.0.20250308.183559.tar.lz2025-Mar-0843.9 KiB
clojure-ts-mode-0.2.3.0.20250304.134254.tar.lz2025-Mar-0443.4 KiB
clojure-ts-mode-0.2.2.0.20250303.205551.tar.lz2025-Mar-0343.4 KiB
clojure-ts-mode-0.2.2.0.20250216.85255.tar.lz2025-Feb-1643.3 KiB
clojure-ts-mode-0.2.0.0.20240215.54347.tar.lz2024-Feb-1525.6 KiB
clojure-ts-mode-0.2.0.0.20230924.232019.tar.lz2023-Sep-2524.6 KiB
clojure-ts-mode-0.1.5.0.20230924.94650.tar.lz2023-Sep-2424.3 KiB
clojure-ts-mode-0.1.4.0.20230829.171042.tar.lz2023-Aug-3020.4 KiB

News

Changelog

main (unreleased)

  • #62: Define list "thing" to improve navigation in Emacs 31.
  • [#64]: Add defcustom clojure-ts-auto-remap to control remapping of clojure-mode buffers.
  • Improve syntax highlighting:
    • Highlight metadata with single keyword with clojure-ts-keyword-face.
    • Only highlight built-ins from clojure.core namespace.
    • Highlight named lambda functions properly.
    • Fix syntax highlighting for functions and vars with metadata on the previous line.
  • Improve semantic indentation rules to be more consistent with cljfmt.
  • Introduce clojure-ts-semantic-indent-rules customization option.

0.2.3 (2025-03-04)

  • [#38]: Add support for in-ns forms in clojure-ts-find-ns.
  • [#46]: Fix missing comment-add variable in clojure-ts-mode-variables mentioned in [#26]
  • Add imenu support for deftest definitions.
  • [#53]: Let clojure-ts-mode derive from clojure-mode for Emacs 30+.
  • [#42]: Fix imenu support for definitions with metadata.
  • [#42]: Fix font locking of definitions with metadata.
  • [#42]: Fix indentation of definitions with metadata.
  • [#49]: Fix semantic indentation of quoted functions.
  • [#58]: Add custom fill-paragraph-function which respects docstrings similar to clojure-mode.
  • [#59]: Add customization option to disable markdown syntax highlighting in the docstrings.

0.2.2 (2024-02-16)

  • [#37]: Fix derived modes broken with [#36].

0.2.1 (2024-02-14)

  • [#36]: Rename all derived mode vars to match the package prefix.
    • clojurescript-ts-mode -> clojure-ts-clojurescript-mode
    • clojurec-ts-mode -> clojure-ts-clojurec-mode
    • clojure-dart-ts-mode -> clojure-ts-clojuredart-mode
    • clojure-jank-ts-mode -> clojure-ts-jank-mode
  • [#30]: Add custom option clojure-ts-toplevel-inside-comment-form as an equivalent to clojure-toplevel-inside-comment-form in clojure-mode.
  • [#32]: Change behavior of beginning-of-defun and end-of-defun to consider all Clojure sexps as defuns.

0.2.0