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

Emacs support for the Clojure(Script) programming language

NotificationsYou must be signed in to change notification settings

clojure-emacs/clojure-mode

Repository files navigation

circleciMELPAMELPA StableNonGNU ELPADiscordLicense GPL 3

Clojure Mode

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.

Installation

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

Bundled major modes

Theclojure-mode package actually bundles together several major modes:

  • clojure-mode is a major mode for editing Clojure code
  • clojurescript-mode is a major mode for editing ClojureScript code
  • clojurec-mode is a major mode for editing.cljc source files
  • clojuredart-mode is a major mode for editing ClojureDart.cljd source files
  • jank-mode is a major mode for editing Jank.jank source files
  • joker-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.

Configuration

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.

Indentation options

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.

Indentation of docstrings

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

Indentation of function forms

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.

Indentation of keywords

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)

Indentation of macro forms

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)

Indentation of Comments

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.

Vertical alignment

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.

Font-locking

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.

Refactoring support

The available refactorings were originally created and maintained by theclj-refactor.el team. The ones implemented in Elisp only are gradually migratedtoclojure-mode.

Threading macros related features

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.

Cycling things

clojure-cycle-privacy: Cycle privacy ofdefs ordefns. Use metadataexplicitly with settingclojure-use-metadata-for-privacy tot fordefnstoo.

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 collection

Convert any given collection at point to list, quoted list, map, vector or set.

Let expression

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

Rename ns alias

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.

Add arity to a function

clojure-add-arity: Add a new arity to an existing single-arity or multi-arity function.

Related packages

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

  • EnablingCamelCase 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 enablesmartparens 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 installedRainbowDelimiters 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 withclojure-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.

REPL Interaction

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.

Basic REPL

inf-clojure provides basic interaction with a Clojure REPL process.It's very similar in nature and supported functionality toinferior-lisp-modefor Common Lisp.

CIDER

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

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.

Caveats

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.

General Issues

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.

Indentation Performance

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.

Font-locking Implementation

As mentionedabove, thefont-locking is implemented in terms of regular expressions which makes it bothslow and inaccurate.

Changelog

An extensive changelog is availablehere.

License

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.


[8]ページ先頭

©2009-2025 Movatter.jp