diff --git a/.circleci/config.yml b/.circleci/config.yml
index def610ed..14043b78 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,56 +1,131 @@
version: 2.1
-# Default actions to perform on each Emacs version
-default: &default-steps
- steps:
- - checkout
- - run: apt-get update && apt-get install make
- - run: make elpa
- - run: emacs --version
- - run: make test
- # Make sure to run test-checks before test-bytecomp, as test-bytecomp autogenerates
- # files which won't pass test-checks.
- - run: make test-checks
- - run: make test-bytecomp
+orbs:
+ win: circleci/windows@2.2.0
+
+commands:
+ setup:
+ steps:
+ - checkout
+ - run:
+ name: Install Eldev
+ command: curl -fsSL https://raw.github.com/doublep/eldev/master/webinstall/circle-eldev > x.sh && source ./x.sh
+
+ setup-macos:
+ steps:
+ - checkout
+ - run:
+ name: Install Emacs latest
+ command: |
+ brew install homebrew/cask/emacs
+ - run:
+ name: Install Eldev
+ command: curl -fsSL https://raw.github.com/doublep/eldev/master/webinstall/circle-eldev > x.sh && source ./x.sh
+
+ setup-windows:
+ steps:
+ - checkout
+ - run:
+ name: Install Eldev
+ command: |
+ # Remove expired DST Root CA X3 certificate. Workaround
+ # for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=51038
+ # bug on Emacs 27.2.
+ gci cert:\LocalMachine\Root\DAC9024F54D8F6DF94935FB1732638CA6AD77C13
+ gci cert:\LocalMachine\Root\DAC9024F54D8F6DF94935FB1732638CA6AD77C13 | Remove-Item
+ (iwr https://raw.github.com/doublep/eldev/master/webinstall/circle-eldev.ps1).Content | powershell -command -
+ test:
+ steps:
+ - run:
+ name: Run regression tests
+ command: eldev -dtT -p test
+ lint:
+ steps:
+ - run:
+ name: Lint
+ command: eldev lint -c
+ compile:
+ steps:
+ - run:
+ name: Check for byte-compilation errors
+ command: eldev -dtT compile --warnings-as-errors
-# Enumerated list of Emacs versions
jobs:
- test-emacs-25:
+ test-ubuntu-emacs-26:
docker:
- - image: silex/emacs:25-ci-cask
+ - image: silex/emacs:26-ci
entrypoint: bash
- <<: *default-steps
-
- test-emacs-26:
+ steps:
+ - setup
+ - test
+ - lint
+ - compile
+ test-ubuntu-emacs-27:
docker:
- - image: silex/emacs:26-ci-cask
+ - image: silex/emacs:27-ci
entrypoint: bash
- <<: *default-steps
-
- test-emacs-27:
+ steps:
+ - setup
+ - test
+ - lint
+ - compile
+ test-ubuntu-emacs-28:
docker:
- - image: silex/emacs:27-ci-cask
+ - image: silex/emacs:28-ci
entrypoint: bash
- <<: *default-steps
-
- test-emacs-28:
+ steps:
+ - setup
+ - test
+ - lint
+ - compile
+ test-ubuntu-emacs-29:
docker:
- - image: silex/emacs:28-ci-cask
+ - image: silex/emacs:29-ci
entrypoint: bash
- <<: *default-steps
-
- test-emacs-master:
+ steps:
+ - setup
+ - test
+ - lint
+ - compile
+ test-ubuntu-emacs-master:
docker:
- - image: silex/emacs:master-ci-cask
+ - image: silex/emacs:master-ci
entrypoint: bash
- <<: *default-steps
+ steps:
+ - setup
+ - test
+ - lint
+ - compile
+ test-macos-emacs-latest:
+ macos:
+ xcode: "14.2.0"
+ steps:
+ - setup-macos
+ - test
+ - lint
+ - compile
+ test-windows-emacs-latest:
+ executor: win/default
+ steps:
+ - run:
+ name: Install Emacs latest
+ command: |
+ choco install emacs -y
+ - setup-windows
+ - test
+ - lint
+ - compile
workflows:
- version: 2
+ version: 2.1
ci-test-matrix:
jobs:
- - test-emacs-25
- - test-emacs-26
- - test-emacs-27
- - test-emacs-28
- - test-emacs-master
+ - test-ubuntu-emacs-26
+ - test-ubuntu-emacs-27
+ - test-ubuntu-emacs-28
+ - test-ubuntu-emacs-29
+ - test-ubuntu-emacs-master
+ - test-windows-emacs-latest
+ - test-macos-emacs-latest:
+ requires:
+ - test-ubuntu-emacs-29
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 24e86434..718dd0d1 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -2,7 +2,5 @@
github: bbatsov
patreon: bbatsov
-ko_fi: bbatsov
open_collective: cider
-liberapay: bbatsov
custom: https://www.paypal.me/bbatsov
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE/bug_report.md
similarity index 88%
rename from .github/ISSUE_TEMPLATE.md
rename to .github/ISSUE_TEMPLATE/bug_report.md
index 421e8683..dcf8bb8e 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -1,3 +1,9 @@
+---
+name: Bug Report
+about: Report an issue with clojure-mode you've discovered.
+labels: [bug]
+---
+
*Use the template below when reporting bugs. Please, make sure that
you're running the latest stable clojure-mode and that the problem you're reporting
hasn't been reported (and potentially fixed) already.*
diff --git a/.gitignore b/.gitignore
index ef07d5a4..360a9941 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,6 @@
elpa*
/clojure-mode-autoloads.el
/clojure-mode-pkg.el
+
+/.eldev
+/Eldev-local
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 95d426e6..51077f9e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,48 @@
## master (unreleased)
+## 5.20.0 (2025-05-27)
+
+### New features
+
+* Add `clojuredart-mode`, `joker-mode` and `jank-mode`, derived from `clojure-mode`.
+
+### Bugs fixed
+
+* [cider#3758](https://github.com/clojure-emacs/cider/issues/3758): Improve regexp for `clojure-find-def` to recognize more complex metadata on vars.
+* [#684](https://github.com/clojure-emacs/clojure-mode/issues/684): Restore `outline-regexp` pattern to permit outline handling of top-level forms.
+* Improve regexp for `clojure-find-def` to recognize `defn-` and other declarations on the form `def...-`.
+
+## 5.19.0 (2024-05-26)
+
+### Bugs fixed
+
+* Fix `clojure-align` when called from `clojure-ts-mode` major mode buffers.
+* [#671](https://github.com/clojure-emacs/clojure-mode/issues/671): Syntax highlighting for digits after the first in `%` args. (e.g. `%10`)
+* [#680](https://github.com/clojure-emacs/clojure-mode/issues/680): Change syntax class of ASCII control characters to punctuation, fixing situations where carriage returns were being interpreted as symbols.
+
+# Changes
+
+* [#675](https://github.com/clojure-emacs/clojure-mode/issues/675): Add `.lpy` to the list of known Clojure file extensions.
+
+## 5.18.1 (2023-11-24)
+
+### Bugs fixed
+
+* [#653](https://github.com/clojure-emacs/clojure-mode/issues/653): Don't highlight vars with colons as keywords.
+
+## 5.18.0 (2023-10-18)
+
+### Changes
+
+* [cider#2903](https://github.com/clojure-emacs/cider/issues/2903): Avoid `No comment syntax is defined` prompts.
+
+## 5.17.1 (2023-09-12)
+
+### Changes
+
+* Declare indentation for the `async` ClojureScript macro.
+
## 5.17.0 (2023-09-11)
### Changes
@@ -10,15 +52,14 @@
### Bugs fixed
-* [#656](https://github.com/clojure-emacs/clojure-mode/issues/656): Fix clojure-find-ns when ns form is preceded by other forms.
-
-* [#593](https://github.com/clojure-emacs/clojure-mode/issues/593): Fix clojure-find-ns when ns form is preceded by whitespace or inside comment form.
+* [#656](https://github.com/clojure-emacs/clojure-mode/issues/656): Fix `clojure-find-ns` when ns form is preceded by other forms.
+* [#593](https://github.com/clojure-emacs/clojure-mode/issues/593): Fix `clojure-find-ns` when ns form is preceded by whitespace or inside comment form.
## 5.16.2 (2023-08-23)
### Changes
-* `clojure-find-ns`: add an option to never raise errors, returning nil instead on unparseable ns forms.
+* `clojure-find-ns`: add an option to never raise errors, returning `nil` instead on unparseable ns forms.
## 5.16.1 (2023-06-26)
@@ -42,7 +83,7 @@
* [#581](https://github.com/clojure-emacs/clojure-mode/issues/581): Fix font locking not working for keywords starting with a number.
* [#377](https://github.com/clojure-emacs/clojure-mode/issues/377): Fix everything starting with the prefix `def` being highlighted as a definition form. Now definition forms are enumerated explicitly in the font-locking code, like all other forms.
-* [#638](https://github.com/clojure-emacs/clojure-mode/pull/638): Fix imenu with Clojure code in string or comment.
+* [#638](https://github.com/clojure-emacs/clojure-mode/pull/638): Fix `imenu` with Clojure code in string or comment.
## 5.15.1 (2022-07-30)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 2743702a..2eada5b9 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -39,8 +39,8 @@ and description in grammatically correct, complete sentences.
## Development setup
1. Fork and clone the repository.
-1. Install [Cask][7].
-1. Run `cask install` in the repository folder.
+1. Install [Eldev][7].
+1. Run `eldev build` in the repository folder.
1. Run tests with `make test`.
**Note:** macOS users should make sure that the `emacs` command resolves the version of Emacs they've installed
@@ -53,5 +53,5 @@ See [this article][8] for more details.
[4]: https://help.github.com/articles/using-pull-requests
[5]: https://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html
[6]: https://github.com/clojure-emacs/clojure-mode/blob/master/CHANGELOG.md
-[7]: https://github.com/cask/cask
+[7]: https://github.com/emacs-eldev/eldev
[8]: https://emacsredux.com/blog/2015/05/09/emacs-on-os-x/
diff --git a/Cask b/Cask
deleted file mode 100644
index abcd75fd..00000000
--- a/Cask
+++ /dev/null
@@ -1,9 +0,0 @@
-(source gnu)
-(source melpa)
-
-(package-file "clojure-mode.el")
-
-(development
- (depends-on "s")
- (depends-on "buttercup")
- (depends-on "paredit"))
diff --git a/Eldev b/Eldev
new file mode 100644
index 00000000..1becee18
--- /dev/null
+++ b/Eldev
@@ -0,0 +1,26 @@
+; -*- mode: emacs-lisp; lexical-binding: t -*-
+
+(eldev-require-version "1.6")
+
+(eldev-use-package-archive 'gnu-elpa)
+(eldev-use-package-archive 'nongnu-elpa)
+(eldev-use-package-archive 'melpa)
+
+(eldev-use-plugin 'autoloads)
+
+(eldev-add-extra-dependencies 'test 'paredit 's 'buttercup)
+
+(setq byte-compile-docstring-max-column 240)
+(setq checkdoc-force-docstrings-flag nil)
+(setq checkdoc-permit-comma-termination-flag t)
+(setq checkdoc--interactive-docstring-flag nil)
+
+(setf eldev-lint-default '(elisp))
+
+(with-eval-after-load 'elisp-lint
+ ;; We will byte-compile with Eldev.
+ (setf elisp-lint-ignored-validators '("package-lint" "fill-column" "byte-compile" "checkdoc")
+ enable-local-variables :safe
+ elisp-lint-indent-specs '((define-clojure-indent . 0))))
+
+(setq eldev-project-main-file "clojure-mode.el")
diff --git a/Makefile b/Makefile
index 27503963..3e613538 100644
--- a/Makefile
+++ b/Makefile
@@ -1,42 +1,17 @@
-CASK = cask
-export EMACS ?= emacs
-EMACSFLAGS =
-
-PKGDIR := $(shell EMACS=$(EMACS) $(CASK) package-directory)
-
-SRCS = $(wildcard *.el)
-OBJS = $(SRCS:.el=.elc)
-
-.PHONY: compile test clean elpa
-
-all: compile
-
-elpa-$(EMACS):
- $(CASK) install
- $(CASK) update
- touch $@
-
-elpa: elpa-$(EMACS)
-
-elpaclean:
- rm -f elpa*
- rm -rf .cask # Clean packages installed for development
-
-compile: elpa
- $(CASK) build
+.PHONY: clean compile lint test all
+.DEFAULT_GOAL := all
clean:
- rm -f $(OBJS) clojure-mode-autoloads.el
+ eldev clean
-test: $(PKGDIR)
- $(CASK) exec buttercup
+lint: clean
+ eldev lint -c
-test-checks:
- $(CASK) exec $(EMACS) --no-site-file --no-site-lisp --batch \
- -l test/test-checks.el ./
+# Checks for byte-compilation warnings.
+compile: clean
+ eldev -dtT compile --warnings-as-errors
-test-bytecomp: $(SRCS:.el=.elc-test)
+test: clean
+ eldev -dtT -p test
-%.elc-test: %.el elpa
- $(CASK) exec $(EMACS) --no-site-file --no-site-lisp --batch \
- -l test/clojure-mode-bytecomp-warnings.el $<
+all: clean compile lint test
diff --git a/README.md b/README.md
index 7042486a..4845bbd3 100644
--- a/README.md
+++ b/README.md
@@ -11,13 +11,13 @@
highlighting), indentation, navigation and refactoring support for the
[Clojure(Script) programming language](https://clojure.org).
------------
-
-**This documentation tracks the `master` branch of `clojure-mode`. Some of
-the features 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.17.0](https://github.com/clojure-emacs/clojure-mode/tree/v5.17.0)) if you need documentation for a
-specific `clojure-mode` release.**
+> [!IMPORTANT]
+>
+> This documentation tracks the `master` branch of `clojure-mode`. Some of the
+> features 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](https://github.com/clojure-emacs/clojure-mode/tree/v5.20.0)) if
+> you need documentation for a specific `clojure-mode` release.
## Installation
@@ -47,9 +47,12 @@ If the installation doesn't work try refreshing the package list:
The `clojure-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
+- `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 from `clojure-mode` and provide more or less the same
functionality. Differences can be found mostly in the font-locking -
@@ -78,6 +81,17 @@ The default indentation rules in `clojure-mode` are derived from the
[community Clojure Style Guide](https://guide.clojure.style).
Please, refer to the guide for the general Clojure indentation rules.
+If you'd like to use the alternative "fixed/tonsky" indentation style you should
+update your configuration accordingly:
+
+``` el
+(setq clojure-indent-style 'always-indent
+ clojure-indent-keyword-style 'always-indent
+ clojure-enable-indent-specs nil)
+```
+
+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 a
@@ -126,8 +140,47 @@ The indentation of function forms is configured by the variable
2)
```
-**Note:** Prior to clojure-mode 5.10, the configuration options for `clojure-indent-style` used to be
-keywords, but now they are symbols. Keywords will still be supported at least until clojure-mode 6.
+> [!NOTE]
+>
+> Prior to clojure-mode 5.10, the configuration options for `clojure-indent-style` used to be
+> keywords, but now they are symbols. Keywords will still be supported at least until clojure-mode 6.
+
+#### Indentation of keywords
+
+Similarly we have the `clojure-indent-keyword-style`, which works in the following way:
+
+- `always-align` (default) - All
+ args are vertically aligned with the first arg in case (A),
+ and vertically aligned with the function name in case (B).
+
+``` clojure
+(:require [foo.bar]
+ [bar.baz])
+(:require
+ [foo.bar]
+ [bar.baz])
+```
+
+- `always-indent` - All args are indented like a macro body.
+
+``` clojure
+(:require [foo.bar]
+ [bar.baz])
+(:x
+ location
+ 0)
+```
+
+- `align-arguments` - Case (A) is indented like `always-align`, and
+ case (B) is indented like a macro body.
+
+``` clojure
+(:require [foo.bar]
+ [bar.baz])
+(:x
+ location
+ 0)
+```
#### Indentation of macro forms
@@ -218,7 +271,13 @@ Setting `clojure-special-arg-indent-factor` to 1, results in:
[my-field])
```
-### Indentation of Comments
+You can completely disable the effect of indentation specs like this:
+
+``` el
+(setq clojure-enable-indent-specs nil)
+```
+
+#### Indentation of Comments
`clojure-mode` differentiates between comments like `;`, `;;`, etc.
By default `clojure-mode` treats `;` as inline comments and *always* indents those.
@@ -231,7 +290,11 @@ You can change this behaviour like this:
You might also want to change `comment-add` to 0 in that way, so that Emacs comment
functions (e.g. `comment-region`) would use `;` by default instead of `;;`.
-**Note:** Check out [this section](https://guide.clojure.style/#comments) of the Clojure style guide to understand better the semantics of the different comment levels and why `clojure-mode` treats them differently by default.
+> [!TIP]
+>
+> Check out [this section](https://guide.clojure.style/#comments) of the Clojure
+> style guide to understand better the semantics of the different comment levels
+> and why `clojure-mode` treats them differently by default.
### Vertical alignment
@@ -258,9 +321,11 @@ happen whenever you select some code and hit `TAB`.
### Font-locking
-`clojure-mode` features static font-locking (syntax highlighting) that you can extend yourself
-if needed. As typical for Emacs, it's based on regular expressions. You can find
-the default font-locking rules in `clojure-font-lock-keywords`. Here's how you can add font-locking for built-in Clojure functions and vars:
+`clojure-mode` features static font-locking (syntax highlighting) that you can
+extend yourself if needed. As typical for Emacs, it's based on regular
+expressions. You can find the default font-locking rules in
+`clojure-font-lock-keywords`. Here's how you can add font-locking for built-in
+Clojure functions and vars:
``` el
(defvar clojure-built-in-vars
@@ -303,9 +368,12 @@ var a symbol resolves to). That's why `clojure-mode`'s font-locking defaults are
conservative and minimalistic.
Precise font-locking requires additional data that can obtained from a running
-REPL (that's how CIDER's [dynamic font-locking](https://docs.cider.mx/cider/config/syntax_highlighting.html) works) or from static code analysis.
+REPL (that's how CIDER's [dynamic
+font-locking](https://docs.cider.mx/cider/config/syntax_highlighting.html)
+works) or from static code analysis.
-When it comes to non built-in definitions, `clojure-mode` needs to be manually instructed how to handle the docstrings and highlighting. Here's an example:
+When it comes to non built-in definitions, `clojure-mode` needs to be manually
+instructed how to handle the docstrings and highlighting. Here's an example:
``` emacs-lisp
(put '>defn 'clojure-doc-string-elt 2)
@@ -316,7 +384,9 @@ When it comes to non built-in definitions, `clojure-mode` needs to be manually i
1 font-lock-keyword-face)))
```
-**Note:** The `clojure-doc-string-elt` attribute is processed by the function `clojure-font-lock-syntactic-face-function`.
+> [!NOTE]
+>
+> The `clojure-doc-string-elt` attribute is processed by the function `clojure-font-lock-syntactic-face-function`.
## Refactoring support
@@ -424,7 +494,7 @@ without affecting the namespace declaration.
## Related packages
-* [clojure-mode-extra-font-locking][] provides additional font-locking
+- [clojure-mode-extra-font-locking][] provides additional font-locking
for built-in methods and macros. The font-locking is pretty
imprecise, because it doesn't take namespaces into account and it
won't font-lock a function at all possible positions in a sexp, but
@@ -445,9 +515,9 @@ plenty of incorrect font-locking. CIDER users should avoid this package,
as CIDER does its own dynamic font-locking, which is namespace-aware
and doesn't produce almost any false positives.
-* [clj-refactor][] provides refactoring support.
+- [clj-refactor][] provides additional refactoring support.
-* Enabling `CamelCase` support for editing commands(like
+- Enabling `CamelCase` support for editing commands (like
`forward-word`, `backward-word`, etc) in `clojure-mode` is quite
useful since we often have to deal with Java class and method
names. The built-in Emacs minor mode `subword-mode` provides such
@@ -457,7 +527,7 @@ functionality:
(add-hook 'clojure-mode-hook #'subword-mode)
```
-* The use of [paredit][] when editing Clojure (or any other Lisp) code
+- The use of [paredit][] when editing Clojure (or any other Lisp) code
is highly recommended. It helps ensure the structure of your forms is
not compromised and offers a number of operations that work on code
structure at a higher level than just characters and words. To enable
@@ -467,7 +537,7 @@ it for Clojure buffers:
(add-hook 'clojure-mode-hook #'paredit-mode)
```
-* [smartparens][] is an excellent
+- [smartparens][] is an excellent
(newer) alternative to paredit. Many Clojure hackers have adopted it
recently and you might want to give it a try as well. To enable
`smartparens` use the following code:
@@ -476,7 +546,7 @@ it for Clojure buffers:
(add-hook 'clojure-mode-hook #'smartparens-strict-mode)
```
-* [RainbowDelimiters][] is a
+- [RainbowDelimiters][] is a
minor mode which highlights parentheses, brackets, and braces
according to their depth. Each successive level is highlighted in a
different color. This makes it easy to spot matching delimiters,
@@ -488,7 +558,7 @@ it for Clojure buffers:
(add-hook 'clojure-mode-hook #'rainbow-delimiters-mode)
```
-* [aggressive-indent-mode][] automatically adjust the indentation of your code,
+- [aggressive-indent-mode][] automatically adjust the indentation of your code,
while you're writing it. Using it together with `clojure-mode` is highly
recommended. Provided you've already installed `aggressive-indent-mode` you can
enable it like this:
@@ -497,6 +567,9 @@ enable it like this:
(add-hook 'clojure-mode-hook #'aggressive-indent-mode)
```
+Note that it might cause performance issues if you're dealing with large
+Clojure source files.
+
## REPL Interaction
One of the fundamental aspects of Lisps in general, and Clojure in
@@ -540,22 +613,30 @@ experience negatively.
### General Issues
-`clojure-mode` derives a lot of functionality directly from `lisp-mode` (an Emacs major mode for Common Lisp), which
-simplified the initial implementation, but also made it harder to implement
-certain functionality. Down the road it'd be nice to fully decouple `clojure-mode`
-from `lisp-mode`.
+`clojure-mode` derives a lot of functionality directly from `lisp-mode` (an
+Emacs major mode for Common Lisp), which simplified the initial implementation,
+but also made it harder to implement certain functionality. Down the road it'd
+be nice to fully decouple `clojure-mode` from `lisp-mode`.
See [this ticket](https://github.com/clojure-emacs/clojure-mode/issues/270) for a bit more details.
### Indentation Performance
-`clojure-mode`'s indentation engine is a bit slow. You can speed things up significantly by disabling `clojure-use-backtracking-indent`, but this will break the indentation of complex forms like `deftype`, `defprotocol`, `reify`, `letfn`, etc.
+`clojure-mode`'s indentation engine is a bit slow. You can speed things up
+significantly by disabling `clojure-use-backtracking-indent`, but this will
+break the indentation of complex forms like `deftype`, `defprotocol`, `reify`,
+`letfn`, etc.
-We should look into ways to optimize the performance of the backtracking indentation logic. See [this ticket](https://github.com/clojure-emacs/clojure-mode/issues/606) for more details.
+We should look into ways to optimize the performance of the backtracking
+indentation logic. See [this ticket](https://github.com/clojure-emacs/clojure-mode/issues/606) for more
+details.
### Font-locking Implementation
-As mentioned [above](https://github.com/clojure-emacs/clojure-mode#font-locking), the font-locking is implemented in terms of regular expressions which makes it both slow and inaccurate.
+As mentioned
+[above](https://github.com/clojure-emacs/clojure-mode#font-locking), the
+font-locking is implemented in terms of regular expressions which makes it both
+slow and inaccurate.
## Changelog
@@ -563,7 +644,7 @@ An extensive changelog is available [here](CHANGELOG.md).
## License
-Copyright © 2007-2023 Jeffrey Chu, Lennart Staflin, Phil Hagelberg, Bozhidar
+Copyright © 2007-2025 Jeffrey Chu, Lennart Staflin, Phil Hagelberg, Bozhidar
Batsov, Artur Malabarba, Magnar Sveen and [contributors][].
Distributed under the GNU General Public License; type C-h C-c to view it.
diff --git a/clojure-mode.el b/clojure-mode.el
index 8e0780a1..c3d950ce 100644
--- a/clojure-mode.el
+++ b/clojure-mode.el
@@ -1,7 +1,7 @@
;;; clojure-mode.el --- Major mode for Clojure code -*- lexical-binding: t; -*-
;; Copyright © 2007-2013 Jeffrey Chu, Lennart Staflin, Phil Hagelberg
-;; Copyright © 2013-2023 Bozhidar Batsov, Artur Malabarba, Magnar Sveen
+;; Copyright © 2013-2025 Bozhidar Batsov, Artur Malabarba, Magnar Sveen
;;
;; Authors: Jeffrey Chu
;; Lennart Staflin
@@ -12,7 +12,7 @@
;; Maintainer: Bozhidar Batsov
;; URL: https://github.com/clojure-emacs/clojure-mode
;; Keywords: languages clojure clojurescript lisp
-;; Version: 5.17.0
+;; Version: 5.20.0
;; Package-Requires: ((emacs "25.1"))
;; This file is not part of GNU Emacs.
@@ -100,6 +100,8 @@
(defcustom clojure-indent-style 'always-align
"Indentation style to use for function forms and macro forms.
+For forms that start with a keyword see `clojure-indent-keyword-style'.
+
There are two cases of interest configured by this variable.
- Case (A) is when at least one function argument is on the same
@@ -147,6 +149,50 @@ to indent function forms.
align-arguments))
:package-version '(clojure-mode . "5.2.0"))
+(defcustom clojure-indent-keyword-style 'always-align
+ "Indentation style to use for forms that start with a keyword.
+For function/macro forms, see `clojure-indent-style'.
+There are two cases of interest configured by this variable.
+
+- Case (A) is when at least one argument following the keyword is
+ on the same line as the keyword.
+- Case (B) is the opposite (no arguments are on the same line as
+ the keyword).
+
+The possible values for this variable are keywords indicating how
+to indent keyword invocation forms.
+
+ `always-align' - Follow the same rules as `lisp-mode'. All
+ args are vertically aligned with the first arg in case (A),
+ and vertically aligned with the function name in case (B).
+ For instance:
+ (: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
+ location
+ 0)
+
+ `align-arguments' - Case (A) is indented like `lisp', and
+ case (B) is indented like a macro body.
+ (:require [foo.bar]
+ [bar.baz])
+ (:x
+ location
+ 0)"
+ :safe #'symbolp
+ :type '(choice (const :tag "Same as `lisp-mode'" always-align)
+ (const :tag "Indent like a macro body" always-indent)
+ (const :tag "Indent like a macro body unless first arg is on the same line"
+ align-arguments))
+ :package-version '(clojure-mode . "5.19.0"))
+
(defcustom clojure-use-backtracking-indent t
"When non-nil, enable context sensitive indentation."
:type 'boolean
@@ -190,6 +236,7 @@ For example, \[ is allowed in :db/id[:db.part/user]."
"shadow-cljs.edn" ; shadow-cljs
"bb.edn" ; babashka
"nbb.edn" ; nbb
+ "basilisp.edn" ; Basilisp (Python)
)
"A list of files, which identify a Clojure project's root.
Out-of-the box `clojure-mode' understands lein, boot, gradle,
@@ -326,7 +373,8 @@ The prefixes are used to generate the correct namespace."
(defvar clojure-mode-syntax-table
(let ((table (make-syntax-table)))
;; Initialize ASCII charset as symbol syntax
- (modify-syntax-entry '(0 . 127) "_" table)
+ ;; Control characters from 0-31 default to the punctuation syntax class
+ (modify-syntax-entry '(32 . 127) "_" table)
;; Word syntax
(modify-syntax-entry '(?0 . ?9) "w" table)
@@ -338,6 +386,7 @@ The prefixes are used to generate the correct namespace."
(modify-syntax-entry ?\xa0 " " table) ; non-breaking space
(modify-syntax-entry ?\t " " table)
(modify-syntax-entry ?\f " " table)
+ (modify-syntax-entry ?\r " " table)
;; Setting commas as whitespace makes functions like `delete-trailing-whitespace' behave unexpectedly (#561)
(modify-syntax-entry ?, "." table)
@@ -493,16 +542,6 @@ ENDP and DELIM."
"\\_<\\(?:'+\\|#\\)")
(line-beginning-position)))))
-(defconst clojure--collection-tag-regexp "#\\(::[a-zA-Z0-9._-]*\\|:?\\([a-zA-Z0-9._-]+/\\)?[a-zA-Z0-9._-]+\\)"
- "Collection reader macro tag regexp.
-It is intended to check for allowed strings that can come before a
-collection literal (e.g. '[]' or '{}'), as reader macro tags.
-This includes #fully.qualified/my-ns[:kw val] and #::my-ns{:kw
-val} as of Clojure 1.9.")
-
-(make-obsolete-variable 'clojure--collection-tag-regexp nil "5.12.0")
-(make-obsolete 'clojure-no-space-after-tag 'clojure-space-for-delimiter-p "5.12.0")
-
(declare-function paredit-open-curly "ext:paredit" t t)
(declare-function paredit-close-curly "ext:paredit" t t)
(declare-function paredit-convolute-sexp "ext:paredit")
@@ -576,7 +615,7 @@ replacement for `cljr-expand-let`."
(add-to-list 'imenu-generic-expression '(nil clojure-match-next-def 0))
(setq-local indent-tabs-mode nil)
(setq-local paragraph-ignore-fill-prefix t)
- (setq-local outline-regexp ";;;;* ")
+ (setq-local outline-regexp ";;;;* \\|(") ; comments and top-level forms
(setq-local outline-level 'lisp-outline-level)
(setq-local comment-start ";")
(setq-local comment-start-skip ";+ *")
@@ -1058,7 +1097,7 @@ any number of matches of `clojure--sym-forbidden-rest-chars'."))
1 'clojure-character-face)
;; lambda arguments - %, %&, %1, %2, etc
;; must come after character literals for \% to be handled properly
- ("\\<%[&1-9]?" (0 font-lock-variable-name-face))
+ ("\\<%[&1-9]*" (0 font-lock-variable-name-face))
;; namespace definitions: (ns foo.bar)
(,(concat "(\\[ \r\n\t]*"
;; Possibly metadata, shorthand and/or longhand
@@ -1072,12 +1111,13 @@ any number of matches of `clojure--sym-forbidden-rest-chars'."))
;; keywords: {:oneword/ve/yCom|pLex.stu-ff 0}
(,(concat "\\(:\\{1,2\\}\\)\\(" clojure--keyword-sym-regexp "?\\)\\(/\\)"
"\\(" clojure--keyword-sym-regexp "\\)")
+ ;; with ns
(1 'clojure-keyword-face)
(2 font-lock-type-face)
- ;; (2 'clojure-keyword-face)
(3 'default)
(4 'clojure-keyword-face))
- (,(concat "\\(:\\{1,2\\}\\)\\(" clojure--keyword-sym-regexp "\\)")
+ (,(concat "\\<\\(:\\{1,2\\}\\)\\(" clojure--keyword-sym-regexp "\\)")
+ ;; without ns
(1 'clojure-keyword-face)
(2 'clojure-keyword-face))
@@ -1232,7 +1272,7 @@ preceeded by a #."
(clojure-string-start nil))))))
(defun clojure-font-lock-escaped-chars (bound)
- "Highlight \escaped chars in strings.
+ "Highlight \\escaped chars in strings.
BOUND denotes a buffer position to limit the search."
(let ((found nil))
(while (and (not found)
@@ -1468,7 +1508,7 @@ When called from lisp code align everything between BEG and END."
(cl-incf count)))
;; Pre-indent the region to avoid aligning to improperly indented
;; contents (#551). Also fixes #360.
- (indent-region (point) sexp-end)
+ (indent-region (point) (marker-position sexp-end))
(dotimes (_ count)
(align-region (point) sexp-end nil
`((clojure-align (regexp . clojure--search-whitespace-after-next-sexp)
@@ -1652,6 +1692,15 @@ accepted by `clojure-indent-style'."
;; Car of form is not a symbol.
(not (looking-at ".\\(?:\\sw\\|\\s_\\)"))))
+(defcustom clojure-enable-indent-specs t
+ "Control whether to honor indent specs.
+They can be either set via metadata on the function/macro, or via
+`define-clojure-indent'. Set this to nil to get uniform
+formatting of all forms."
+ :type 'boolean
+ :safe #'booleanp
+ :package-version '(clojure-mode . "5.19.0"))
+
;; Check the general context, and provide indentation for data structures and
;; special macros. If current form is a function (or non-special macro),
;; delegate indentation to `clojure--normal-indent'.
@@ -1685,7 +1734,8 @@ This function also returns nil meaning don't specify the indentation."
(1+ (current-column))
;; Function or macro call.
(forward-char 1)
- (let ((method (clojure--find-indent-spec))
+ (let ((method (and clojure-enable-indent-specs
+ (clojure--find-indent-spec)))
(last-sexp calculate-lisp-indent-last-sexp)
(containing-form-column (1- (current-column))))
(pcase method
@@ -1722,7 +1772,7 @@ This function also returns nil meaning don't specify the indentation."
(cond
;; Preserve useful alignment of :require (and friends) in `ns' forms.
((and function (string-match "^:" function))
- (clojure--normal-indent last-sexp 'always-align))
+ (clojure--normal-indent last-sexp clojure-indent-keyword-style))
;; This should be identical to the :defn above.
((and function
(string-match "\\`\\(?:\\S +/\\)?\\(def[a-z]*\\|with-\\)"
@@ -1876,6 +1926,7 @@ work). To set it from Lisp code, use
(deftest :defn)
(are 2)
(use-fixtures :defn)
+ (async 1)
;; core.logic
(run :defn)
@@ -2083,7 +2134,7 @@ content) are considered part of the preceding sexp."
(defun clojure-sort-ns ()
"Internally sort each sexp inside the ns form."
(interactive)
- (comment-normalize-vars)
+ (comment-normalize-vars t) ;; `t`: avoid prompts
(if (clojure-find-ns)
(save-excursion
(goto-char (match-beginning 0))
@@ -2205,11 +2256,11 @@ renaming a namespace."
(defconst clojure-def-type-and-name-regex
(concat "(\\(?:\\(?:\\sw\\|\\s_\\)+/\\)?"
;; Declaration
- "\\(def\\(?:\\sw\\|\\s_\\)*\\)\\>"
+ "\\(def\\(?:\\sw\\|\\s_\\)*\\(?:-\\|\\>\\)\\)"
;; Any whitespace
"[ \r\n\t]*"
;; Possibly type or metadata
- "\\(?:#?^\\(?:{[^}]*}\\|\\(?:\\sw\\|\\s_\\)+\\)[ \r\n\t]*\\)*"
+ "\\(?:#?^\\(?:{[^}]*}+\\|\\(?:\\sw\\|\\s_\\)+\\)[ \r\n\t]*\\)*"
;; Symbol name
"\\(\\(?:\\sw\\|\\s_\\)+\\)"))
@@ -2229,7 +2280,7 @@ Returns a list pair, e.g. (\"defn\" \"abc\") or (\"deftest\" \"some-test\")."
(defun clojure--looking-at-non-logical-sexp ()
"Return non-nil if text after point is \"non-logical\" sexp.
\"Non-logical\" sexp are ^metadata and #reader.macros."
- (comment-normalize-vars)
+ (comment-normalize-vars t) ;; `t`: avoid prompts
(comment-forward (point-max))
(looking-at-p "\\(?:#?\\^\\)\\|#:?:?[[:alpha:]]"))
@@ -3128,7 +3179,7 @@ Assumes cursor is at beginning of function."
"Add an arity to a function.
Assumes cursor is at beginning of function."
- (let ((beg-line (what-line))
+ (let ((beg-line (line-number-at-pos))
(end (save-excursion (forward-sexp)
(point))))
(down-list 2)
@@ -3140,7 +3191,7 @@ Assumes cursor is at beginning of function."
(insert "[")
(save-excursion (insert "])\n(")))
((looking-back "\\[" 1) ;; single-arity fn
- (let* ((same-line (string= beg-line (what-line)))
+ (let* ((same-line (= beg-line (line-number-at-pos)))
(new-arity-text (concat (when same-line "\n") "([")))
(save-excursion
(goto-char end)
@@ -3259,12 +3310,33 @@ With universal argument \\[universal-argument], act on the \"top-level\" form."
\\{clojurec-mode-map}")
+;;;###autoload
+(define-derived-mode clojuredart-mode clojure-mode "ClojureDart"
+ "Major mode for editing Clojure Dart code.
+
+\\{clojuredart-mode-map}")
+
+;;;###autoload
+(define-derived-mode jank-mode clojure-mode "Jank"
+ "Major mode for editing Jank code.
+
+\\{jank-mode-map}")
+
+;;;###autoload
+(define-derived-mode joker-mode clojure-mode "Joker"
+ "Major mode for editing Joker code.
+
+\\{joker-mode-map}")
+
;;;###autoload
(progn
(add-to-list 'auto-mode-alist
- '("\\.\\(clj\\|cljd\\|dtm\\|edn\\)\\'" . clojure-mode))
+ '("\\.\\(clj\\|cljd\\|dtm\\|edn\\|lpy\\)\\'" . clojure-mode))
(add-to-list 'auto-mode-alist '("\\.cljc\\'" . clojurec-mode))
(add-to-list 'auto-mode-alist '("\\.cljs\\'" . clojurescript-mode))
+ (add-to-list 'auto-mode-alist '("\\.cljd\\'" . clojuredart-mode))
+ (add-to-list 'auto-mode-alist '("\\.jank\\'" . jank-mode))
+ (add-to-list 'auto-mode-alist '("\\.joke\\'" . joker-mode))
;; boot build scripts are Clojure source files
(add-to-list 'auto-mode-alist '("\\(?:build\\|profile\\)\\.boot\\'" . clojure-mode))
;; babashka scripts are Clojure source files
diff --git a/test/clojure-mode-bytecomp-warnings.el b/test/clojure-mode-bytecomp-warnings.el
deleted file mode 100644
index 41b3230d..00000000
--- a/test/clojure-mode-bytecomp-warnings.el
+++ /dev/null
@@ -1,40 +0,0 @@
-;;; clojure-mode-bytecomp-warnings.el --- Check for byte-compilation problems -*- lexical-binding: t; -*-
-
-;; Copyright © 2012-2021 Bozhidar Batsov and contributors
-;;
-;; This program is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see .
-
-;; This file is not part of GNU Emacs.
-
-;;; Commentary:
-
-;; This is a script to be loaded while visiting a `clojure-mode' source file.
-;; It will prepare all requirements and then byte-compile the file and signal an
-;; error on any warning. For example:
-;;
-;; emacs -Q --batch -l test/clojure-mode-bytecomp-warnings.el clojure-mode.el
-
-;; This assumes that all `clojure-mode' dependencies are already on the package
-;; dir (probably from running `cask install').
-
-(setq load-prefer-newer t)
-(add-to-list 'load-path (expand-file-name "./"))
-(require 'package)
-(package-generate-autoloads 'clojure-mode default-directory)
-(package-initialize)
-(load-file "clojure-mode-autoloads.el")
-(setq byte-compile-error-on-warn t)
-(batch-byte-compile)
-
-;;; clojure-mode-bytecomp-warnings.el ends here
diff --git a/test/clojure-mode-convert-collection-test.el b/test/clojure-mode-convert-collection-test.el
index 28c5977e..14e52915 100644
--- a/test/clojure-mode-convert-collection-test.el
+++ b/test/clojure-mode-convert-collection-test.el
@@ -27,6 +27,7 @@
(require 'clojure-mode)
(require 'buttercup)
+(require 'test-helper "test/utils/test-helper")
(describe "clojure-convert-collection-to-map"
(when-refactoring-it "should convert a list to a map"
diff --git a/test/clojure-mode-font-lock-test.el b/test/clojure-mode-font-lock-test.el
index bb6ef74d..34771905 100644
--- a/test/clojure-mode-font-lock-test.el
+++ b/test/clojure-mode-font-lock-test.el
@@ -1,5 +1,4 @@
-;;; clojure-mode-font-lock-test.el --- Clojure Mode: Font lock test suite
-;; -*- lexical-binding: t; -*-
+;;; clojure-mode-font-lock-test.el --- Clojure Mode: Font lock test suite -*- lexical-binding: t; -*-
;; Copyright (C) 2014-2021 Bozhidar Batsov
@@ -262,6 +261,13 @@ DESCRIPTION is the description of the spec."
(9 10 nil)
(11 16 nil))
+ ("(colons:are:okay)"
+ (2 16 nil))
+
+ ("(some-ns/colons:are:okay)"
+ (2 8 font-lock-type-face)
+ (9 24 nil))
+
("(oneword/ve/yCom|pLex.stu-ff)"
(2 8 font-lock-type-face)
(9 10 nil)
@@ -715,6 +721,19 @@ DESCRIPTION is the description of the spec."
(10 10 default)
(11 30 clojure-keyword-face)))
+ (when-fontifying-it "should handle keywords with colons"
+ (":a:a"
+ (1 4 clojure-keyword-face))
+
+ (":a:a/:a"
+ (1 7 clojure-keyword-face))
+
+ ("::a:a"
+ (1 5 clojure-keyword-face))
+
+ ("::a.a:a"
+ (1 7 clojure-keyword-face)))
+
(when-fontifying-it "should handle very complex keywords"
(" :ve/yCom|pLex.stu-ff"
(3 4 font-lock-type-face)
@@ -824,7 +843,10 @@ DESCRIPTION is the description of the spec."
(when-fontifying-it "should handle variables defined with def"
("(def foo 10)"
(2 4 font-lock-keyword-face)
- (6 8 font-lock-variable-name-face)))
+ (6 8 font-lock-variable-name-face))
+ ("(def foo:bar 10)"
+ (2 4 font-lock-keyword-face)
+ (6 12 font-lock-variable-name-face)))
(when-fontifying-it "should handle variables definitions of type string"
("(def foo \"hello\")"
@@ -878,13 +900,24 @@ DESCRIPTION is the description of the spec."
(2 3 font-lock-keyword-face)
( 5 7 font-lock-function-name-face)))
- (when-fontifying-it "should handle lambda-params"
+ (when-fontifying-it "should handle lambda-params %, %1, %n..."
("#(+ % %2 %3 %&)"
(5 5 font-lock-variable-name-face)
(7 8 font-lock-variable-name-face)
(10 11 font-lock-variable-name-face)
(13 14 font-lock-variable-name-face)))
+ (when-fontifying-it "should handle multi-digit lambda-params"
+ ;; % args with >1 digit are rare and unidiomatic but legal up to
+ ;; `MAX_POSITIONAL_ARITY` in Clojure's compiler, which as of today is 20
+ ("#(* %10 %15 %19 %20)"
+ ;; it would be better if this were just `font-lock-variable-name-face` but
+ ;; it seems to work as-is
+ (5 7 various-faces)
+ (9 11 font-lock-variable-name-face)
+ (13 15 font-lock-variable-name-face)
+ (17 19 various-faces)))
+
(when-fontifying-it "should handle nils"
("(= nil x)"
(4 6 font-lock-constant-face))
diff --git a/test/clojure-mode-refactor-add-arity-test.el b/test/clojure-mode-refactor-add-arity-test.el
index 9c75f128..5f1c5fb9 100644
--- a/test/clojure-mode-refactor-add-arity-test.el
+++ b/test/clojure-mode-refactor-add-arity-test.el
@@ -24,6 +24,7 @@
(require 'clojure-mode)
(require 'buttercup)
+(require 'test-helper "test/utils/test-helper")
(describe "clojure-add-arity"
diff --git a/test/clojure-mode-util-test.el b/test/clojure-mode-util-test.el
index 565773d4..d905fc70 100644
--- a/test/clojure-mode-util-test.el
+++ b/test/clojure-mode-util-test.el
@@ -46,7 +46,7 @@
(bb-edn-src (expand-file-name "src" temp-dir)))
(write-region "{}" nil bb-edn)
(make-directory bb-edn-src)
- (expect (clojure-project-dir bb-edn-src)
+ (expect (expand-file-name (clojure-project-dir bb-edn-src))
:to-equal (file-name-as-directory temp-dir))))))
(describe "clojure-project-relative-path"
@@ -163,6 +163,11 @@
(with-clojure-buffer "(ns)(ns foo)"
(expect (clojure-find-ns) :to-equal "foo"))
(with-clojure-buffer "(ns )(ns foo)"
+ (expect (clojure-find-ns) :to-equal "foo")))
+ (it "should ignore carriage returns"
+ (with-clojure-buffer "(ns \r\n foo)"
+ (expect (clojure-find-ns) :to-equal "foo"))
+ (with-clojure-buffer "(ns\r\n ^{:doc \"meta\r\n\"}\r\n foo\r\n)"
(expect (clojure-find-ns) :to-equal "foo"))))
(describe "clojure-sort-ns"
@@ -326,6 +331,104 @@
{:nested (in|c x)})"
(clojure-toggle-ignore-defun)))
+(describe "clojure-find-def"
+ (it "should recognize def and defn"
+ (with-clojure-buffer-point
+ "(def foo 1)|
+ (defn bar [x y z] z)"
+ (expect (clojure-find-def) :to-equal '("def" "foo")))
+ (with-clojure-buffer-point
+ "(def foo 1)
+ (defn bar |[x y z] z)"
+ (expect (clojure-find-def) :to-equal '("defn" "bar")))
+ (with-clojure-buffer-point
+ "(def foo 1)
+ (defn ^:private bar |[x y z] z)"
+ (expect (clojure-find-def) :to-equal '("defn" "bar")))
+ (with-clojure-buffer-point
+ "(defn |^{:doc \"A function\"} foo [] 1)
+ (defn ^:private bar 2)"
+ (expect (clojure-find-def) :to-equal '("defn" "foo"))))
+ (it "should recognize deftest, with or without metadata added to the var"
+ (with-clojure-buffer-point
+ "|(deftest ^{:a 1} simple-metadata)
+ (deftest ^{:a {}} complex-metadata)
+ (deftest no-metadata)"
+ (expect (clojure-find-def) :to-equal '("deftest" "simple-metadata")))
+ (with-clojure-buffer-point
+ "(deftest ^{:a 1} |simple-metadata)
+ (deftest ^{:a {}} complex-metadata)
+ (deftest no-metadata)"
+ (expect (clojure-find-def) :to-equal '("deftest" "simple-metadata")))
+ (with-clojure-buffer-point
+ "(deftest ^{:a 1} simple-metadata)
+ (deftest ^{:a {}} |complex-metadata)
+ (deftest no-metadata)"
+ (expect (clojure-find-def) :to-equal '("deftest" "complex-metadata")))
+ (with-clojure-buffer-point
+ "(deftest ^{:a 1} simple-metadata)
+ (deftest ^{:|a {}} complex-metadata)
+ (deftest no-metadata)"
+ (expect (clojure-find-def) :to-equal '("deftest" "complex-metadata")))
+ (with-clojure-buffer-point
+ "(deftest ^{:a 1} simple-metadata)
+ (deftest ^{:a {}} complex-metadata)
+ (deftest |no-metadata)"
+ (expect (clojure-find-def) :to-equal '("deftest" "no-metadata"))))
+ (it "should recognize defn-, with or without metadata"
+ (with-clojure-buffer-point
+ "(def foo 1)
+ (defn- bar |[x y z] z)
+ (def bar 2)"
+ (expect (clojure-find-def) :to-equal '("defn-" "bar")))
+ (with-clojure-buffer-point
+ "(def foo 1)
+ (defn- ^:private bar |[x y z] z)"
+ (expect (clojure-find-def) :to-equal '("defn-" "bar")))
+ (with-clojure-buffer-point
+ "(defn- |^{:doc \"A function\"} foo [] 1)
+ (defn- ^:private bar 2)"
+ (expect (clojure-find-def) :to-equal '("defn-" "foo")))
+ (with-clojure-buffer-point
+ "(def foo 1)
+ (defn- ^{:|a {}} complex-metadata |[x y z] z)
+ (def bar 2)"
+ (expect (clojure-find-def) :to-equal '("defn-" "complex-metadata"))))
+ (it "should recognize def...-, with or without metadata"
+ (with-clojure-buffer-point
+ "(def foo 1)
+ (def- bar| 5)
+ (def baz 2)"
+ (expect (clojure-find-def) :to-equal '("def-" "bar")))
+ (with-clojure-buffer-point
+ "(def foo 1)
+ (deftest- bar |[x y z] z)
+ (def baz 2)"
+ (expect (clojure-find-def) :to-equal '("deftest-" "bar")))
+ (with-clojure-buffer-point
+ "(def foo 1)
+ (defxyz- bar| 5)
+ (def baz 2)"
+ (expect (clojure-find-def) :to-equal '("defxyz-" "bar")))
+ (with-clojure-buffer-point
+ "(def foo 1)
+ (defn-n- bar| [x y z] z)
+ (def baz 2)"
+ (expect (clojure-find-def) :to-equal '("defn-n-" "bar")))
+ (with-clojure-buffer-point
+ "(def foo 1)
+ (defn-n- ^:private bar |[x y z] z)"
+ (expect (clojure-find-def) :to-equal '("defn-n-" "bar")))
+ (with-clojure-buffer-point
+ "(def-n- |^{:doc \"A function\"} foo [] 1)
+ (def- ^:private bar 2)"
+ (expect (clojure-find-def) :to-equal '("def-n-" "foo")))
+ (with-clojure-buffer-point
+ "(def foo 1)
+ (defn-n- ^{:|a {}} complex-metadata |[x y z] z)
+ (def bar 2)"
+ (expect (clojure-find-def) :to-equal '("defn-n-" "complex-metadata")))))
+
(provide 'clojure-mode-util-test)
;;; clojure-mode-util-test.el ends here
diff --git a/test/test-checks.el b/test/test-checks.el
deleted file mode 100644
index a4b4208f..00000000
--- a/test/test-checks.el
+++ /dev/null
@@ -1,30 +0,0 @@
-;; This is a script to be loaded from the root `clojure-mode' directory. It will -*- lexical-binding: t; -*-
-;; prepare all requirements and then run `check-declare-directory' on
-;; `default-directory'. For example: emacs -Q --batch -l test/test-checkdoc.el
-
-;; This assumes that all `clojure-mode' dependencies are already on the package
-;; dir (probably from running `cask install').
-
-(add-to-list 'load-path (expand-file-name "./"))
-(require 'package)
-(require 'check-declare)
-(package-initialize)
-
-;; disable some annoying (or non-applicable) checkdoc checks
-(setq checkdoc-package-keywords-flag nil)
-(setq checkdoc-arguments-in-order-flag nil)
-(setq checkdoc-verb-check-experimental-flag nil)
-
-(let ((files (directory-files default-directory t
- "\\`[^.].*\\.el\\'" t)))
-
- ;; `checkdoc-file' was introduced in Emacs 25
- (when (fboundp 'checkdoc-file)
- (dolist (file files)
- (checkdoc-file file))
- (when (get-buffer "*Warnings*")
- (message "Failing due to checkdoc warnings...")
- (kill-emacs 1)))
-
- (when (apply #'check-declare-files files)
- (kill-emacs 1)))
diff --git a/test/utils/test-helper.el b/test/utils/test-helper.el
index b359277c..af5273a2 100644
--- a/test/utils/test-helper.el
+++ b/test/utils/test-helper.el
@@ -25,13 +25,6 @@
(message "Running tests on Emacs %s" emacs-version)
-(let* ((current-file (if load-in-progress load-file-name (buffer-file-name)))
- (source-directory (locate-dominating-file current-file "Cask"))
- ;; Do not load outdated byte code for tests
- (load-prefer-newer t))
- ;; Load the file under test
- (load (expand-file-name "clojure-mode" source-directory)))
-
(defmacro with-clojure-buffer (text &rest body)
"Create a temporary buffer, insert TEXT, switch to clojure-mode and evaluate BODY."
(declare (indent 1))