From bdbae7581d620d48cc31a90a2fb0aad1e33ce6d9 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 1 Nov 2026 11:12:13 +0200 Subject: [PATCH 1/3] Drop the Markdown entry of the thing settings The markdown-inline entry of clojure-ts--thing-settings sat in a `when' form that the backquote didn't evaluate, so it defined the things of a language called `when' and never took effect. Making it take effect isn't an improvement: on Emacs 30, where forward-sexp goes through these things, C-M-f and C-M-k from a plain word in a docstring would jump to the end of the next code span, and Emacs 31 moves over atoms without them. Remove it. --- clojure-ts-mode.el | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/clojure-ts-mode.el b/clojure-ts-mode.el index ca8f416..1db9952 100644 --- a/clojure-ts-mode.el +++ b/clojure-ts-mode.el @@ -1785,12 +1785,6 @@ function literal." "Return non-nil if NODE is a function or a var definition." (clojure-ts--list-node-sym-match-p node clojure-ts--defun-symbols-regex)) -(defconst clojure-ts--markdown-inline-sexp-nodes - '("inline_link" "full_reference_link" "collapsed_reference_link" - "uri_autolink" "email_autolink" "shortcut_link" "image" - "code_span") - "Nodes representing s-expressions in the `markdown-inline' parser.") - (defun clojure-ts--default-sexp-node-p (node) "Return non-nil if point is after the # marker of set or function literal NODE." (and (eq (char-before) ?\#) @@ -1808,10 +1802,7 @@ function literal." ;; For `C-M-f' in "#|(a)" or "#|{1 2 3}" (,(rx (or "(" "{")) . ,#'clojure-ts--default-sexp-node-p)) (text ,(regexp-opt '("comment"))) - (defun ,#'clojure-ts--defun-node-p)) - (when clojure-ts-use-markdown-inline - (markdown-inline - (sexp ,(regexp-opt clojure-ts--markdown-inline-sexp-nodes)))))) + (defun ,#'clojure-ts--defun-node-p)))) ;;; Vertical alignment From 6197785113df4a336cadcda13f765b1ca638c870 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 1 Nov 2026 11:14:32 +0200 Subject: [PATCH 2/3] Apply the outline and completion options set in .dir-locals.el clojure-ts-outline-variant and clojure-ts-completion-enabled are safe as directory-local variables, but they were only read while the mode set itself up, before the directory-local ones are set. Redo their part of the setup when they're set locally, like for the indentation style. The imenu variant of the outline now gets set up here too, rather than by treesit-major-mode-setup, so that switching to it works. Only the two valid values of clojure-ts-outline-variant are safe now, so a typo in .dir-locals.el doesn't silently select the imenu outline. --- CHANGELOG.md | 1 + clojure-ts-mode.el | 37 +++++++++++++++++++---------- test/clojure-ts-mode-config-test.el | 21 +++++++++++++--- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59ed35b..cc6cad1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ - [#170](https://github.com/clojure-emacs/clojure-ts-mode/pull/170): Add the `let*` semantic indentation rule from cljfmt. - [#171](https://github.com/clojure-emacs/clojure-ts-mode/pull/171): Highlight the names of methods (in `defrecord`, `reify` and the like) and of `letfn` functions as definitions at `treesit-font-lock-level` 4, where they were colored as function calls. - [#171](https://github.com/clojure-emacs/clojure-ts-mode/pull/171): Highlight Markdown in the docstrings of the forms in `clojure-ts-extra-def-forms`. +- [#172](https://github.com/clojure-emacs/clojure-ts-mode/pull/172): Fix `clojure-ts-outline-variant` and `clojure-ts-completion-enabled` being ignored in `.dir-locals.el`. ## 0.6.0 (2025-12-02) diff --git a/clojure-ts-mode.el b/clojure-ts-mode.el index 1db9952..c54f1a5 100644 --- a/clojure-ts-mode.el +++ b/clojure-ts-mode.el @@ -163,7 +163,7 @@ double quotes on the third column." If set to the symbol `comments', then top-level comments starting with three or more semicolons will be treated as outline headings. If set to `imenu', then def-like forms are treated as outline headings." - :safe #'symbolp + :safe (lambda (value) (memq value '(comments imenu))) :type '(choice (const :tag "Use special comments" comments) (const :tag "Use imenu" imenu)) :package-version '(clojure-ts-mode . "0.4")) @@ -3431,6 +3431,23 @@ the same features enabled in MODE." ;; (plist-get configs :simple-indent))) )) +(defun clojure-ts--setup-outline () + "Set up `outline-minor-mode' for the variant in `clojure-ts-outline-variant'." + (if (eq clojure-ts-outline-variant 'comments) + (setq-local treesit-outline-predicate #'clojure-ts--outline-predicate + outline-level #'clojure-ts--outline-level) + (setq-local treesit-outline-predicate #'treesit-outline-predicate--from-imenu + outline-level #'treesit-outline-level)) + (setq-local outline-search-function #'treesit-outline-search)) + +(defun clojure-ts--setup-completion () + "Add or remove the completion function, following `clojure-ts-completion-enabled'." + (if clojure-ts-completion-enabled + (add-hook 'completion-at-point-functions + #'clojure-ts-completion-at-point-function nil 'local) + (remove-hook 'completion-at-point-functions + #'clojure-ts-completion-at-point-function 'local))) + (defun clojure-ts-mode-variables (&optional markdown-available regex-available) "Initialize buffer-local variables for `clojure-ts-mode'. @@ -3439,13 +3456,7 @@ REGEX-AVAILABLE." (setq-local indent-tabs-mode nil) (setq-local comment-add 1) (setq-local comment-start ";") - (when (equal clojure-ts-outline-variant 'comments) - ;; NOTE: If `imenu' option is selected for `clojure-ts-outline-variant', all - ;; necessary variables will be set automatically by - ;; `treesit-major-mode-setup'. - (setq-local treesit-outline-predicate #'clojure-ts--outline-predicate - outline-search-function #'treesit-outline-search - outline-level #'clojure-ts--outline-level)) + (clojure-ts--setup-outline) (setq-local clojure-ts-expected-ns-function #'clojure-ts-expected-ns) @@ -3480,15 +3491,17 @@ REGEX-AVAILABLE." (when (boundp 'treesit-thing-settings) ;; Emacs 30+ (setq-local treesit-thing-settings clojure-ts--thing-settings)) - (when clojure-ts-completion-enabled - (add-hook 'completion-at-point-functions - #'clojure-ts-completion-at-point-function nil 'local))) + (clojure-ts--setup-completion)) (defun clojure-ts--apply-local-variables () "Redo the parts of the setup that depend on file or directory-local variables. Those are set after the major mode." (when (local-variable-p 'clojure-ts-indent-style) - (setq-local treesit-simple-indent-rules (clojure-ts--configured-indent-rules)))) + (setq-local treesit-simple-indent-rules (clojure-ts--configured-indent-rules))) + (when (local-variable-p 'clojure-ts-outline-variant) + (clojure-ts--setup-outline)) + (when (local-variable-p 'clojure-ts-completion-enabled) + (clojure-ts--setup-completion))) (defun clojure-ts--major-mode-setup () "Run `treesit-major-mode-setup', then override some of its settings. diff --git a/test/clojure-ts-mode-config-test.el b/test/clojure-ts-mode-config-test.el index 43057e1..c12db76 100644 --- a/test/clojure-ts-mode-config-test.el +++ b/test/clojure-ts-mode-config-test.el @@ -174,7 +174,9 @@ y) (write-region "((clojure-ts-mode . ((clojure-ts-indent-style . fixed) (clojure-ts-align-forms-automatically . t) (clojure-ts-extra-def-forms . (\"defelem\")) - (clojure-ts-comment-macro-font-lock-body . t))))" + (clojure-ts-comment-macro-font-lock-body . t) + (clojure-ts-outline-variant . imenu) + (clojure-ts-completion-enabled . nil))))" nil (expand-file-name ".dir-locals.el" project-dir)) (dolist (dir (list project-dir other-dir)) (write-region clojure-ts-test--options-source nil @@ -193,7 +195,11 @@ y) ;; Fixed indentation and aligned map values. (expect (buffer-string) :to-match "(foo\n bar)") (expect (buffer-string) :to-match "(my-block x\n y)") - (expect (buffer-string) :to-match "{:a 1\n :bbb 2}")) + (expect (buffer-string) :to-match "{:a 1\n :bbb 2}") + (expect treesit-outline-predicate + :to-be #'treesit-outline-predicate--from-imenu) + (expect completion-at-point-functions + :not :to-contain #'clojure-ts-completion-at-point-function)) (with-current-buffer other-buffer (font-lock-ensure) (expect (clojure-ts-test--face-at "defelem") @@ -203,10 +209,19 @@ y) (indent-region (point-min) (point-max)) (expect (buffer-string) :to-match "(foo\n bar)") (expect (buffer-string) :to-match "(my-block x\n y)") - (expect (buffer-string) :to-match "{:a 1\n :bbb 2}"))) + (expect (buffer-string) :to-match "{:a 1\n :bbb 2}") + (expect treesit-outline-predicate + :to-be #'clojure-ts--outline-predicate) + (expect completion-at-point-functions + :to-contain #'clojure-ts-completion-at-point-function))) (kill-buffer project-buffer) (kill-buffer other-buffer))))))) +(describe "clojure-ts-outline-variant" + (it "should only be safe as a directory-local variable with a valid value" + (expect (safe-local-variable-p 'clojure-ts-outline-variant 'imenu) :to-be-truthy) + (expect (safe-local-variable-p 'clojure-ts-outline-variant 'imenus) :not :to-be-truthy))) + (describe "options set with setopt" (it "should apply to the open buffers, even when set from another buffer" (with-clojure-ts-buffer clojure-ts-test--options-source From 2c5f247b113bd8fd26303e96b245da479a12af32 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Sun, 1 Nov 2026 11:15:24 +0200 Subject: [PATCH 3/3] Don't mark the options read when the mode starts as safe clojure-ts-ensure-grammars, clojure-ts-auto-remap and the options that turn the embedded parsers on and off are read when the package loads or when the mode sets up its parsers, before any directory-local variables are set. Marked safe, they were silently ignored in .dir-locals.el. --- CHANGELOG.md | 1 + clojure-ts-mode.el | 6 ------ test/clojure-ts-mode-config-test.el | 10 ++++++++++ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc6cad1..7055075 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ - [#171](https://github.com/clojure-emacs/clojure-ts-mode/pull/171): Highlight the names of methods (in `defrecord`, `reify` and the like) and of `letfn` functions as definitions at `treesit-font-lock-level` 4, where they were colored as function calls. - [#171](https://github.com/clojure-emacs/clojure-ts-mode/pull/171): Highlight Markdown in the docstrings of the forms in `clojure-ts-extra-def-forms`. - [#172](https://github.com/clojure-emacs/clojure-ts-mode/pull/172): Fix `clojure-ts-outline-variant` and `clojure-ts-completion-enabled` being ignored in `.dir-locals.el`. +- [#172](https://github.com/clojure-emacs/clojure-ts-mode/pull/172): Stop marking `clojure-ts-ensure-grammars`, `clojure-ts-auto-remap` and the options that turn the embedded parsers on and off as safe in `.dir-locals.el`, where they have no effect. ## 0.6.0 (2025-12-02) diff --git a/clojure-ts-mode.el b/clojure-ts-mode.el index c54f1a5..c3239c3 100644 --- a/clojure-ts-mode.el +++ b/clojure-ts-mode.el @@ -102,7 +102,6 @@ itself." (defcustom clojure-ts-ensure-grammars t "When non-nil, ensure required Tree-sitter grammars are installed." - :safe #'booleanp :type 'boolean :package-version '(clojure-ts-mode . "0.2.0")) @@ -130,30 +129,25 @@ double quotes on the third column." (defcustom clojure-ts-use-markdown-inline t "When non-nil, use Markdown inline grammar for docstrings." :type 'boolean - :safe #'booleanp :package-version '(clojure-ts-mode . "0.2.3")) (defcustom clojure-ts-use-regex-parser t "When non-nil, use separate grammar to highlight regex syntax." :type 'boolean - :safe #'booleanp :package-version '(clojure-ts-mode . "0.4")) (defcustom clojure-ts-clojurescript-use-js-parser t "When non-nil, use JS grammar to highlight syntax in js* forms." :type 'boolean - :safe #'booleanp :package-version '(clojure-ts-mode . "0.5")) (defcustom clojure-ts-jank-use-cpp-parser t "When non-nil, use C++ grammar to highlight syntax in cpp/raw forms." :type 'boolean - :safe #'booleanp :package-version '(clojure-ts-mode . "0.5")) (defcustom clojure-ts-auto-remap t "When non-nil, redirect all `clojure-mode' buffers to `clojure-ts-mode'." - :safe #'booleanp :type 'boolean :package-version '(clojure-ts-mode . "0.3")) diff --git a/test/clojure-ts-mode-config-test.el b/test/clojure-ts-mode-config-test.el index c12db76..5feb918 100644 --- a/test/clojure-ts-mode-config-test.el +++ b/test/clojure-ts-mode-config-test.el @@ -217,6 +217,16 @@ y) (kill-buffer project-buffer) (kill-buffer other-buffer))))))) +(describe "options read when the mode starts" + (it "should not be safe as directory-local variables, as they can't apply there" + (dolist (option '(clojure-ts-ensure-grammars + clojure-ts-use-markdown-inline + clojure-ts-use-regex-parser + clojure-ts-clojurescript-use-js-parser + clojure-ts-jank-use-cpp-parser + clojure-ts-auto-remap)) + (expect (safe-local-variable-p option nil) :not :to-be-truthy)))) + (describe "clojure-ts-outline-variant" (it "should only be safe as a directory-local variable with a valid value" (expect (safe-local-variable-p 'clojure-ts-outline-variant 'imenu) :to-be-truthy)