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/CHANGELOG.md b/CHANGELOG.md index 22ba816f..51077f9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,25 @@ ## 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 +* [#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 @@ -40,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) @@ -72,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/README.md b/README.md index 1862db14..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.19.0](https://github.com/clojure-emacs/clojure-mode/tree/v5.19.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 - @@ -137,14 +140,16 @@ 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 +- `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). @@ -156,7 +161,7 @@ Similarly we have the `clojure-indent-keyword-style`, which works in the followi [bar.baz]) ``` -* `always-indent` - All args are indented like a macro body. +- `always-indent` - All args are indented like a macro body. ``` clojure (:require [foo.bar] @@ -166,7 +171,7 @@ Similarly we have the `clojure-indent-keyword-style`, which works in the followi 0) ``` -* `align-arguments` - Case (A) is indented like `always-align`, and +- `align-arguments` - Case (A) is indented like `always-align`, and case (B) is indented like a macro body. ``` clojure @@ -285,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 @@ -312,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 @@ -357,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) @@ -370,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 @@ -478,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 @@ -499,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 @@ -511,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 @@ -521,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: @@ -530,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, @@ -542,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: @@ -551,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 @@ -594,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 @@ -617,7 +644,7 @@ An extensive changelog is available [here](CHANGELOG.md). ## License -Copyright © 2007-2024 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 1f23884b..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-2024 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.19.0 +;; Version: 5.20.0 ;; Package-Requires: ((emacs "25.1")) ;; This file is not part of GNU Emacs. @@ -542,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") @@ -625,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 ";+ *") @@ -2266,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_\\)+\\)")) @@ -3320,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\\|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-util-test.el b/test/clojure-mode-util-test.el index 78a2ac17..d905fc70 100644 --- a/test/clojure-mode-util-test.el +++ b/test/clojure-mode-util-test.el @@ -331,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/utils/test-helper.el b/test/utils/test-helper.el index e7894f04..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 "Eldev")) - ;; 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))