Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
- [#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`.
- [#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)

Expand Down
54 changes: 26 additions & 28 deletions clojure-ts-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -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"))

Expand Down Expand Up @@ -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"))

Expand All @@ -163,7 +157,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"))
Expand Down Expand Up @@ -1785,12 +1779,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) ?\#)
Expand All @@ -1808,10 +1796,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

Expand Down Expand Up @@ -3440,6 +3425,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'.

Expand All @@ -3448,13 +3450,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)

Expand Down Expand Up @@ -3489,15 +3485,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.
Expand Down
31 changes: 28 additions & 3 deletions test/clojure-ts-mode-config-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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")
Expand All @@ -203,10 +209,29 @@ 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 "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)
(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
Expand Down
Loading