Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

The next generation Clojure major mode for Emacs, powered by TreeSitter

License

NotificationsYou must be signed in to change notification settings

clojure-emacs/clojure-ts-mode

Repository files navigation

NonGNU ELPAMELPA StableMELPALicense GPL 3CI Status

Clojure Tree-sitter Mode

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.

Rationale

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 Tree-sitter to provide:

  • fast, accurate and more granular font-locking
  • fast indentation
  • common Emacs functionality like structured navigation,imenu (an outline ofa source buffer), current form inference (used internally by various Emacsmodes and utilities), etc

Working with Tree-sitter 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 withclojure-mode will take some time
  • tools that depend onclojure-mode will 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.

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 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.

Installation

Requirements

Forclojure-ts-mode to work, you need Emacs 30+ built with Tree-sitter support.To check if your Emacs supports Tree-sitter 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 requiredTree-sitter grammars automatically.

Tip

As the Tree-sitter 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.

Install clojure-ts-mode

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)

package-vc

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.

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, evaluateclojure-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 mostpeople no manual actions will be required.

clojure-ts-mode makes use of the following Tree-sitter grammars:

  • Theexperimental version Clojure grammar. This version includes a fewimprovements, which potentially will be promoted to a stable release (Seethediscussion). This grammar is required for proper work ofclojure-ts-mode.
  • markdown-inline, which will be used for docstrings if available and ifclojure-ts-use-markdown-inline is enabled.
  • tree-sitter-regex, which will be used for regex literals if available and ifclojure-ts-use-regex-parser is notnil.

clojure-ts-clojurescript-mode can optionally usetree-sitter-javascript grammarto highlight JS syntax injs* forms. This is enabled by default and can beturned off by settingclojure-ts-clojurescript-use-js-parser tonil.

clojure-ts-jank-mode can optionally usetree-sitter-cpp grammar to highlight C++syntax innative/raw forms. This is enabled by default and can be turned off bysettingclojure-ts-jank-use-cpp-parser tonil.

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). macOS users can install the required tools like this:

xcode-select --install

Similarly, Debian/Ubuntu users can do something like:

sudo apt install build-essential

This installs GCC, G++,make, and other essential development tools.

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).

Ifclojure-ts-ensure-grammars is enabled,clojure-ts-mode will try to upgradethe Clojure grammar if it's outdated. This might happen, when you activateclojure-ts-mode for the first time after package update. If grammar waspreviously installed, you might need to restart Emacs, because it has to reloadthe grammar binary.

Upgrading Tree-sitter grammars

To reinstall or upgrade Tree-sitter grammars, you can execute:

M-x clojure-ts-reinstall-grammars

This will install the latest compatible grammars, even if they are alreadyinstalled.

Configuration

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.

Remapping ofclojure-mode buffers

By default,clojure-ts-mode assumes command over all buffers and fileextensions previously associated withclojure-mode (and derived major modeslikeclojurescript-mode). To disable this remapping, set

(setopt clojure-ts-auto-remapnil)

You can also use the commandsclojure-ts-activate /clojure-ts-deactivate tointeractively change this behavior.

Indentation

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

Set the varclojure-ts-indent-style to change it.

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

Tip

You can findthis article comparing semantic and fixed indentation useful.

Customizing semantic indentation

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:

  • do has a rule((:block 0)).
  • when has a rule((:block 1)).
  • defn andfn have a rule((:inner 0)).
  • letfn has 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.

Project-specific indentation

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 be"reverted" (reloaded).

Vertical alignment

You can vertically align sexps withC-c SPC. For instance, typing this comboon 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) by turning onclojure-ts-align-forms-automatically. This way it will happen whenever youselect some code and hitTAB.

Forms that can be aligned vertically are configured via the following variables:

  • clojure-ts-align-reader-conditionals - align reader conditionals as if theywere maps.
  • clojure-ts-align-binding-forms - a customizable list of forms with let-likebindings that can be aligned vertically.
  • clojure-ts-align-cond-forms - a customizable list of forms whose bodyelements can be aligned vertically. These forms respect the block semanticindentation rule (if configured) and align only the body forms, skipping Nspecial arguments.
  • clojure-ts-align-separator - determines whether blank lines prevent verticalalignment.

Font Locking

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

(setopt 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.

Extending font-lock rules

Inclojure-ts-mode it is possible to specify additional defn-like forms thatshould be fontified. For example to highlight the following form from Hiccuplibrary as a function definition:

(defelemfile-upload"Creates a file upload input."  [name]  (input-field"file" namenil))

You can adddefelem toclojure-ts-extra-def-forms list like this:

(add-to-list'clojure-ts-extra-def-forms"defelem")

or set this variable usingsetopt:

(setopt clojure-ts-extra-def-forms '("defelem"))

This setting will highlightdefelem symbol, function name and the docstring.

Important

Settingclojure-ts-extra-def-forms won't change the indentation rule forthese forms. For indentation rules you should useclojure-ts-semantic-indent-rules variable (seesemanticindentation section).

Highlight markdown syntax in docstrings

By default Markdown syntax is highlighted in the docstrings usingmarkdown-inline grammar. To disable this feature use:

(setopt clojure-ts-use-markdown-inlinenil)

Example of Markdown syntax highlighting:

Highlight regular expression syntax

By default syntax inside regex literals is highlighted usingregex grammar. To disablethis feature use:

(setopt clojure-ts-use-regex-parsernil)

Example of regex syntax highlighting:

Navigation and Evaluation

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

(setopt clojure-ts-toplevel-inside-comment-formt)

Fill paragraph

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).

imenu

clojure-ts-mode supports various types of definition that can be navigatedusingimenu, such as:

  • namespace
  • function
  • macro
  • var
  • interface (forms such asdefprotocol,definterface anddefmulti)
  • class (forms such asdeftype,defrecord anddefstruct)
  • keyword (for example, spec definitions)

Integration withoutline-minor-mode

clojure-ts-mode supports two integration variants withoutline-minor-mode. The default variant uses special top-level comments (level1 heading starts with three semicolons, level 2 heading starts with four,etc.). The other variant treats def-like forms (the same forms produced by theimenu command) as outline headings. To use the second option, use thefollowing customization:

(setopt clojure-ts-outline-variant'imenu)

Refactoring support

Threading macros related features

There are a bunch of commands for threading and unwinding threaded Clojure forms:

  • clojure-ts-thread: Thread another form into the surrounding thread. Both->>/some->> and->/some-> variants are supported.
  • clojure-ts-unwind: Unwind a threaded expression. Supports both->>/some->>and->/some->.
  • clojure-ts-thread-first-all: Introduce the thread first macro (->) andrewrite the entire form. With a prefix argument do not thread the last form.
  • clojure-ts-thread-last-all: Introduce the thread last macro and rewrite theentire form. With a prefix argument do not thread the last form.
  • clojure-ts-unwind-all: Fully unwind a threaded expression removing thethreading macro.

Customize threading refactoring behavior

By defaultclojure-ts-thread-first-all andclojure-ts-thread-last-all willthread all nested expressions. For example this expression:

(->map (assoc {}:key"value"):lock)

After executingclojure-ts-thread-last-all will be converted to:

(-> {}    (assoc:key"value")    (->map:lock))

This behavior can be changed by setting:

(setopt clojure-ts-thread-all-but-lastt)

Then the last expression will not be threaded and the result will be:

(-> (assoc {}:key"value")    (->map:lock))

Cycling things

  • clojure-ts-cycle-keyword-string: Convert the string at point to a keyword andvice versa.
  • clojure-ts-cycle-privacy: Cycle privacy ofdefs ordefns. Use metadataexplicitly with settingclojure-ts-use-metadata-for-defn-privacy tot fordefns too.
  • clojure-ts-cycle-conditional: Change a surrounding conditional form to itsnegated counterpart, or vice versa (supportsif/if-not andwhen/when-not). Forif/if-not also transposes the else and thenbranches, keeping the semantics the same as before.
  • clojure-ts-cycle-not: Add or remove anot form around the current form.

Convert collection

Convert any given collection at point to list, quoted list, map, vector orset. The following commands are available:

  • clojure-ts-convert-collection-to-list
  • clojure-ts-convert-collection-to-quoted-list
  • clojure-ts-convert-collection-to-map
  • clojure-ts-convert-collection-to-vector
  • clojure-ts-convert-collection-to-set

Add arity to a function or macro

clojure-ts-add-arity: Add a new arity to an existing single-arity ormulti-arity function or macro. Function can be defined usingdefn,fn ordefmethod form. This command also supports functions defined inside forms likeletfn,defprotol,reify,extend-protocol orproxy.

Default keybindings

KeybindingCommand
C-:clojure-ts-cycle-keyword-string
C-c SPCclojure-ts-align
C-c C-r t /C-c C-r C-tclojure-ts-thread
C-c C-r u /C-c C-r C-uclojure-ts-unwind
C-c C-r f /C-c C-r C-fclojure-ts-thread-first-all
C-c C-r l /C-c C-r C-lclojure-ts-thread-last-all
C-c C-r p /C-c C-r C-pclojure-ts-cycle-privacy
C-c C-r ( /C-c C-r C-(clojure-ts-convert-collection-to-list
C-c C-r ' /C-c C-r C-'clojure-ts-convert-collection-to-quoted-list
C-c C-r { /C-c C-r C-{clojure-ts-convert-collection-to-map
C-c C-r [ /C-c C-r C-[clojure-ts-convert-collection-to-vector
C-c C-r # /C-c C-r C-#clojure-ts-convert-collection-to-set
C-c C-r c /C-c C-r C-cclojure-ts-cycle-conditional
C-c C-r o /C-c C-r C-oclojure-ts-cycle-not
C-c C-r a /C-c C-r C-aclojure-ts-add-arity

Customize refactoring commands prefix

By default prefix for all refactoring commands isC-c C-r. It can be changedby customizingclojure-ts-refactor-map-prefix variable.

Code completion

clojure-ts-mode provides basic code completion functionality. Completion onlyworks for the current source buffer and includes completion of top-leveldefinitions and local bindings. This feature can be turned off by setting:

(setopt clojure-ts-completion-enablednil)

Here's the short video illustrating the feature with Emacs's built-in completion UI (itshould also work well with more advanced packages likecompany andcorfu):

completion.mp4

Migrating to clojure-ts-mode

If you are migrating toclojure-ts-mode note thatclojure-mode is stillrequired for CIDER andclj-refactor packages to work properly.

After installing the package do the following:

  • Check the value ofclojure-mode-hook and 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.el in all of your Clojure projects to activate directorylocal variables inclojure-ts-mode.
((clojure-mode  (cider-clojure-cli-aliases.":test:repl")) (clojure-ts-mode  (cider-clojure-cli-aliases.":test:repl")))

Caveats

As the Tree-sitter 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 isprog-mode, but on Emacs 30+ it's bothprog-modeandclojure-mode (this is very helpful when dealing withderived-mode-p checks)
  • Navigation by sexp/lists might work differently on Emacs versions lowerthan 31. Starting with version 31, Emacs uses Tree-sitter 'things' settings, ifavailable, to rebind some commands.
  • If you setclojure-ts-extra-def-forms,clojure-ts-mode will highlight thespecified forms, including their docstrings, in a manner similar to Clojure'sdefn. However, Markdown syntax will not be highlighted within these customdocstrings.

Frequently Asked Questions

Whatclojure-mode features are currently missing?

As of version 0.5.x,clojure-ts-mode provides almost allclojure-mode features.Currently only a few refactoring commands are missing.

Doesclojure-ts-mode work with CIDER?

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+.

Doesclojure-ts-mode work withinf-clojure?

Yes, it does.inf-clojure 3.3+ supportsclojure-ts-mode.

Why doesclojure-ts-mode require Emacs 30?

You might be wondering why doesclojure-ts-mode require Emacs 30 instead ofEmacs 29, which introduced the built-in Tree-sitter support. The answer issimple - the initial Tree-sitter support in Emacs 29 had quite a few issues andwe felt it's better to nudge most people interested in using it to Emacs 30,which fixed a lot of the problems.

Contributing

We welcome contributions of any kind!

If you're not familiar with Tree-sitter, a good place to start is ourdesign documentation, which explains how Tree-sitterworks in Emacs in broad strokes and covers some of the designdecisions we've made a long the way.

We're usingEldev as our build tool, so you'llhave to install it. We also provide a simpleMakefile with targets invoking Eldev. Youonly need to know a couple of them:

make lintmaketest

The process of releasing a new version ofclojure-ts-mode is documentedhere.

License

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

Stars

Watchers

Forks

Packages

No packages published

Contributors42


[8]ページ先頭

©2009-2025 Movatter.jp