diff --git a/CHANGELOG.md b/CHANGELOG.md index d3534b7..a458474 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ - [#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. - [#169](https://github.com/clojure-emacs/clojure-ts-mode/pull/169): Add `clojure-ts-remove-unused-keys` (`C-c C-r k`), which removes the names the top-level form at point destructures from maps but never uses, along with their `:or` defaults. +- [#164](https://github.com/clojure-emacs/clojure-ts-mode/pull/164): Support `setopt-local` for `clojure-ts-indent-style`, `clojure-ts-extra-def-forms` and `clojure-ts-comment-macro-font-lock-body`, which Emacs 31 refused to set locally and Emacs 32 warned about in `.dir-locals.el`. ## 0.6.0 (2025-12-02) diff --git a/clojure-ts-mode.el b/clojure-ts-mode.el index 20a9ee0..91f4cc8 100644 --- a/clojure-ts-mode.el +++ b/clojure-ts-mode.el @@ -834,17 +834,16 @@ OVERRIDE, START and END are passed to `treesit-fontify-with-override'." marker: "@" @font-lock-punctuation-face)))) (defun clojure-ts--set-font-lock-option (symbol value &optional scope) - "Set the default value of SYMBOL to VALUE and refontify Clojure buffers. - -When SCOPE is `buffer-local' (Emacs's `setopt-local' / dir-locals path), -set VALUE buffer-locally and recompute the cache for the current buffer -only. Otherwise set the global SYMBOL value and recompute the cache in -every `clojure-ts-mode' buffer from that buffer's own effective value, -so a buffer carrying a local override is left untouched. + "Set SYMBOL to VALUE and refontify Clojure buffers. +When SCOPE is `buffer-local', as with `setopt-local', set VALUE in the +current buffer and refontify only that one. NOTE: This function is not meant to be called directly." (if (eq scope 'buffer-local) - (set (make-local-variable symbol) value) + (progn + (set (make-local-variable symbol) value) + (when (derived-mode-p 'clojure-ts-mode) + (font-lock-flush))) (set-default-toplevel-value symbol value) (dolist (buf (match-buffers '(derived-mode . clojure-ts-mode))) (with-current-buffer buf @@ -1202,18 +1201,18 @@ See `clojure-ts--standard-definition-node-name' for the implementation used.") (- (match-end 1) (match-beginning 1)))) (defun clojure-ts--set-indent-style (symbol value &optional scope) - "Set the default value of SYMBOL to VALUE and reconfigure Clojure buffers. -A buffer with its own indentation style keeps it. - -When SCOPE is `buffer-local' (Emacs's `setopt-local' / dir-locals path), -set VALUE buffer-locally and recompute the cache for the current buffer -only. Otherwise set the global SYMBOL value and recompute the cache in -every `clojure-ts-mode' buffer from that buffer's own effective value, -so a buffer carrying a local override is left untouched. + "Set SYMBOL to VALUE and reconfigure Clojure buffers. +A buffer with its own indentation style keeps it. When SCOPE is +`buffer-local', as with `setopt-local', set VALUE in the current buffer +and reconfigure only that one. NOTE: This function is not meant to be called directly." (if (eq scope 'buffer-local) - (set (make-local-variable symbol) value) + (progn + (set (make-local-variable symbol) value) + (when (derived-mode-p 'clojure-ts-mode) + (setq-local treesit-simple-indent-rules + (clojure-ts--configured-indent-rules)))) (set-default-toplevel-value symbol value) (dolist (buf (match-buffers '(derived-mode . clojure-ts-mode))) (with-current-buffer buf @@ -1836,12 +1835,6 @@ children of the rich comment form are also considered as top-level." parent-source-p)) parent-source-p))) -(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) ?\#) @@ -3921,8 +3914,6 @@ REGEX-AVAILABLE." (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-align-forms-automatically) - (setq-local indent-region-function #'clojure-ts-indent-region)) (when (local-variable-p 'clojure-ts-indent-style) (setq-local treesit-simple-indent-rules (clojure-ts--configured-indent-rules))) (when (local-variable-p 'clojure-ts-outline-variant) @@ -3935,8 +3926,9 @@ Those are set after the major mode." The modes that embed another language run the setup again once they've added its parser, so this is used for every run." (treesit-major-mode-setup) - (when clojure-ts-align-forms-automatically - (setq-local indent-region-function #'clojure-ts-indent-region)) + ;; It checks `clojure-ts-align-forms-automatically' when it runs, so that + ;; turning the option on later, or in .dir-locals.el, works. + (setq-local indent-region-function #'clojure-ts-indent-region) ;; Workaround for treesit-transpose-sexps not correctly working with ;; treesit-thing-settings on Emacs 30. ;; Once treesit-transpose-sexps is working again this can be removed diff --git a/test/clojure-ts-mode-config-test.el b/test/clojure-ts-mode-config-test.el index 5feb918..be6632b 100644 --- a/test/clojure-ts-mode-config-test.el +++ b/test/clojure-ts-mode-config-test.el @@ -255,6 +255,34 @@ y) clojure-ts-comment-macro-font-lock-body nil clojure-ts-indent-style 'semantic)))))) +(describe "options set with setopt-local" + (it "should apply to the current buffer, and only to that one" + (assume (fboundp 'setopt-local) "setopt-local needs Emacs 31") + (with-clojure-ts-buffer clojure-ts-test--options-source + (with-clojure-ts-buffer clojure-ts-test--options-source + (font-lock-ensure) + (spy-on 'font-lock-flush :and-call-through) + (setopt-local clojure-ts-extra-def-forms '("defelem") + clojure-ts-comment-macro-font-lock-body t + clojure-ts-indent-style 'fixed) + ;; `font-lock-ensure' refontifies everything in batch mode, so it + ;; can't tell whether the old faces would have stayed on screen. + (expect 'font-lock-flush :to-have-been-called) + (font-lock-ensure) + (expect (clojure-ts-test--face-at "defelem") + :to-equal 'font-lock-keyword-face) + (expect (clojure-ts-test--face-at "(foo)") + :to-equal 'font-lock-comment-face) + (indent-region (point-min) (point-max)) + (expect (buffer-string) :to-match "(foo\n bar)")) + (font-lock-ensure) + (expect (clojure-ts-test--face-at "defelem") + :not :to-equal 'font-lock-keyword-face) + (expect (clojure-ts-test--face-at "(foo)") + :not :to-equal 'font-lock-comment-face) + (indent-region (point-min) (point-max)) + (expect (buffer-string) :to-match "(foo\n bar)")))) + (describe "clojure-ts-semantic-indent-rules" (it "should apply however it's set" (with-clojure-ts-buffer "(my-block x\ny)" diff --git a/test/clojure-ts-mode-indentation-test.el b/test/clojure-ts-mode-indentation-test.el index c7d2392..93486ea 100644 --- a/test/clojure-ts-mode-indentation-test.el +++ b/test/clojure-ts-mode-indentation-test.el @@ -1276,6 +1276,12 @@ c) :a 1 :bbbbb 2)")))) + (it "should align when the option is turned on after the mode starts" + (with-clojure-ts-buffer "{:a 1\n:bbb 2}" + (setq-local clojure-ts-align-forms-automatically t) + (indent-region (point-min) (point-max)) + (expect (buffer-string) :to-equal "{:a 1\n :bbb 2}"))) + (when-aligning-it "should handle trailing commas" " {:a {:a :a,