From 1ac1b70d4e70478297ad3cb40c52c9574c836610 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 7 May 2025 18:08:24 -0400 Subject: [PATCH 01/71] refactor!(tree-sitter): replace tree-sitter w/ treesit BREAKING CHANGE: This rewrites the :tools tree-sitter module to use treesit instead of tree-sitter.el. Users will need to adapt to treesit and remove any tree-sitter-specific config in their dotfiles. Ref: #7623 Ref: #7742 Ref: #8197 --- modules/tools/tree-sitter/README.org | 8 +- modules/tools/tree-sitter/autoload.el | 41 ---- .../tools/tree-sitter/autoload/compat-30.el | 43 ++++ .../tools/tree-sitter/autoload/tree-sitter.el | 71 +++++++ modules/tools/tree-sitter/config.el | 186 ++++++++++++------ modules/tools/tree-sitter/doctor.el | 8 +- modules/tools/tree-sitter/packages.el | 22 ++- 7 files changed, 262 insertions(+), 117 deletions(-) delete mode 100644 modules/tools/tree-sitter/autoload.el create mode 100644 modules/tools/tree-sitter/autoload/compat-30.el create mode 100644 modules/tools/tree-sitter/autoload/tree-sitter.el diff --git a/modules/tools/tree-sitter/README.org b/modules/tools/tree-sitter/README.org index a13d58a9d..3303ad1b2 100644 --- a/modules/tools/tree-sitter/README.org +++ b/modules/tools/tree-sitter/README.org @@ -27,9 +27,11 @@ It includes: /This module has no flags./ ** Packages -- [[doom-package:evil-textobj-tree-sitter]] if [[doom-module::editor evil +everywhere]] -- [[doom-package:tree-sitter]] -- [[doom-package:tree-sitter-langs]] +- if [[doom-module:+compat]] + - [[doom-package:evil-textobj-tree-sitter]] if [[doom-module::editor evil +everywhere]] + - [[doom-package:tree-sitter]] + - [[doom-package:tree-sitter-indent]] + - [[doom-package:tree-sitter-langs]] ** Hacks /No hacks documented for this module./ diff --git a/modules/tools/tree-sitter/autoload.el b/modules/tools/tree-sitter/autoload.el deleted file mode 100644 index 42e11dd9b..000000000 --- a/modules/tools/tree-sitter/autoload.el +++ /dev/null @@ -1,41 +0,0 @@ -;;; tools/tree-sitter/autoload.el -*- lexical-binding: t; -*- - -;;;###autodef (fset 'tree-sitter! #'ignore) -(defun tree-sitter! () - "Dispatch to turn on tree sitter. - -Used as a hook function which turns on `tree-sitter-mode' -and selectively turn on `tree-sitter-hl-mode'. -according to `+tree-sitter-hl-enabled-modes'" - (turn-on-tree-sitter-mode) - ;; conditionally enable `tree-sitter-hl-mode' - (let ((mode (bound-and-true-p tree-sitter-hl-mode))) - (when-let (mode (if (pcase +tree-sitter-hl-enabled-modes - (`(not . ,modes) (not (memq major-mode modes))) - ((and `(,_ . ,_) modes) (memq major-mode modes)) - (bool bool)) - (unless mode +1) - (if mode -1))) - (tree-sitter-hl-mode mode)))) - -;;;###autodef (fset 'set-tree-sitter-lang! #'ignore) -(defun set-tree-sitter-lang! (mode lang) - "Associate LANG with major MODE." - (after! tree-sitter-langs - (add-to-list 'tree-sitter-major-mode-language-alist (cons mode lang)))) - -;; HACK: Remove and refactor when `use-package' eager macro expansion is solved or `use-package!' is removed -;;;###autoload -(defun +tree-sitter-get-textobj (group &optional query) - "A wrapper around `evil-textobj-tree-sitter-get-textobj' to -prevent eager expansion." - (eval `(evil-textobj-tree-sitter-get-textobj ,group ,query))) - -;;;###autoload -(defun +tree-sitter-goto-textobj (group &optional previous end query) - "Thin wrapper that returns the symbol of a named function, used in keybindings." - (let ((sym (intern (format "+goto%s%s-%s" (if previous "-previous" "") (if end "-end" "") group)))) - (fset sym (lambda () - (interactive) - (evil-textobj-tree-sitter-goto-textobj group previous end query))) - sym)) diff --git a/modules/tools/tree-sitter/autoload/compat-30.el b/modules/tools/tree-sitter/autoload/compat-30.el new file mode 100644 index 000000000..a4fe39300 --- /dev/null +++ b/modules/tools/tree-sitter/autoload/compat-30.el @@ -0,0 +1,43 @@ +;;; tools/tree-sitter/autoload/compat-30.el -*- lexical-binding: t; -*- +;;;###if (and (fboundp 'treesit-available-p) (version< emacs-version "31.1")) +;; +;; Backported from 31.1 +;; +;;; Code: + +(autoload 'treesit-ready-p "treesit") + +;;;###autoload +(defcustom treesit-auto-install-grammar 'ask + "Whether to install tree-sitter language grammar libraries when needed. +This controls whether Emacs will install missing grammar libraries +when they are needed by some tree-sitter based mode. +If `ask', ask for confirmation before installing the required grammar library. +If `always', install the grammar library without asking. +If nil or `never' or anything else, don't install the grammar library +even while visiting a file in the mode that requires such grammar; this +might display a warning and/or fail to turn on the mode." + :type '(choice (const :tag "Never install grammar libraries" never) + (const :tag "Always automatically install grammar libraries" + always) + (const :tag "Ask whether to install missing grammar libraries" + ask)) + :version "31.1" + :group 'treesit) + +;;;###autoload +(defun treesit-ensure-installed (lang) + "Ensure that the grammar library for the language LANG is installed. +The option `treesit-auto-install-grammar' defines whether to install +the grammar library if it's unavailable." + (or (treesit-ready-p lang t) + (when (or (eq treesit-auto-install-grammar 'always) + (and (eq treesit-auto-install-grammar 'ask) + (y-or-n-p (format "\ +Tree-sitter grammar for `%s' is missing; install it?" + lang)))) + (treesit-install-language-grammar lang) + ;; Check that the grammar was installed successfully + (treesit-ready-p lang)))) + +;;; compat-30.el ends here diff --git a/modules/tools/tree-sitter/autoload/tree-sitter.el b/modules/tools/tree-sitter/autoload/tree-sitter.el new file mode 100644 index 000000000..1797c56e4 --- /dev/null +++ b/modules/tools/tree-sitter/autoload/tree-sitter.el @@ -0,0 +1,71 @@ +;;; tools/tree-sitter/autoload/tree-sitter.el -*- lexical-binding: t; -*- + +;;;###autodef (fset 'tree-sitter! #'ignore) +(defun tree-sitter! () + (message "Old tree-sitter.el support is deprecated!")) + +;;;###autodef (fset 'set-tree-sitter! #'ignore) +(defun set-tree-sitter! (mode ts-mode &optional langs) + "Remap major MODE to TS-MODE. + +MODE and TS-MODE are major mode symbols. If LANGS is provided, fall back to MODE +if LANGS don't pass `treesit-ready-p' when activating TS-MODE. Use this for ts +modes that error out instead of failing gracefully." + (declare (indent 2)) + (cl-check-type mode symbol) + (cl-check-type ts-mode symbol) + (setq langs (ensure-list langs)) + (dolist (m (ensure-list mode)) + (add-to-list + 'major-mode-remap-defaults + (cons + m (let (ensured?) + (lambda () + (funcall + ;; Because standard major-mode remapping doesn't offer graceful + ;; failure in some cases, I implement it myself: + (cond ((null langs) m) + ((not (fboundp ts-mode)) + (message "Couldn't find %S, using %S instead" ts-mode m) + m) + ((and (fboundp 'treesit-available-p) + (treesit-available-p) + (fboundp ts-mode) + ;; Only prompt once, and log other times. + (cl-every (if ensured? + (doom-rpartial #'treesit-ready-p 'message) + #'treesit-ensure-installed) + (cl-loop for lang in langs + if (listp lang) + collect (car lang) + else collect (list lang)))) + ts-mode) + ((setq ensured? t) + m)))))))) + (with-eval-after-load 'treesit + (dolist (lang langs) + (when (and lang (listp lang)) + (cl-destructuring-bind (name &key url rev source-dir cc cpp commit) lang + (setf (alist-get name treesit-language-source-alist) + (list url rev source-dir cc cpp commit))))))) + +;; ;; HACK: Remove and refactor when `use-package' eager macro expansion is solved or `use-package!' is removed +;; ;;;###autoload +;; (defun +tree-sitter-get-textobj (group &optional query) +;; "A wrapper around `evil-textobj-tree-sitter-get-textobj' to +;; prevent eager expansion." +;; (eval `(evil-textobj-tree-sitter-get-textobj ,group ,query))) + +;; ;;;###autoload +;; (defun +tree-sitter-goto-textobj (group &optional previous end query) +;; "Thin wrapper that returns the symbol of a named function, used in keybindings." +;; (let ((sym (intern (format "+goto%s%s-%s" (if previous "-previous" "") (if end "-end" "") group)))) +;; (fset sym (lambda () +;; (interactive) +;; (evil-textobj-tree-sitter-goto-textobj group previous end query))) +;; sym)) + + +;;; TODO: Backwards compatibility + +;;; tree-sitter.el ends here diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index def0ce5d2..e47845e87 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -1,77 +1,135 @@ ;;; tools/tree-sitter/config.el -*- lexical-binding: t; -*- -(defvar +tree-sitter-hl-enabled-modes '(not web-mode typescript-tsx-mode) - "A list of major modes which should be highlighted by tree-sitter. - -If this list begins with `not', then it negates the list. -If it is t, it is enabled in all modes. -If nil, it is disabled in all modes") - ;; ;;; Packages -(use-package! tree-sitter +(use-package! treesit + :when (fboundp 'treesit-available-p) + :when (treesit-available-p) :defer t :config - (require 'tree-sitter-langs) - ;; This makes every node a link to a section of code - (setq tree-sitter-debug-jump-buttons t - ;; and this highlights the entire sub tree in your code - tree-sitter-debug-highlight-jump-region t)) + ;; HACK: treesit lacks any way to dictate where to install grammars. + (defadvice! +tree-sitter--install-grammar-to-local-dir-a (fn &rest args) + "Write grammars to `doom-profile-data-dir'." + :around #'treesit-install-language-grammar + :around #'treesit--build-grammar + (let ((user-emacs-directory doom-profile-data-dir)) + (apply fn args))) + + ;; TODO: Move most of these out to modules + (dolist (map '((awk "https://github.com/Beaglefoot/tree-sitter-awk" nil nil nil nil) + (bibtex "https://github.com/latex-lsp/tree-sitter-bibtex" nil nil nil nil) + (blueprint "https://github.com/huanie/tree-sitter-blueprint" nil nil nil nil) + (c "https://github.com/tree-sitter/tree-sitter-c" nil nil nil nil) + (c-sharp "https://github.com/tree-sitter/tree-sitter-c-sharp" nil nil nil nil) + (clojure "https://github.com/sogaiu/tree-sitter-clojure" nil nil nil nil) + (cmake "https://github.com/uyha/tree-sitter-cmake" nil nil nil nil) + (commonlisp "https://github.com/tree-sitter-grammars/tree-sitter-commonlisp" nil nil nil nil) + (cpp "https://github.com/tree-sitter/tree-sitter-cpp" nil nil nil nil) + (css "https://github.com/tree-sitter/tree-sitter-css" nil nil nil nil) + (dart "https://github.com/ast-grep/tree-sitter-dart" nil nil nil nil) + (dockerfile "https://github.com/camdencheek/tree-sitter-dockerfile" nil nil nil nil) + (elixir "https://github.com/elixir-lang/tree-sitter-elixir" nil nil nil nil) + (glsl "https://github.com/tree-sitter-grammars/tree-sitter-glsl" nil nil nil nil) + (go "https://github.com/tree-sitter/tree-sitter-go" nil nil nil nil) + (gomod "https://github.com/camdencheek/tree-sitter-go-mod" nil nil nil nil) + (heex "https://github.com/phoenixframework/tree-sitter-heex" nil nil nil nil) + (html "https://github.com/tree-sitter/tree-sitter-html" nil nil nil nil) + (java "https://github.com/tree-sitter/tree-sitter-java" nil nil nil nil) + (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src" nil nil) + (json "https://github.com/tree-sitter/tree-sitter-json" nil nil nil nil) + (julia "https://github.com/tree-sitter/tree-sitter-julia" nil nil nil nil) + (kotlin "https://github.com/fwcd/tree-sitter-kotlin" nil nil nil nil) + (latex "https://github.com/latex-lsp/tree-sitter-latex" nil nil nil nil) + (lua "https://github.com/tree-sitter-grammars/tree-sitter-lua" nil nil nil nil) + (make "https://github.com/tree-sitter-grammars/tree-sitter-make" nil nil nil nil) + (nix "https://github.com/nix-community/tree-sitter-nix" nil nil nil nil) + (nu "https://github.com/nushell/tree-sitter-nu" nil nil nil nil) + (org "https://github.com/milisims/tree-sitter-org" nil nil nil nil) + (perl "https://github.com/ganezdragon/tree-sitter-perl" nil nil nil nil) + (proto "https://github.com/mitchellh/tree-sitter-proto" nil nil nil nil) + (python "https://github.com/tree-sitter/tree-sitter-python" nil nil nil nil) + (r "https://github.com/r-lib/tree-sitter-r" nil nil nil nil) + (ruby "https://github.com/tree-sitter/tree-sitter-ruby" nil nil nil nil) + (rust "https://github.com/tree-sitter/tree-sitter-rust" nil nil nil nil) + (scala "https://github.com/tree-sitter/tree-sitter-scala" nil nil nil nil) + (sql "https://github.com/DerekStride/tree-sitter-sql" "gh-pages" nil nil nil) + (surface "https://github.com/connorlay/tree-sitter-surface" nil nil nil nil) + (toml "https://github.com/tree-sitter/tree-sitter-toml" nil nil nil nil) + (tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src" nil nil) + (typescript "https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src" nil nil) + (typst "https://github.com/uben0/tree-sitter-typst" "master" "src" nil nil) + (verilog "https://github.com/gmlarumbe/tree-sitter-verilog" nil nil nil nil) + (vhdl "https://github.com/alemuller/tree-sitter-vhdl" nil nil nil nil) + (vue "https://github.com/tree-sitter-grammars/tree-sitter-vue" nil nil nil nil) + (wast "https://github.com/wasm-lsp/tree-sitter-wasm" nil "wast/src" nil nil) + (wat "https://github.com/wasm-lsp/tree-sitter-wasm" nil "wat/src" nil nil) + (wgsl "https://github.com/mehmetoguzderin/tree-sitter-wgsl" nil nil nil nil) + (yaml "https://github.com/tree-sitter-grammars/tree-sitter-yaml" nil nil nil nil))) + (cl-pushnew map treesit-language-source-alist :test #'eq :key #'car))) -(use-package! evil-textobj-tree-sitter - :when (modulep! :editor evil +everywhere) - :defer t - :init (after! tree-sitter (require 'evil-textobj-tree-sitter)) - :config - (defvar +tree-sitter-inner-text-objects-map (make-sparse-keymap)) - (defvar +tree-sitter-outer-text-objects-map (make-sparse-keymap)) - (defvar +tree-sitter-goto-previous-map (make-sparse-keymap)) - (defvar +tree-sitter-goto-next-map (make-sparse-keymap)) +;; TODO: combobulate or evil-textobj-tree-sitter - (evil-define-key '(visual operator) 'tree-sitter-mode - "i" +tree-sitter-inner-text-objects-map - "a" +tree-sitter-outer-text-objects-map) - (evil-define-key 'normal 'tree-sitter-mode - "[g" +tree-sitter-goto-previous-map - "]g" +tree-sitter-goto-next-map) - (map! (:map +tree-sitter-inner-text-objects-map - "A" (+tree-sitter-get-textobj '("parameter.inner" "call.inner")) - "f" (+tree-sitter-get-textobj "function.inner") - "F" (+tree-sitter-get-textobj "call.inner") - "C" (+tree-sitter-get-textobj "class.inner") - "v" (+tree-sitter-get-textobj "conditional.inner") - "l" (+tree-sitter-get-textobj "loop.inner")) - (:map +tree-sitter-outer-text-objects-map - "A" (+tree-sitter-get-textobj '("parameter.outer" "call.outer")) - "f" (+tree-sitter-get-textobj "function.outer") - "F" (+tree-sitter-get-textobj "call.outer") - "C" (+tree-sitter-get-textobj "class.outer") - "c" (+tree-sitter-get-textobj "comment.outer") - "v" (+tree-sitter-get-textobj "conditional.outer") - "l" (+tree-sitter-get-textobj "loop.outer")) +;; (use-package! combobulate +;; :commands combobulate-query-builder +;; :hook (prog-mode . combobulate-mode)) - (:map +tree-sitter-goto-previous-map - "a" (+tree-sitter-goto-textobj "parameter.outer" t) - "f" (+tree-sitter-goto-textobj "function.outer" t) - "F" (+tree-sitter-goto-textobj "call.outer" t) - "C" (+tree-sitter-goto-textobj "class.outer" t) - "c" (+tree-sitter-goto-textobj "comment.outer" t) - "v" (+tree-sitter-goto-textobj "conditional.outer" t) - "l" (+tree-sitter-goto-textobj "loop.outer" t)) - (:map +tree-sitter-goto-next-map - "a" (+tree-sitter-goto-textobj "parameter.outer") - "f" (+tree-sitter-goto-textobj "function.outer") - "F" (+tree-sitter-goto-textobj "call.outer") - "C" (+tree-sitter-goto-textobj "class.outer") - "c" (+tree-sitter-goto-textobj "comment.outer") - "v" (+tree-sitter-goto-textobj "conditional.outer") - "l" (+tree-sitter-goto-textobj "loop.outer"))) - (after! which-key - (setq which-key-allow-multiple-replacements t) - (pushnew! - which-key-replacement-alist - '(("" . "\\`+?evil-textobj-tree-sitter-function--\\(.*\\)\\(?:.inner\\|.outer\\)") . (nil . "\\1"))))) +;; (use-package! evil-textobj-tree-sitter +;; :when (modulep! :editor evil +everywhere) +;; :defer t +;; :init (after! tree-sitter (require 'evil-textobj-tree-sitter)) +;; :after-call doom-first-input-hook +;; :config +;; (defvar +tree-sitter-inner-text-objects-map (make-sparse-keymap)) +;; (defvar +tree-sitter-outer-text-objects-map (make-sparse-keymap)) +;; (defvar +tree-sitter-goto-previous-map (make-sparse-keymap)) +;; (defvar +tree-sitter-goto-next-map (make-sparse-keymap)) + +;; (evil-define-key '(visual operator) 'tree-sitter-mode +;; "i" +tree-sitter-inner-text-objects-map +;; "a" +tree-sitter-outer-text-objects-map) +;; (evil-define-key 'normal 'tree-sitter-mode +;; "[g" +tree-sitter-goto-previous-map +;; "]g" +tree-sitter-goto-next-map) + +;; (map! (:map +tree-sitter-inner-text-objects-map +;; "A" (+tree-sitter-get-textobj '("parameter.inner" "call.inner")) +;; "f" (+tree-sitter-get-textobj "function.inner") +;; "F" (+tree-sitter-get-textobj "call.inner") +;; "C" (+tree-sitter-get-textobj "class.inner") +;; "v" (+tree-sitter-get-textobj "conditional.inner") +;; "l" (+tree-sitter-get-textobj "loop.inner")) +;; (:map +tree-sitter-outer-text-objects-map +;; "A" (+tree-sitter-get-textobj '("parameter.outer" "call.outer")) +;; "f" (+tree-sitter-get-textobj "function.outer") +;; "F" (+tree-sitter-get-textobj "call.outer") +;; "C" (+tree-sitter-get-textobj "class.outer") +;; "c" (+tree-sitter-get-textobj "comment.outer") +;; "v" (+tree-sitter-get-textobj "conditional.outer") +;; "l" (+tree-sitter-get-textobj "loop.outer")) + +;; (:map +tree-sitter-goto-previous-map +;; "a" (+tree-sitter-goto-textobj "parameter.outer" t) +;; "f" (+tree-sitter-goto-textobj "function.outer" t) +;; "F" (+tree-sitter-goto-textobj "call.outer" t) +;; "C" (+tree-sitter-goto-textobj "class.outer" t) +;; "c" (+tree-sitter-goto-textobj "comment.outer" t) +;; "v" (+tree-sitter-goto-textobj "conditional.outer" t) +;; "l" (+tree-sitter-goto-textobj "loop.outer" t)) +;; (:map +tree-sitter-goto-next-map +;; "a" (+tree-sitter-goto-textobj "parameter.outer") +;; "f" (+tree-sitter-goto-textobj "function.outer") +;; "F" (+tree-sitter-goto-textobj "call.outer") +;; "C" (+tree-sitter-goto-textobj "class.outer") +;; "c" (+tree-sitter-goto-textobj "comment.outer") +;; "v" (+tree-sitter-goto-textobj "conditional.outer") +;; "l" (+tree-sitter-goto-textobj "loop.outer"))) + +;; (after! which-key +;; (setq which-key-allow-multiple-replacements t) +;; (pushnew! +;; which-key-replacement-alist +;; '(("" . "\\`+?evil-textobj-tree-sitter-function--\\(.*\\)\\(?:.inner\\|.outer\\)") . (nil . "\\1"))))) diff --git a/modules/tools/tree-sitter/doctor.el b/modules/tools/tree-sitter/doctor.el index 68026fce7..f5ebe8731 100644 --- a/modules/tools/tree-sitter/doctor.el +++ b/modules/tools/tree-sitter/doctor.el @@ -1,4 +1,8 @@ -;;; tools/treesitter/doctor.el -*- lexical-binding: t; -*- +;;; tools/tree-sitter/doctor.el -*- lexical-binding: t; -*- (unless (fboundp 'module-load) - (warn! "Emacs was not built with dynamic modules support. Tree sitter needs this to function")) + (warn! "Emacs was not built with dynamic modules support, which the treesit.el library requires")) + +(unless (and (fboundp 'treesit-available-p) + (treesit-available-p)) + (error! "Treesit library not available. Did you build Emacs with tree-sitter support?")) diff --git a/modules/tools/tree-sitter/packages.el b/modules/tools/tree-sitter/packages.el index 0fd650e7a..c5b7fa3c2 100644 --- a/modules/tools/tree-sitter/packages.el +++ b/modules/tools/tree-sitter/packages.el @@ -1,10 +1,18 @@ ;; -*- no-byte-compile: t; -*- ;;; tools/tree-sitter/packages.el -(package! tree-sitter :recipe (:branch "master") :pin "1c455b0953da06c40fcf1f21f1ac0c6e179b46d0") -(package! tree-sitter-langs :pin "becd29c756a3272bc91d09de642df99a0fca6cee") -(package! tree-sitter-indent :pin "4ef246db3e4ff99f672fe5e4b416c890f885c09e") - -(when (modulep! :editor evil +everywhere) - (package! evil-textobj-tree-sitter - :pin "bce236e5d2cc2fa4eae7d284ffd19ad18d46349a")) +(package! treesit :built-in t) +(when (> emacs-major-version 28) + ;; (package! combobulate + ;; :recipe '(;; If pulled from emacsmirror, this would otherwise pull in test + ;; ;; repos that users don't need. + ;; :nonrecursive t + ;; ;; HACK: This package has terrible autoload ettiquette, eagerly + ;; ;; loading a number of expensive packages at startup, so + ;; ;; autoloads are handled manually in config.el + ;; :build (:not autoloads)) + ;; :pin "59b64d66d66eb84da6a2cedd152b1692378af674") + ;; (when (modulep! :editor evil +everywhere) + ;; (package! evil-textobj-tree-sitter + ;; :pin "bce236e5d2cc2fa4eae7d284ffd19ad18d46349a")) + ) From f2678b3ea2b3743d6246a3954fb2212b21a9804a Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 7 May 2025 18:14:52 -0400 Subject: [PATCH 02/71] feat(fold): add treesit-fold support --- modules/editor/fold/autoload/fold.el | 78 ++++++++++++++-------------- modules/editor/fold/config.el | 14 +++-- modules/editor/fold/packages.el | 3 +- 3 files changed, 47 insertions(+), 48 deletions(-) diff --git a/modules/editor/fold/autoload/fold.el b/modules/editor/fold/autoload/fold.el index 57f2fdf88..c371431ab 100644 --- a/modules/editor/fold/autoload/fold.el +++ b/modules/editor/fold/autoload/fold.el @@ -41,10 +41,11 @@ Return non-nil if successful in doing so." (end-of-line) (+fold--hideshow-fold-p))))))) -;; NOTE: does this need more? -(defun +fold--ts-fold-p () - (and (bound-and-true-p tree-sitter-mode) - (featurep 'ts-fold))) +(defun +fold--treesit-fold-p () + (and (treesit-available-p) + (treesit-parser-list) + (require 'treesit-fold nil t) + (treesit-fold-usable-mode-p))) (defun +fold--invisible-points (count) (let (points) @@ -102,18 +103,17 @@ Return non-nil if successful in doing so." ov (hs-overlay-at start))) (when ov (list (cons (overlay-start ov) (overlay-end ov)))))) - (when (+fold--ts-fold-p) - (when-let* ((node (ts-fold--foldable-node-at-pos)) - (beg (tsc-node-start-position node)) - (end (tsc-node-end-position node))) + (when (+fold--treesit-fold-p) + (when-let* ((node (treesit-fold--foldable-node-at-pos)) + (beg (treesit-node-start node)) + (end (treesit-node-end node))) (list (cons beg end))))))) (defun +fold--open-rec-between (beg end) "Recursively open all folds betwen BEG and END." (when (featurep 'vimish-fold) ;; from `vimish-fold-unfold-all' - (mapc #'vimish-fold--unfold - (vimish-fold--folds-in beg end))) + (mapc #'vimish-fold--unfold (vimish-fold--folds-in beg end))) (and (+fold--outline-fold-p) (outline-show-subtree)) (hs-life-goes-on @@ -121,13 +121,13 @@ Return non-nil if successful in doing so." (let ((hs-allow-nesting nil)) (hs-discard-overlays beg end)) (run-hooks 'hs-show-hook)) - (when (bound-and-true-p ts-fold-mode) - ;; from `ts-fold-open-all' - (ts-fold--ensure-ts + (when (+fold--treesit-fold-p) + (treesit-fold--ensure-ts + ;; from `ts-fold-open-all' (thread-last (overlays-in beg end) (seq-filter (lambda (ov) - (eq (overlay-get ov 'invisible) 'ts-fold))) + (eq (overlay-get ov 'invisible) 'treesit-fold))) (mapc #'delete-overlay))))) ;; @@ -146,7 +146,7 @@ Targets `vimmish-fold', `hideshow', `ts-fold' and `outline' folds." (symbol-function #'outline-hide-entry))) (outline-toggle-children))) ((+fold--hideshow-fold-p) (+fold-from-eol (hs-toggle-hiding))) - ((+fold--ts-fold-p) (ts-fold-toggle))))) + ((+fold--treesit-fold-p) (treesit-fold-toggle))))) ;;;###autoload (defun +fold/open-rec () @@ -169,7 +169,7 @@ Targets `vimmish-fold', `hideshow', `ts-fold' and `outline' folds." (outline-show-branches) (outline-show-entry)) ((+fold--hideshow-fold-p) (+fold-from-eol (hs-show-block))) - ((+fold--ts-fold-p) (ts-fold-open))))) + ((+fold--treesit-fold-p) (treesit-fold-open))))) ;;;###autoload (defun +fold/close () @@ -181,15 +181,15 @@ Targets `vimmish-fold', `hideshow', `ts-fold' and `outline' folds." (cond ((+fold--vimish-fold-p) (vimish-fold-refold)) ((+fold--outline-fold-p) (outline-hide-subtree)) ((+fold--hideshow-fold-p) (+fold-from-eol (hs-hide-block))) - ((+fold--ts-fold-p) (ts-fold-close))))) + ((+fold--treesit-fold-p) (treesit-fold-close))))) ;;;###autoload (defun +fold/open-all (&optional level) "Open folds at LEVEL (or all folds if LEVEL is nil)." (interactive (list (if current-prefix-arg (prefix-numeric-value current-prefix-arg)))) - (cond ((+fold--ts-fold-p) - (ts-fold-open-all)) + (cond ((+fold--treesit-fold-p) + (treesit-fold-open-all)) ((and (featurep 'vimish-fold) (+fold--vimish-fold-p)) (vimish-fold-unfold-all)) ((save-excursion @@ -209,20 +209,19 @@ Targets `vimmish-fold', `hideshow', `ts-fold' and `outline' folds." (interactive (list (if current-prefix-arg (prefix-numeric-value current-prefix-arg)))) (save-excursion - (if (+fold--ts-fold-p) - (ts-fold-close-all) - (progn - (when (featurep 'vimish-fold) - (vimish-fold-refold-all)) - (when (+fold--ensure-hideshow-mode) - (hs-life-goes-on - (if (integerp level) - (hs-hide-level-recursive level (point-min) (point-max)) - (hs-hide-all)))) - (if (integerp level) - (outline--show-headings-up-to-level level) - (when (fboundp 'outline-hide-sublevels) - (outline-show-only-headings))))))) + (if (+fold--treesit-fold-p) + (treesit-fold-close-all) + (when (featurep 'vimish-fold) + (vimish-fold-refold-all)) + (when (+fold--ensure-hideshow-mode) + (hs-life-goes-on + (if (integerp level) + (hs-hide-level-recursive level (point-min) (point-max)) + (hs-hide-all)))) + (if (integerp level) + (outline--show-headings-up-to-level level) + (when (fboundp 'outline-hide-sublevels) + (outline-show-only-headings)))))) ;;;###autoload (defun +fold/next (count) @@ -260,8 +259,9 @@ region." (outline-end-of-heading)))) (point))) (lambda () - ;; ts-fold does not define movement functions so we need to do it ourselves - (when (+fold--ts-fold-p) + ;; {ts,treesit}-fold does not define movement functions so + ;; we need to do it ourselves + (when (+fold--treesit-fold-p) (let* ((arg-list (if (> count 0) ;; depending on direction we need to change the ranges (list (point) (point-max)) (list (point-min) (point)))) @@ -270,9 +270,11 @@ region." #'>)) (ovs (cl-remove-if-not (lambda (ov) - (eq (overlay-get ov 'creator) 'ts-fold)) - ;; `overlays-in' does not provide a list that is sorted - ;; (in the way we need it atleast) so we need to sort it based on direction + (eq (overlay-get ov 'creator) 'treesit-fold)) + ;; `overlays-in' does not provide a list + ;; that is sorted (in the way we need it + ;; atleast) so we need to sort it based on + ;; direction (cl-sort (apply #'overlays-in arg-list) comp-fun :key #'overlay-start)))) (if (and ovs (<= (abs count) (length ovs))) (goto-char (overlay-start (nth (- (abs count) 1) ovs)))))))) diff --git a/modules/editor/fold/config.el b/modules/editor/fold/config.el index c063ecef7..3212ae147 100644 --- a/modules/editor/fold/config.el +++ b/modules/editor/fold/config.el @@ -3,8 +3,7 @@ (defcustom +fold-ellipsis " [...] " "The ellipsis to show for ellided regions (folds). -`org-ellipsis', `truncate-string-ellipsis', and `ts-fold-replacement' are set to -this." +`org-ellipsis' and `truncate-string-ellipsis' are set to this." :type 'string :group '+fold) @@ -106,9 +105,8 @@ this." (vimish-fold-global-mode +1)) -(use-package! ts-fold - :when (modulep! :tools tree-sitter) - :after tree-sitter - :config - (setq ts-fold-replacement +fold-ellipsis) - (global-ts-fold-mode +1)) +;; Will be autoloaded by fold commands +(use-package! treesit-fold + :when (modulep! :tools tree-sitter -compat) + :defer t + :config (global-treesit-fold-mode +1)) diff --git a/modules/editor/fold/packages.el b/modules/editor/fold/packages.el index 3485e6939..fb7d5fe88 100644 --- a/modules/editor/fold/packages.el +++ b/modules/editor/fold/packages.el @@ -7,5 +7,4 @@ (when (modulep! :editor evil) (package! evil-vimish-fold :pin "b6e0e6b91b8cd047e80debef1a536d9d49eef31a")) (when (modulep! :tools tree-sitter) - (package! ts-fold :pin "6eed69cf2b97dce9c6ad329710ed42f0ad674f76" - :recipe (:host github :repo "emacs-tree-sitter/ts-fold"))) + (package! treesit-fold :pin "6628b7cce585328e05d810b5505e4fdb9306f24f")) From a372eba7cd58d80aa3d865491d0cda0908feca93 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 7 May 2025 18:15:51 -0400 Subject: [PATCH 03/71] feat(python): add treesit support --- modules/lang/python/autoload/pyenv.el | 2 +- modules/lang/python/config.el | 60 +++++++++++++++++++-------- modules/lang/python/doctor.el | 4 ++ modules/tools/tree-sitter/config.el | 1 - 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/modules/lang/python/autoload/pyenv.el b/modules/lang/python/autoload/pyenv.el index a129cd5b4..9fd159832 100644 --- a/modules/lang/python/autoload/pyenv.el +++ b/modules/lang/python/autoload/pyenv.el @@ -7,7 +7,7 @@ ;;;###autoload (defun +python-pyenv-mode-set-auto-h () "Set pyenv-mode version from buffer-local variable." - (when (eq major-mode 'python-mode) + (when (memq major-mode '(python-mode python-ts-mode)) (when (not (local-variable-p '+pyenv--version)) (make-local-variable '+pyenv--version) (setq +pyenv--version (+python-pyenv-read-version-from-file))) diff --git a/modules/lang/python/config.el b/modules/lang/python/config.el index 6739dc71d..1e61c960c 100644 --- a/modules/lang/python/config.el +++ b/modules/lang/python/config.el @@ -14,28 +14,38 @@ ;;; Packages (use-package! python - :mode ("[./]flake8\\'" . conf-mode) - :mode ("/Pipfile\\'" . conf-mode) + :mode ("/\\(?:Pipfile\\|\\.?flake8\\)\\'" . conf-mode) :init (setq python-environment-directory doom-cache-dir python-indent-guess-indent-offset-verbose nil) + (when (modulep! +tree-sitter) + (set-tree-sitter! 'python-mode 'python-ts-mode + '((python :url "https://github.com/tree-sitter/tree-sitter-python")))) + + :config + ;; HACK: `python-base-mode' (and `python-ts-mode') don't exist on pre-29 + ;; versions of Emacs, Rather than litter this module with conditionals, I + ;; shim the keymap in. + (unless (boundp 'python-base-mode-map) + (defvaralias 'python-base-mode-map 'python-mode-map)) + (when (modulep! +lsp) (add-hook 'python-mode-local-vars-hook #'lsp! 'append) + (add-hook 'python-ts-mode-local-vars-hook #'lsp! 'append) ;; Use "mspyls" in eglot if in PATH (when (executable-find "Microsoft.Python.LanguageServer") - (set-eglot-client! 'python-mode '("Microsoft.Python.LanguageServer")))) + (set-eglot-client! '(python-mode python-ts-mode) '("Microsoft.Python.LanguageServer")))) - (when (modulep! +tree-sitter) - (add-hook 'python-mode-local-vars-hook #'tree-sitter! 'append)) - :config - (set-repl-handler! 'python-mode #'+python/open-repl + (set-repl-handler! '(python-mode python-ts-mode) #'+python/open-repl :persist t :send-region #'python-shell-send-region :send-buffer #'python-shell-send-buffer) - (set-docsets! '(python-mode inferior-python-mode) "Python 3" "NumPy" "SciPy" "Pandas") - (set-ligatures! 'python-mode + (set-docsets! '(python-mode python-ts-mode inferior-python-mode) + "Python 3" "NumPy" "SciPy" "Pandas") + + (set-ligatures! '(python-mode python-ts-mode) ;; Functional :def "def" :lambda "lambda" @@ -62,7 +72,7 @@ (string= python-shell-interpreter "python")) (setq python-shell-interpreter "python3")) - (add-hook! 'python-mode-hook + (add-hook! '(python-mode-hook python-ts-mode-hook) (defun +python-use-correct-flycheck-executables-h () "Use the correct Python executables for Flycheck." (let ((executable python-shell-interpreter)) @@ -86,14 +96,25 @@ (advice-add #'pythonic-activate :after-while #'+modeline-update-env-in-all-windows-h) (advice-add #'pythonic-deactivate :after #'+modeline-clear-env-in-all-windows-h)) - (setq-hook! 'python-mode-hook tab-width python-indent-offset)) + ;; HACK: `python-mode' doesn't update `tab-width' to reflect + ;; `python-indent-offset', causing issues anywhere `tab-width' is respected. + (setq-hook! '(python-mode-hook python-ts-mode-hook) tab-width python-indent-offset) + + ;; HACK: `python-ts-mode' changes `auto-mode-alist' and + ;; `interpreter-mode-alist' every time the mode is activated, which runs the + ;; risk of overwriting user (or Doom) entries. + ;; REVIEW: Should be addressed upstream. + (defadvice! +python--undo-ts-side-effects-a (fn &rest args) + :around #'python-ts-mode + (let (auto-mode-alist interpreter-mode-alist) + (apply fn args)))) (use-package! pyimport :defer t :init (map! :after python - :map python-mode-map + :map python-base-mode-map :localleader :prefix ("i" . "imports") :desc "Insert missing imports" "i" #'pyimport-insert-missing @@ -105,12 +126,13 @@ :defer t :init (map! :after python - :map python-mode-map + :map python-base-mode-map :localleader (:prefix ("i" . "imports") :desc "Sort imports" "s" #'py-isort-buffer :desc "Sort region" "r" #'py-isort-region))) + (use-package! nose :commands nose-mode :preface (defvar nose-mode-map (make-sparse-keymap)) @@ -138,7 +160,7 @@ :init (map! :after python :localleader - :map python-mode-map + :map python-base-mode-map :prefix ("t" . "test") "a" #'python-pytest "f" #'python-pytest-file-dwim @@ -157,7 +179,7 @@ :hook (python-mode . pipenv-mode) :init (setq pipenv-with-projectile nil) :config - (set-eval-handler! 'python-mode + (set-eval-handler! '(python-mode python-ts-mode) '((:command . (lambda () python-shell-interpreter)) (:exec (lambda () (if-let* ((bin (executable-find "pipenv" t)) @@ -165,7 +187,7 @@ (format "PIPENV_MAX_DEPTH=9999 %s run %%c %%o %%s %%a" bin) "%c %o %s %a"))) (:description . "Run Python script"))) - (map! :map python-mode-map + (map! :map python-base-mode-map :localleader :prefix ("e" . "pipenv") :desc "activate" "a" #'pipenv-activate @@ -185,7 +207,8 @@ (add-hook 'pyvenv-post-activate-hooks #'+modeline-update-env-in-all-windows-h) (add-hook 'pyvenv-pre-deactivate-hooks #'+modeline-clear-env-in-all-windows-h)) :config - (add-hook 'python-mode-local-vars-hook #'pyvenv-track-virtualenv) + (add-hook! '(python-mode-local-vars-hook python-ts-mode-local-vars-hook) + #'pyvenv-track-virtualenv) (add-to-list 'global-mode-string '(pyvenv-virtual-env-name (" venv:" pyvenv-virtual-env-name " ")) 'append)) @@ -199,7 +222,8 @@ (when (executable-find "pyenv") (pyenv-mode +1) (add-to-list 'exec-path (expand-file-name "shims" (or (getenv "PYENV_ROOT") "~/.pyenv")))) - (add-hook 'python-mode-local-vars-hook #'+python-pyenv-mode-set-auto-h) + (add-hook! '(python-mode-local-vars-hook python-ts-mode-local-vars-hook) + #'+python-pyenv-mode-set-auto-h) (add-hook 'doom-switch-buffer-hook #'+python-pyenv-mode-set-auto-h)) diff --git a/modules/lang/python/doctor.el b/modules/lang/python/doctor.el index 65928df91..47af20fcd 100644 --- a/modules/lang/python/doctor.el +++ b/modules/lang/python/doctor.el @@ -8,6 +8,10 @@ (modulep! :tools tree-sitter)) "This module requires (:tools tree-sitter)") +(assert! (or (not (modulep! +tree-sitter)) + (fboundp 'python-ts-mode)) + "Can't find `python-ts-mode'; Emacs 29.1+ is required") + (if (not (or (executable-find "python") (executable-find "python3"))) (error! "Couldn't find python in your PATH") diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index e47845e87..f8d32059a 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -48,7 +48,6 @@ (org "https://github.com/milisims/tree-sitter-org" nil nil nil nil) (perl "https://github.com/ganezdragon/tree-sitter-perl" nil nil nil nil) (proto "https://github.com/mitchellh/tree-sitter-proto" nil nil nil nil) - (python "https://github.com/tree-sitter/tree-sitter-python" nil nil nil nil) (r "https://github.com/r-lib/tree-sitter-r" nil nil nil nil) (ruby "https://github.com/tree-sitter/tree-sitter-ruby" nil nil nil nil) (rust "https://github.com/tree-sitter/tree-sitter-rust" nil nil nil nil) From 7cb23f335926283a21c70a0f661e8d783c28e848 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 7 May 2025 19:37:48 -0400 Subject: [PATCH 04/71] feat(markdown): add treesit support --- modules/lang/markdown/README.org | 5 +++++ modules/lang/markdown/config.el | 17 +++++++++++++++++ modules/lang/markdown/doctor.el | 4 ++++ modules/lang/markdown/packages.el | 5 +++++ 4 files changed, 31 insertions(+) diff --git a/modules/lang/markdown/README.org b/modules/lang/markdown/README.org index 72ea069d0..dc2e4660c 100644 --- a/modules/lang/markdown/README.org +++ b/modules/lang/markdown/README.org @@ -33,11 +33,16 @@ for Markdown's syntax is the format of plain text email. -- John Gruber - +grip :: Enable [[https://github.com/seagle0128/grip-mode][grip support]] (on [[kbd:][ p]]), to provide live github-style previews of your markdown (or org) files. +- +tree-sitter :: + Enable tree-sitter support for Markdown files. Note that tree-sitter support + on Emacs 31 is superior to 30 and under. Requires the [[doom-module::tools + tree-sitter]] module. ** Packages - [[doom-package:edit-indirect]] - [[doom-package:evil-markdown]] if [[doom-module::editor evil +everywhere]] - [[doom-package:grip-mode]] if [[doom-module:+grip]] +- [[doom-package:markdown-ts-mode]] if [[doom-module:+tree-sitter]] - [[doom-package:markdown-mode]] - [[doom-package:markdown-toc]] diff --git a/modules/lang/markdown/config.el b/modules/lang/markdown/config.el index 8df215bca..6f5e2111e 100644 --- a/modules/lang/markdown/config.el +++ b/modules/lang/markdown/config.el @@ -126,6 +126,23 @@ capture, the end position, and the output buffer.") :desc "GFM checkbox" "x" #'markdown-toggle-gfm-checkbox))) +(use-package! markdown-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'markdown-ts-mode) + :defer t + :init + (set-tree-sitter! 'markdown-mode 'markdown-ts-mode + '((markdown :url "https://github.com/tree-sitter-grammars/tree-sitter-markdown" + :rev "v0.4.1" + :source-dir "tree-sitter-markdown-inline/src") + (markdown-inline :url "https://github.com/tree-sitter-grammars/tree-sitter-markdown" + :rev "v0.4.1" + :source-dir "tree-sitter-markdown-inline/src"))) + + :config + (cl-callf2 delete '("\\.md\\'" . markdown-ts-mode) auto-mode-alist)) + + (use-package! evil-markdown :when (modulep! :editor evil +everywhere) :hook (markdown-mode . evil-markdown-mode) diff --git a/modules/lang/markdown/doctor.el b/modules/lang/markdown/doctor.el index 6a2d39231..3617565de 100644 --- a/modules/lang/markdown/doctor.el +++ b/modules/lang/markdown/doctor.el @@ -1,6 +1,10 @@ ;; -*- lexical-binding: t; no-byte-compile: t; -*- ;;; lang/markdown/doctor.el +(assert! (or (not (modulep! +tree-sitter)) + (modulep! :tools tree-sitter)) + "This module requires (:tools tree-sitter)") + (when (require 'markdown-mode nil t) (cond ((eq markdown-command #'+markdown-compile) (unless (cl-loop for (exe . cmd) in (list (cons "marked" '+markdown-compile-marked) diff --git a/modules/lang/markdown/packages.el b/modules/lang/markdown/packages.el index 9f3521546..ae6542d1f 100644 --- a/modules/lang/markdown/packages.el +++ b/modules/lang/markdown/packages.el @@ -8,6 +8,11 @@ ;; present when you call `markdown-edit-code-block'. (package! edit-indirect :pin "82a28d8a85277cfe453af464603ea330eae41c05") +(when (modulep! +tree-sitter) + (package! markdown-ts-mode + :built-in 'prefer ; Emacs 31+ has a superior markdown-ts-mode + :pin "2f1ee8b94cdf53cebc31ae08ecfbba846193d5e1")) + (when (modulep! +grip) (package! grip-mode :pin "96a927dce69d7607b981d7754cf8b415ebf9d6a8")) From 445c9828389ca703a44b55c326c1e338659471b1 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 7 May 2025 22:29:23 -0400 Subject: [PATCH 05/71] feat(ruby): add treesit support --- modules/lang/ruby/config.el | 17 ++++++++++++++--- modules/lang/ruby/doctor.el | 4 ++++ modules/tools/tree-sitter/config.el | 1 - 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/modules/lang/ruby/config.el b/modules/lang/ruby/config.el index 1420363c5..0721167aa 100644 --- a/modules/lang/ruby/config.el +++ b/modules/lang/ruby/config.el @@ -22,9 +22,6 @@ (when (modulep! +lsp) (add-hook 'ruby-mode-local-vars-hook #'lsp! 'append)) - (when (modulep! +tree-sitter) - (add-hook 'ruby-mode-local-vars-hook #'tree-sitter! 'append)) - (after! inf-ruby (add-hook 'inf-ruby-mode-hook #'doom-mark-buffer-as-real-h) ;; switch to inf-ruby from compile if we detect a breakpoint has been hit @@ -39,6 +36,20 @@ "{" #'ruby-toggle-block)) +(use-package! ruby-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'ruby-ts-mode) ; 29.1+ only + :defer t + :init + (set-tree-sitter! 'ruby-mode 'ruby-ts-mode + '((ruby :url "https://github.com/tree-sitter/tree-sitter-ruby"))) + :config + (set-electric! 'ruby-ts-mode :words '("else" "end" "elsif")) + (set-repl-handler! 'ruby-ts-mode #'inf-ruby) + (when (modulep! +lsp) + (add-hook 'ruby-ts-mode-local-vars-hook #'lsp! 'append))) + + (use-package! yard-mode :hook ruby-mode) diff --git a/modules/lang/ruby/doctor.el b/modules/lang/ruby/doctor.el index dfc0ecd66..1ab28a7ac 100644 --- a/modules/lang/ruby/doctor.el +++ b/modules/lang/ruby/doctor.el @@ -8,6 +8,10 @@ (modulep! :tools tree-sitter)) "This module requires (:tools tree-sitter)") +(assert! (or (not (modulep! +tree-sitter)) + (fboundp 'ruby-ts-mode)) + "Can't find `ruby-ts-mode'; Emacs 29.1+ is required") + (unless (executable-find "ruby") (warn! "Ruby isn't installed.")) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index f8d32059a..3d18325de 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -49,7 +49,6 @@ (perl "https://github.com/ganezdragon/tree-sitter-perl" nil nil nil nil) (proto "https://github.com/mitchellh/tree-sitter-proto" nil nil nil nil) (r "https://github.com/r-lib/tree-sitter-r" nil nil nil nil) - (ruby "https://github.com/tree-sitter/tree-sitter-ruby" nil nil nil nil) (rust "https://github.com/tree-sitter/tree-sitter-rust" nil nil nil nil) (scala "https://github.com/tree-sitter/tree-sitter-scala" nil nil nil nil) (sql "https://github.com/DerekStride/tree-sitter-sql" "gh-pages" nil nil nil) From f002424106f3e273022ccbc4768f73cf56342ca7 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 7 May 2025 23:42:49 -0400 Subject: [PATCH 06/71] feat(lua): add treesit support --- modules/lang/lua/autoload/lua.el | 21 ++++++++++++ modules/lang/lua/config.el | 52 ++++++++++++++--------------- modules/lang/lua/doctor.el | 13 ++++++++ modules/tools/tree-sitter/config.el | 1 - 4 files changed, 60 insertions(+), 27 deletions(-) create mode 100644 modules/lang/lua/doctor.el diff --git a/modules/lang/lua/autoload/lua.el b/modules/lang/lua/autoload/lua.el index fb10215e8..e5e19b2c1 100644 --- a/modules/lang/lua/autoload/lua.el +++ b/modules/lang/lua/autoload/lua.el @@ -1,5 +1,26 @@ ;;; lang/lua/autoload/lua.el -*- lexical-binding: t; -*- +;;;###autoload +(defvar +lua-lsp-dir (concat doom-data-dir "lsp/lua-language-server/") + "Absolute path to the directory of sumneko's lua-language-server. + +This directory MUST contain the 'main.lua' file and be the in-source build of +lua-language-server.") + +;;;###autoload +(defun +lua-generate-lsp-server-command () + ;; The absolute path to lua-language-server binary is necessary because the + ;; bundled dependencies aren't found otherwise. The only reason this is a + ;; function is to dynamically change when/if `+lua-lsp-dir' does + (list (or (executable-find "lua-language-server") + (doom-path +lua-lsp-dir + (cond ((featurep :system 'macos) "bin/macOS") + ((featurep :system 'linux) "bin/Linux") + ((featurep :system 'windows) "bin/Windows")) + "lua-language-server")) + "-E" "-e" "LANG=en" + (doom-path +lua-lsp-dir "main.lua"))) + (defun +lua-love-build-command () (when-let (root (+lua-love-project-root)) (format "%s %s" diff --git a/modules/lang/lua/config.el b/modules/lang/lua/config.el index cb59dd905..91d95c307 100644 --- a/modules/lang/lua/config.el +++ b/modules/lang/lua/config.el @@ -8,10 +8,11 @@ ;;; Major modes (use-package! lua-mode - :defer t + :interpreter "\\ Date: Thu, 8 May 2025 01:17:54 -0400 Subject: [PATCH 07/71] fix(agda): remove defunct tree-sitter.el support --- modules/lang/agda/config.el | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/modules/lang/agda/config.el b/modules/lang/agda/config.el index fc6a6d863..1a9fe07ad 100644 --- a/modules/lang/agda/config.el +++ b/modules/lang/agda/config.el @@ -11,11 +11,7 @@ (set-lookup-handlers! 'agda2-mode :definition #'agda2-goto-definition-keyboard) - (when (modulep! +tree-sitter) - (set-tree-sitter-lang! 'agda2-mode 'agda) - (add-hook! '(agda-mode-local-vars-hook - agda2-mode-local-vars-hook) - :append #'tree-sitter!)) + ;; TODO: agda2-ts-mode (map! :map agda2-mode-map :localleader From 46b87362f7d4c7aed06e342b47eea1410d655ddf Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 8 May 2025 01:18:07 -0400 Subject: [PATCH 08/71] feat(julia): add treesit support --- modules/lang/julia/README.org | 6 +++--- modules/lang/julia/config.el | 22 +++++++++++++++++----- modules/lang/julia/packages.el | 3 +++ modules/tools/tree-sitter/config.el | 1 - 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/modules/lang/julia/README.org b/modules/lang/julia/README.org index 97f8094b6..fc46fe04f 100644 --- a/modules/lang/julia/README.org +++ b/modules/lang/julia/README.org @@ -15,11 +15,11 @@ This module adds support for [[https://julialang.org/][the Julia language]] to D ** Module flags - +lsp :: - Enable LSP support for ~julia-mode~. Requires [[doom-module::tools lsp]] and a langserver - (supports LanguageServer.jl). + Enable LSP support for ~julia-mode~. Requires [[doom-module::tools lsp]] and a + langserver (supports LanguageServer.jl). - +tree-sitter :: Leverages tree-sitter for better syntax highlighting and structural text - editing. Requires [[doom-module::tools tree-sitter]]. + editing. Requires Emacs >=29 and [[doom-module::tools tree-sitter]]. - +snail :: Use Snail, a development environment and REPL interaction package for Julia in the spirit of Common Lisp’s SLIME and Clojure’s CIDER. It enables convenient diff --git a/modules/lang/julia/config.el b/modules/lang/julia/config.el index 462b42b10..5e944741f 100644 --- a/modules/lang/julia/config.el +++ b/modules/lang/julia/config.el @@ -4,14 +4,11 @@ :interpreter "julia" :config (unless (modulep! +snail) - (set-repl-handler! 'julia-mode #'+julia/open-repl)) + (set-repl-handler! '(julia-mode julia-ts-mode) #'+julia/open-repl)) (when (modulep! +lsp) (add-hook 'julia-mode-local-vars-hook #'lsp! 'append)) - (when (modulep! +tree-sitter) - (add-hook 'julia-mode-local-vars-hook #'tree-sitter! 'append)) - ;; Borrow matlab.el's fontification of math operators. From ;; (dolist (mode '(julia-mode ess-julia-mode)) @@ -47,9 +44,22 @@ 1 font-lock-type-face))))) +(use-package! julia-ts-mode + :when (modulep! +tree-sitter) + :defer t + :init + (set-tree-sitter! 'julia-mode 'julia-ts-mode + '((julia :url "https://github.com/tree-sitter/tree-sitter-julia" + :rev "v0.23.1"))) + :config + (when (modulep! +lsp) + (add-hook 'julia-ts-mode-local-vars-hook #'lsp! 'append))) + + (use-package! julia-repl :preface (defvar +julia-repl-start-hook nil) :hook (julia-mode . julia-repl-mode) + :hook (julia-ts-mode . julia-repl-mode) :hook (+julia-repl-start . +julia-override-repl-escape-char-h) :hook (+julia-repl-start . julia-repl-use-emacsclient) :config @@ -95,7 +105,8 @@ :after eglot :init ;; Prevent timeout while installing LanguageServer.jl - (setq-hook! 'julia-mode-hook eglot-connect-timeout (max eglot-connect-timeout 60)) + (setq-hook! '(julia-mode-hook julia-ts-mode-hook) + eglot-connect-timeout (max eglot-connect-timeout 60)) :config (eglot-jl-init)) @@ -103,6 +114,7 @@ :when (modulep! +snail) :when (modulep! :term vterm) :hook (julia-mode . julia-snail-mode) + :hook (julia-ts-mode . julia-snail-mode) :config (set-popup-rule! "^\\*julia.*\\*$" :ttl nil :select nil :quit nil) diff --git a/modules/lang/julia/packages.el b/modules/lang/julia/packages.el index 6d45f02e5..c35b03300 100644 --- a/modules/lang/julia/packages.el +++ b/modules/lang/julia/packages.el @@ -4,6 +4,9 @@ (package! julia-mode :pin "5c940c4ba357d8361534f11169f3d40b2d7833fc") (package! julia-repl :pin "317d56021889a336b4be241604ba71e46dc80581") +(when (modulep! +tree-sitter) + (package! julia-ts-mode :pin "d693c6b35d3aed986b2700a3b5f910de12d6c53c")) + (when (modulep! +lsp) (if (modulep! :tools lsp +eglot) (package! eglot-jl :pin "7c968cc61fb64016ebe6dc8ff83fd05923db4374") diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index 95a12690c..55197da50 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -38,7 +38,6 @@ (java "https://github.com/tree-sitter/tree-sitter-java" nil nil nil nil) (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src" nil nil) (json "https://github.com/tree-sitter/tree-sitter-json" nil nil nil nil) - (julia "https://github.com/tree-sitter/tree-sitter-julia" nil nil nil nil) (kotlin "https://github.com/fwcd/tree-sitter-kotlin" nil nil nil nil) (latex "https://github.com/latex-lsp/tree-sitter-latex" nil nil nil nil) (make "https://github.com/tree-sitter-grammars/tree-sitter-make" nil nil nil nil) From c403bb5e2f77aa1821345d3a76dabbad2c97e314 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 11 May 2025 00:40:59 -0400 Subject: [PATCH 09/71] feat(csharp): add treesit support --- modules/lang/csharp/config.el | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/modules/lang/csharp/config.el b/modules/lang/csharp/config.el index 38bac4879..d92844558 100644 --- a/modules/lang/csharp/config.el +++ b/modules/lang/csharp/config.el @@ -4,12 +4,12 @@ :hook (csharp-mode . rainbow-delimiters-mode) :config (set-formatter! 'csharpier '("csharpier" "format" "--write-stdout") - :modes '(csharp-mode)) - (set-electric! 'csharp-mode :chars '(?\n ?\})) - (set-rotate-patterns! 'csharp-mode + :modes '(csharp-mode csharp-ts-mode)) + (set-electric! '(csharp-mode csharp-ts-mode) :chars '(?\n ?\})) + (set-rotate-patterns! '(csharp-mode csharp-ts-mode) :symbols '(("public" "protected" "private") ("class" "struct"))) - (set-ligatures! 'csharp-mode + (set-ligatures! '(csharp-mode csharp-ts-mode) ;; Functional :lambda "() =>" ;; Types @@ -30,12 +30,19 @@ :return "return" :yield "yield") - (sp-local-pair 'csharp-mode "<" ">" + (sp-local-pair '(csharp-mode csharp-ts-mode) "<" ">" :when '(+csharp-sp-point-in-type-p) :post-handlers '(("| " "SPC"))) (when (modulep! +lsp) - (add-hook 'csharp-mode-local-vars-hook #'lsp! 'append)) + (add-hook 'csharp-mode-local-vars-hook #'lsp! 'append) + (add-hook 'csharp-ts-mode-local-vars-hook #'lsp! 'append)) + + (when (and (modulep! +tree-sitter) + (fboundp 'csharp-ts-mode)) ; 29.1+ only + (set-tree-sitter! 'csharp-mode 'csharp-ts-mode + '((c-sharp :url "https://github.com/tree-sitter/tree-sitter-c-sharp" + :rev "v0.23.1")))) (defadvice! +csharp-disable-clear-string-fences-a (fn &rest args) "This turns off `c-clear-string-fences' for `csharp-mode'. When @@ -46,24 +53,13 @@ or terminating simple string." (apply fn args)))) -(use-package! csharp-tree-sitter - :when (modulep! +tree-sitter) - :defer t - :init - (add-hook 'csharp-mode-local-vars-hook #'tree-sitter! 'append) - (when (fboundp #'csharp-tree-sitter-mode) - (add-to-list 'auto-mode-alist '("\\.cs\\'" . csharp-tree-sitter-mode)) - (when (modulep! +lsp) - (add-hook 'csharp-tree-sitter-mode-local-vars-hook #'lsp! 'append)))) - - ;; Unity shaders (use-package! shader-mode :when (modulep! +unity) :mode "\\.shader\\'" :config (def-project-mode! +csharp-unity-mode - :modes '(csharp-mode shader-mode) + :modes '(csharp-mode csharp-ts-mode shader-mode) :files (and "Assets" "Library/MonoManager.asset" "Library/ScriptMapper"))) From 1670ce27679f323282c68a21f6e29eac3cc2532e Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 15 May 2025 12:46:58 +0200 Subject: [PATCH 10/71] feat!(cc): add treesit support BREAKING CHANGE: Besides treesit support, this removes a few fontification enhancements (in favor of tree-sitter). --- modules/lang/cc/autoload.el | 61 +++++++-------- modules/lang/cc/config.el | 113 +++++++++++++++++++--------- modules/lang/cc/packages.el | 8 +- modules/tools/tree-sitter/config.el | 4 - 4 files changed, 110 insertions(+), 76 deletions(-) diff --git a/modules/lang/cc/autoload.el b/modules/lang/cc/autoload.el index e809ed225..24e5af191 100644 --- a/modules/lang/cc/autoload.el +++ b/modules/lang/cc/autoload.el @@ -54,32 +54,34 @@ preceded by the opening brace or a comma (disregarding whitespace in between)." This is meant to replace `c-or-c++-mode' (introduced in Emacs 26.1), which doesn't support specification of the fallback mode and whose heuristics are simpler." - (let ((base (file-name-sans-extension (buffer-file-name (buffer-base-buffer))))) - (cond ((file-exists-p! (or (concat base ".cpp") - (concat base ".cc"))) - (c++-mode)) - ((or (file-exists-p! (or (concat base ".m") - (concat base ".mm"))) - (+cc--re-search-for - (concat "^[ \t\r]*\\(?:" - "@\\(?:class\\|interface\\|property\\|end\\)\\_>" - "\\|#import +" - "\\|[-+] ([a-zA-Z0-9_]+)" + (funcall + (major-mode-remap + (let ((base (file-name-sans-extension (buffer-file-name (buffer-base-buffer))))) + (cond ((file-exists-p! (or (concat base ".cpp") + (concat base ".cc"))) + 'c++-mode) + ((or (file-exists-p! (or (concat base ".m") + (concat base ".mm"))) + (+cc--re-search-for + (concat "^[ \t\r]*\\(?:" + "@\\(?:class\\|interface\\|property\\|end\\)\\_>" + "\\|#import +" + "\\|[-+] ([a-zA-Z0-9_]+)" + "\\)"))) + 'objc-mode) + ((+cc--re-search-for + (let ((id "[a-zA-Z0-9_]+") (ws "[ \t\r]+") (ws-maybe "[ \t\r]*")) + (concat "^" ws-maybe "\\(?:" + "using" ws "\\(?:namespace" ws "std;\\|std::\\)" + "\\|" "namespace" "\\(?:" ws id "\\)?" ws-maybe "{" + "\\|" "class" ws id ws-maybe "[:{\n]" + "\\|" "template" ws-maybe "<.*>" + "\\|" "#include" ws-maybe "<\\(?:string\\|iostream\\|map\\)>" "\\)"))) - (objc-mode)) - ((+cc--re-search-for - (let ((id "[a-zA-Z0-9_]+") (ws "[ \t\r]+") (ws-maybe "[ \t\r]*")) - (concat "^" ws-maybe "\\(?:" - "using" ws "\\(?:namespace" ws "std;\\|std::\\)" - "\\|" "namespace" "\\(?:" ws id "\\)?" ws-maybe "{" - "\\|" "class" ws id ws-maybe "[:{\n]" - "\\|" "template" ws-maybe "<.*>" - "\\|" "#include" ws-maybe "<\\(?:string\\|iostream\\|map\\)>" - "\\)"))) - (c++-mode)) - ((functionp +cc-default-header-file-mode) - (funcall +cc-default-header-file-mode)) - ((c-mode))))) + 'c++-mode) + ((functionp +cc-default-header-file-mode) + +cc-default-header-file-mode) + ('c-mode)))))) (defun +cc-resolve-include-paths () (cl-loop with path = (or buffer-file-name default-directory) @@ -137,15 +139,6 @@ the children of class at point." ;; ;; Hooks -;;;###autoload -(defun +cc-fontify-constants-h () - "Better fontification for preprocessor constants" - (when (memq major-mode '(c-mode c++-mode)) - (font-lock-add-keywords - nil '(("\\<[A-Z]*_[0-9A-Z_]+\\>" . font-lock-constant-face) - ("\\<[A-Z]\\{3,\\}\\>" . font-lock-constant-face)) - t))) - (defvar +cc--project-includes-alist nil) ;;;###autoload (defun +cc-init-ffap-integration-h () diff --git a/modules/lang/cc/config.el b/modules/lang/cc/config.el index a1b797271..ca98b4719 100644 --- a/modules/lang/cc/config.el +++ b/modules/lang/cc/config.el @@ -25,17 +25,26 @@ This is ignored by ccls.") ;; set up before lsp is initialized. Also, we use local-vars hooks to ensure ;; these only run in their respective major modes, and not derived modes. :hook ((c-mode-local-vars c++-mode-local-vars objc-mode-local-vars) . +cc-init-ffap-integration-h) + :hook ((c-ts-mode-local-vars c++-ts-mode-local-vars) . +cc-init-ffap-integration-h) ;;; Improve fontification in C/C++ (also see `modern-cpp-font-lock') :hook (c-mode-common . rainbow-delimiters-mode) - :hook ((c-mode c++-mode) . +cc-fontify-constants-h) + :init + (when (modulep! +tree-sitter) + (set-tree-sitter! 'c-mode 'c-ts-mode + '((c :url "https://github.com/tree-sitter/tree-sitter-c"))) + (set-tree-sitter! 'c++-mode 'c++-ts-mode + '((cpp :url "https://github.com/tree-sitter/tree-sitter-cpp")))) + :config - (set-docsets! 'c-mode "C") - (set-docsets! 'c++-mode "C++" "Boost") - (set-electric! '(c-mode c++-mode objc-mode java-mode) :chars '(?\n ?\} ?\{)) + (set-docsets! '(c-mode c-ts-mode) "C") + (set-docsets! '(c++-mode c++-ts-mode) "C++" "Boost") + (set-electric! '(c-mode c++-mode objc-mode java-mode + c-ts-mode c++-ts-mode java-ts-mode) + :chars '(?\n ?\} ?\{)) (set-rotate-patterns! 'c++-mode :symbols '(("public" "protected" "private") ("class" "struct"))) - (set-ligatures! '(c-mode c++-mode) + (set-ligatures! '(c-mode c-ts-mode c++-mode c++-ts-mode) ;; Functional ;; :def "void " ;; Types @@ -54,10 +63,14 @@ This is ignored by ccls.") (add-to-list 'find-sibling-rules '("/\\([^/]+\\)\\.c\\(c\\|pp\\)?\\'" "\\1.h\\(h\\|pp\\)?\\'")) (add-to-list 'find-sibling-rules '("/\\([^/]+\\)\\.h\\(h\\|pp\\)?\\'" "\\1.c\\(c\\|pp\\)?\\'")) - (when (modulep! +tree-sitter) - (add-hook! '(c-mode-local-vars-hook - c++-mode-local-vars-hook) - :append #'tree-sitter!)) + ;; Delete all the default remappings created by the cc-mode package. We define + ;; better ones with `set-tree-sitter!' further below, otherwise there should + ;; be no remapping if the user hasn't explicitly asked for tree-sitter + ;; integration. + (dolist (mode '((c++-mode . c++-ts-mode) + (c-mode . c-ts-mode) + (c-or-c++-mode . c-or-c++-ts-mode))) + (cl-callf2 delete mode major-mode-remap-defaults)) ;; HACK Suppress 'Args out of range' error in when multiple modifications are ;; performed at once in a `c++-mode' buffer, e.g. with `iedit' or @@ -101,52 +114,82 @@ This is ignored by ccls.") (label . 0)))) (when (listp c-default-style) - (setf (alist-get 'other c-default-style) "doom")) - - (after! ffap - (add-to-list 'ffap-alist '(c-mode . ffap-c-mode)))) - - -(use-package! modern-cpp-font-lock - :unless (modulep! +tree-sitter) - :hook (c++-mode . modern-c++-font-lock-mode)) + (setf (alist-get 'other c-default-style) "doom"))) ;; ;; Major modes -(after! cmake-mode - (set-docsets! 'cmake-mode "CMake") +(use-package! cmake-mode + :defer t + :init + (when (and (modulep! +tree-sitter) + (boundp 'cmake-ts-mode)) ; 29+ only + (set-tree-sitter! 'cmake-mode 'cmake-ts-mode + '((cmake :url "https://github.com/uyha/tree-sitter-cmake")))) + :config + (set-docsets! '(cmake-mode cmake-ts-mode) "CMake") (set-popup-rule! "^\\*CMake Help\\*" :size 0.4 :ttl t) - (set-lookup-handlers! 'cmake-mode - :documentation '+cc-cmake-lookup-documentation-fn)) + (set-lookup-handlers! '(cmake-mode cmake-ts-mode) + :documentation '+cc-cmake-lookup-documentation-fn) + (when (require 'company-cmake nil t) + (set-company-backend! '(cmake-mode cmake-ts-mode) 'company-cmake)) + (when (modulep! +lsp) + (add-hook 'cmake-mode-local-vars-hook #'lsp! 'append) + (add-hook 'cmake-ts-mode-local-vars-hook #'lsp! 'append))) -(use-package! company-cmake ; for `cmake-mode' - :when (modulep! :completion company) - :after cmake-mode - :config (set-company-backend! 'cmake-mode 'company-cmake)) +(use-package! glsl-mode + :defer t + :init + (when (modulep! +tree-sitter) ; 29+ only + (set-tree-sitter! 'glsl-mode 'glsl-ts-mode + '((glsl :url "https://github.com/tree-sitter-grammars/tree-sitter-glsl")))) + :config + (when (require 'company-glsl nil t) + (set-company-backend! 'glsl-mode 'company-glsl)) + (when (modulep! +lsp) + (add-hook 'glsl-mode-local-vars-hook #'lsp! 'append) + (add-hook 'glsl-ts-mode-local-vars-hook #'lsp! 'append))) + + +(use-package! cuda-mode + :defer t + :config + (when (modulep! +lsp) + (add-hook 'cuda-mode-local-vars-hook #'lsp! 'append)) + ) + + +(use-package! cuda-ts-mode + :when (modulep! +tree-sitter) + :defer t + :init + (set-tree-sitter! 'cuda-mode 'cuda-ts-mode + '((cuda :url "https://github.com/tree-sitter-grammars/tree-sitter-cuda"))) + :config + (when (modulep! +lsp) + (add-hook 'cuda-ts-mode-local-vars-hook #'lsp! 'append)) + ;; HACK: Remove redundant entries so we can rely solely on + ;; `major-mode-remap-defaults' et co. + (rassq-delete-all 'cuda-ts-mode auto-mode-alist) + (cl-callf2 delete '(cuda "https://github.com/tree-sitter-grammars/tree-sitter-cuda" nil nil nil nil) + treesit-language-source-alist)) (use-package! demangle-mode :hook llvm-mode) -(use-package! company-glsl ; for `glsl-mode' - :when (modulep! :completion company) - :after glsl-mode - :config (set-company-backend! 'glsl-mode 'company-glsl)) - - ;; ;;; LSP (when (modulep! +lsp) (add-hook! '(c-mode-local-vars-hook + c-ts-mode-local-vars-hook c++-mode-local-vars-hook - objc-mode-local-vars-hook - cmake-mode-local-vars-hook - cuda-mode-local-vars-hook) + c++-ts-mode-local-vars-hook + objc-mode-local-vars-hook) :append #'lsp!) (if (modulep! :tools lsp -eglot) diff --git a/modules/lang/cc/packages.el b/modules/lang/cc/packages.el index cb969ca48..d54dfca01 100644 --- a/modules/lang/cc/packages.el +++ b/modules/lang/cc/packages.el @@ -4,13 +4,15 @@ (package! cmake-mode :recipe (:host github :repo "emacsmirror/cmake-mode" :files (:defaults "*")) :pin "b08b5d9045308362a623a4f576896d55ffecfd52") -(package! cuda-mode :pin "c3dae31b3d1abedf4d0b98840127e2cac73d6ad8") (package! demangle-mode :pin "04f545adab066708d6151f13da65aaf519f8ac4e") (package! disaster :pin "8b445913221feb0c196e943106643040118bcd77") (package! opencl-mode :pin "204d5d9e0f5cb2cbe810f2933230eb08fe2c7695") -(unless (modulep! +tree-sitter) - (package! modern-cpp-font-lock :pin "43c6b68ff58fccdf9deef11674a172e4eaa8455c")) +(when (package! cuda-mode :pin "c3dae31b3d1abedf4d0b98840127e2cac73d6ad8") + (when (modulep! +tree-sitter) + (package! cuda-ts-mode + :recipe (:host github :repo "Ergus/cuda-ts-mode") + :pin "807f15150deb3a3060bc36a0e135a27876d7e239"))) (when (package! glsl-mode :pin "86e6bb6cf28d1053366039683a4498401bab9c47") (when (modulep! :completion company) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index 55197da50..78c32cc03 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -20,17 +20,13 @@ (dolist (map '((awk "https://github.com/Beaglefoot/tree-sitter-awk" nil nil nil nil) (bibtex "https://github.com/latex-lsp/tree-sitter-bibtex" nil nil nil nil) (blueprint "https://github.com/huanie/tree-sitter-blueprint" nil nil nil nil) - (c "https://github.com/tree-sitter/tree-sitter-c" nil nil nil nil) (c-sharp "https://github.com/tree-sitter/tree-sitter-c-sharp" nil nil nil nil) (clojure "https://github.com/sogaiu/tree-sitter-clojure" nil nil nil nil) - (cmake "https://github.com/uyha/tree-sitter-cmake" nil nil nil nil) (commonlisp "https://github.com/tree-sitter-grammars/tree-sitter-commonlisp" nil nil nil nil) - (cpp "https://github.com/tree-sitter/tree-sitter-cpp" nil nil nil nil) (css "https://github.com/tree-sitter/tree-sitter-css" nil nil nil nil) (dart "https://github.com/ast-grep/tree-sitter-dart" nil nil nil nil) (dockerfile "https://github.com/camdencheek/tree-sitter-dockerfile" nil nil nil nil) (elixir "https://github.com/elixir-lang/tree-sitter-elixir" nil nil nil nil) - (glsl "https://github.com/tree-sitter-grammars/tree-sitter-glsl" nil nil nil nil) (go "https://github.com/tree-sitter/tree-sitter-go" nil nil nil nil) (gomod "https://github.com/camdencheek/tree-sitter-go-mod" nil nil nil nil) (heex "https://github.com/phoenixframework/tree-sitter-heex" nil nil nil nil) From 8ac83f4600963b74bd8cbd5091df2b56ecfc0f20 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 15 May 2025 14:15:50 +0200 Subject: [PATCH 11/71] fix(indent-guides): treesit support --- modules/ui/indent-guides/config.el | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/modules/ui/indent-guides/config.el b/modules/ui/indent-guides/config.el index 898920d5f..b60191a9c 100644 --- a/modules/ui/indent-guides/config.el +++ b/modules/ui/indent-guides/config.el @@ -21,7 +21,8 @@ be enabled. If any function returns non-nil, the mode will not be activated." (unless (run-hook-with-args-until-success '+indent-guides-inhibit-functions) (indent-bars-mode +1))) :config - (setq indent-bars-prefer-character + (setq indent-bars-treesit-support (modulep! :tools tree-sitter) + indent-bars-prefer-character (or ;; Bitmaps are far slower on MacOS, inexplicably, but this needs more ;; testing to see if it's specific to ns or emacs-mac builds, or is @@ -42,9 +43,6 @@ be enabled. If any function returns non-nil, the mode will not be activated." ;; unnecessary overhead for little benefit. indent-bars-highlight-current-depth nil) - ;; TODO: Uncomment once we support treesit - ;; (setq indent-bars-treesit-support (modulep! :tools tree-sitter)) - ;; indent-bars adds this to `enable-theme-functions', which was introduced in ;; 29.1, which will be redundant with `doom-load-theme-hook'. (unless (boundp 'enable-theme-functions) @@ -105,21 +103,4 @@ be enabled. If any function returns non-nil, the mode will not be activated." (defadvice! +indent-guides--restore-after-lsp-ui-peek-a (&rest _) :after #'lsp-ui-peek--peek-hide (unless indent-bars-prefer-character - (indent-bars-setup)))) - - ;; HACK: Both indent-bars and tree-sitter-hl-mode use the jit-font-lock - ;; mechanism, and so they don't play well together. For those particular - ;; cases, we'll use `highlight-indent-guides', at least until the - ;; tree-sitter module adopts treesit. - (defvar-local +indent-guides-p nil) - (add-hook! 'tree-sitter-mode-hook :append - (defun +indent-guides--toggle-on-tree-sitter-h () - (if tree-sitter-mode - (when (bound-and-true-p indent-bars-mode) - (with-memoization (get 'indent-bars-mode 'disabled-in-tree-sitter) - (doom-log "Disabled `indent-bars-mode' because it's not supported in `tree-sitter-mode'") - t) - (indent-bars-mode -1) - (setq +indent-guides-p t)) - (when +indent-guides-p - (indent-bars-mode +1)))))) + (indent-bars-setup))))) From e0e2c3aa61c35b36f0972cde7f03af79957084f7 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 15 May 2025 17:44:34 +0200 Subject: [PATCH 12/71] feat(janet): add treesit support --- modules/lang/janet/README.org | 4 +++- modules/lang/janet/config.el | 25 ++++++++++++------------- modules/lang/janet/packages.el | 8 ++++---- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/modules/lang/janet/README.org b/modules/lang/janet/README.org index 44cfe98f5..65e09c2ea 100644 --- a/modules/lang/janet/README.org +++ b/modules/lang/janet/README.org @@ -12,7 +12,9 @@ This module adds rudimentary support for the [[https://janet-lang.org/][Janet pr [[doom-contrib-maintainer:][Become a maintainer?]] ** Module flags -/This module has no flags./ +- +tree-sitter :: + Leverages tree-sitter for better syntax highlighting and structural text + editing. Requires [[doom-module::tools tree-sitter]]. ** Packages - [[doom-package:janet-mode]] diff --git a/modules/lang/janet/config.el b/modules/lang/janet/config.el index cf26fbd66..00c4f0a42 100644 --- a/modules/lang/janet/config.el +++ b/modules/lang/janet/config.el @@ -24,16 +24,15 @@ (put sym 'janet-indent-function 'defun))) -;; (use-package! janet-ts-mode -;; :when (modulep! +tree-sitter) -;; :defer t -;; :init -;; (set-tree-sitter! 'janet-mode 'janet-ts-mode -;; `(janet-simple :url "https://github.com/sogaiu/tree-sitter-janet-simple" -;; :cc ,(if (featurep :system 'windows) "gcc.exe"))) -;; :config -;; ;; HACK: These autoloads are inserted twice by this package, so remove them so -;; ;; this module can be the single source of truth. -;; (cl-callf2 delete '("\\.janet\\'" . janet-ts-mode) auto-mode-alist) -;; (cl-callf2 delete '("\\.jdn\\'" . janet-ts-mode) auto-mode-alist) -;; (cl-callf2 delete '("janet" . janet-ts-mode) interpreter-mode-alist)) +(use-package! janet-ts-mode + :when (modulep! +tree-sitter) + :defer t + :init + (set-tree-sitter! 'janet-mode 'janet-ts-mode + `(janet-simple :url "https://github.com/sogaiu/tree-sitter-janet-simple" + :cc ,(if (featurep :system 'windows) "gcc.exe"))) + :config + ;; HACK: These entries are inserted twice by this package, so remove them so + ;; this module can be the single source of truth. + (cl-callf2 rassq-delete-all 'janet-ts-mode auto-mode-alist) + (cl-callf2 rassq-delete-all 'janet-ts-mode interpreter-mode-alist)) diff --git a/modules/lang/janet/packages.el b/modules/lang/janet/packages.el index ba107e355..88409a9d9 100644 --- a/modules/lang/janet/packages.el +++ b/modules/lang/janet/packages.el @@ -5,7 +5,7 @@ :recipe (:files ("*.el")) :pin "9e3254a0249d720d5fa5603f1f8c3ed0612695af") -;; (when (modulep! +tree-sitter) -;; (package! janet-ts-mode -;; :recipe (:host github :repo "sogaiu/janet-ts-mode") -;; :pin "ac684edf57e4d4e085cf99d5ad2ee084b46b8123")) +(when (modulep! +tree-sitter) + (package! janet-ts-mode + :recipe (:host github :repo "sogaiu/janet-ts-mode") + :pin "ac684edf57e4d4e085cf99d5ad2ee084b46b8123")) From 9073b248783e2161a3e2909e23851cf684890813 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 15 May 2025 18:09:56 +0200 Subject: [PATCH 13/71] feat(php): add treesit support --- modules/lang/php/README.org | 2 +- modules/lang/php/config.el | 114 ++++++++++++++++++++++-------------- modules/lang/php/doctor.el | 4 ++ 3 files changed, 74 insertions(+), 46 deletions(-) diff --git a/modules/lang/php/README.org b/modules/lang/php/README.org index 321ce8177..24f7c1f31 100644 --- a/modules/lang/php/README.org +++ b/modules/lang/php/README.org @@ -36,7 +36,7 @@ This module adds support for PHP 5.3+ (including PHP8) to Doom Emacs. langserver (supports [[https://emacs-lsp.github.io/lsp-mode/page/lsp-phpactor/][phpactor]], [[https://emacs-lsp.github.io/lsp-mode/page/lsp-intelephense/][intelephense]], [[https://emacs-lsp.github.io/lsp-mode/page/lsp-serenata/][serenata]], [[https://emacs-lsp.github.io/lsp-mode/page/lsp-php/][php-language-server]]). - +tree-sitter :: Leverages tree-sitter for better syntax highlighting and structural text - editing. Requires [[doom-module::tools tree-sitter]]. + editing. Requires [[doom-module::tools tree-sitter]] and Emacs 30.1+. ** Packages - [[doom-package:async]] diff --git a/modules/lang/php/config.el b/modules/lang/php/config.el index 62b1c405e..fe7460e0f 100644 --- a/modules/lang/php/config.el +++ b/modules/lang/php/config.el @@ -1,7 +1,7 @@ ;;; lang/php/config.el -*- lexical-binding: t; -*- (defvar +php--company-backends nil - "List of company backends to use in `php-mode'.") + "List of company backends to use in `php-mode' and `php-ts-mode'.") (defvar +php-default-docker-container "php-fpm" "The default docker container to run commands in.") @@ -20,18 +20,11 @@ ;; ;;; Packages -(use-package! php-mode - :mode "\\.inc\\'" - :hook (php-mode . rainbow-delimiters-mode) - :config - ;; Disable HTML compatibility in php-mode. `web-mode' has superior support for - ;; php+html. Use the .phtml extension instead. - (setq php-mode-template-compatibility nil) - - (set-docsets! 'php-mode "PHP" "PHPUnit" "Laravel" "CakePHP" "CodeIgniter" "Doctrine_ORM") - (set-repl-handler! 'php-mode #'+php/open-repl) - (set-lookup-handlers! 'php-mode :documentation #'php-search-documentation) - (set-ligatures! 'php-mode +(defun +php-common-config (mode) + (set-docsets! mode "PHP" "PHPUnit" "Laravel" "CakePHP" "CodeIgniter" "Doctrine_ORM") + (set-repl-handler! mode #'+php/open-repl) + (set-lookup-handlers! mode :documentation #'php-search-documentation) + (set-ligatures! mode ;; Functional :lambda "function()" :lambda "fn" :def "function" @@ -49,37 +42,63 @@ :return "return" :yield "use") - (if (modulep! -lsp) - ;; `+php-company-backend' uses `php-extras-company' or - ;; `company-dabbrev-code', in that order. - (when +php--company-backends - (set-company-backend! 'php-mode - (cons :separate +php--company-backends) - 'company-dabbrev-code)) - (when (executable-find "php-language-server.php") - (setq lsp-clients-php-server-command "php-language-server.php")) - (add-hook 'php-mode-local-vars-hook #'lsp! 'append)) + (let ((mode-hook (intern (format "%s-hook" mode))) + (mode-vars-hook (intern (format "%s-local-vars-hook" mode))) + (mode-map (symbol-value (intern (format "%s-map" mode))))) + (sp-with-modes (ensure-list mode) + (sp-local-pair "" :post-handlers '(("| " "SPC" "=") ("||\n[i]" "RET") ("[d2]" "p"))) + (sp-local-pair "" :post-handlers '(("| " "SPC") ("||\n[i]" "RET")))) - (when (modulep! +tree-sitter) - (add-hook 'php-mode-local-vars-hook #'tree-sitter! 'append)) + (if (modulep! -lsp) + ;; `+php-company-backend' uses `php-extras-company' or + ;; `company-dabbrev-code', in that order. + (when +php--company-backends + (set-company-backend! mode + (cons :separate +php--company-backends) + 'company-dabbrev-code)) + (when (executable-find "php-language-server.php") + (setq lsp-clients-php-server-command "php-language-server.php")) + (add-hook mode-vars-hook #'lsp! 'append)) - ;; Use the smallest `sp-max-pair-length' for optimum `smartparens' performance - (setq-hook! 'php-mode-hook sp-max-pair-length 5) + (map! :localleader + :map ,mode-map + :prefix ("t" . "test") + "r" #'phpunit-current-project + "a" #'phpunit-current-class + "s" #'phpunit-current-test))) - (sp-with-modes '(php-mode) - (sp-local-pair "" :post-handlers '(("| " "SPC" "=") ("||\n[i]" "RET") ("[d2]" "p"))) - (sp-local-pair "" :post-handlers '(("| " "SPC") ("||\n[i]" "RET")))) - (map! :localleader - :map php-mode-map - :prefix ("t" . "test") - "r" #'phpunit-current-project - "a" #'phpunit-current-class - "s" #'phpunit-current-test)) +(use-package! php-mode + :hook (php-mode . rainbow-delimiters-mode) + :config + (+php-common-config 'php-mode) + + ;; Disable HTML compatibility in php-mode. `web-mode' has superior support for + ;; php+html. Use the .phtml extension instead. + (setq php-mode-template-compatibility nil)) + + +(use-package! php-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'php-ts-mode) ; 30.1+ only + :defer t + :init + (set-tree-sitter! 'php-mode 'php-ts-mode + '((php :url "https://github.com/tree-sitter/tree-sitter-php" + :rev "v0.23.11" + :source-dir "php/src") + (phpdoc :url "https://github.com/claytonrcarter/tree-sitter-phpdoc"))) + :config + ;; HACK: Rely on `major-mode-remap-defaults'. + (cl-callf2 rassq-delete-all 'php-ts-mode auto-mode-alist) + (cl-callf2 rassq-delete-all 'php-ts-mode interpreter-mode-alist) + + (+php-common-config 'php-ts-mode)) (use-package! php-refactor-mode :hook php-mode + :hook php-ts-mode :config (map! :localleader :map php-refactor-mode-map @@ -91,7 +110,7 @@ (use-package! php-extras - :after php-mode + :after (:or php-mode php-ts-mode) :preface (setq php-extras-eldoc-functions-file (concat doom-profile-cache-dir "php-extras-eldoc-functions")) @@ -124,10 +143,9 @@ (use-package! composer :defer t :init - (map! :after php-mode - :localleader - :map php-mode-map - :prefix ("c" . "composer") + (setq composer-directory-to-managed-file (file-name-concat doom-etc-dir "composer/")) + (defvar +php-common-mode-map (make-sparse-keymap)) + (map! :map +php-common-mode-map "c" #'composer "i" #'composer-install "r" #'composer-require @@ -136,23 +154,29 @@ "s" #'composer-run-script "v" #'composer-run-vendor-bin-command "o" #'composer-find-json-file - "l" #'composer-view-lock-file)) + "l" #'composer-view-lock-file) + (map! :after php-mode + :map php-mode-map + :desc "composer" "c" +php-common-mode-map) + (map! :after php-ts-mode + :map php-ts-mode-map + :desc "composer" "c" +php-common-mode-map)) ;; ;; Projects (def-project-mode! +php-laravel-mode - :modes '(php-mode yaml-mode web-mode nxml-mode js2-mode scss-mode) + :modes '(php-mode php-ts-mode yaml-mode web-mode nxml-mode js2-mode scss-mode) :files (and "artisan" "server.php")) (def-project-mode! +php-composer-mode - :modes '(web-mode php-mode) + :modes '(web-mode php-mode php-ts-mode) :files ("composer.json")) (def-project-mode! +phpunit-docker-compose-mode :when +php-run-tests-in-docker - :modes '(php-mode docker-compose-mode) + :modes '(php-mode php-ts-mode docker-compose-mode) :files (and "phpunit.xml" (or +php-default-docker-compose "docker-compose.yml")) :on-enter (setq phpunit-args `("exec" ,+php-default-docker-container "php" "vendor/bin/phpunit") diff --git a/modules/lang/php/doctor.el b/modules/lang/php/doctor.el index 6094a4c75..426927e54 100644 --- a/modules/lang/php/doctor.el +++ b/modules/lang/php/doctor.el @@ -9,6 +9,10 @@ (modulep! :tools tree-sitter)) "This module requires (:tools tree-sitter)") +(assert! (or (not (modulep! +tree-sitter)) + (fboundp 'php-ts-mode)) + "Can't find `php-ts-mode'; Emacs 30.1+ is required") + (unless (executable-find "php") (warn! "Couldn't find php in your PATH")) From 5be0df24d32fd6278f01de3b9f502144b7c41ad1 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 15 May 2025 18:17:15 +0200 Subject: [PATCH 14/71] docs(csharp,julia,lua,markdown): mention +tree-sitter requirements --- modules/lang/csharp/README.org | 2 +- modules/lang/julia/README.org | 2 +- modules/lang/lua/README.org | 4 ++-- modules/lang/markdown/README.org | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/lang/csharp/README.org b/modules/lang/csharp/README.org index fcde71183..6fdcd1498 100644 --- a/modules/lang/csharp/README.org +++ b/modules/lang/csharp/README.org @@ -18,7 +18,7 @@ LSP). (supports =omnisharp-roslyn=). - +tree-sitter :: Leverages tree-sitter for better syntax highlighting and structural text - editing. Requires [[doom-module::tools tree-sitter]]. + editing. Requires Emacs 29.1+ and [[doom-module::tools tree-sitter]]. - +unity :: Enable special support for the [[https://unity.com/][Unity game engine]] (particularly, support for HLSL shaders). diff --git a/modules/lang/julia/README.org b/modules/lang/julia/README.org index fc46fe04f..c3fcb25ea 100644 --- a/modules/lang/julia/README.org +++ b/modules/lang/julia/README.org @@ -19,7 +19,7 @@ This module adds support for [[https://julialang.org/][the Julia language]] to D langserver (supports LanguageServer.jl). - +tree-sitter :: Leverages tree-sitter for better syntax highlighting and structural text - editing. Requires Emacs >=29 and [[doom-module::tools tree-sitter]]. + editing. Requires [[doom-module::tools tree-sitter]]. - +snail :: Use Snail, a development environment and REPL interaction package for Julia in the spirit of Common Lisp’s SLIME and Clojure’s CIDER. It enables convenient diff --git a/modules/lang/lua/README.org b/modules/lang/lua/README.org index a07e0ecec..ffdfbb6af 100644 --- a/modules/lang/lua/README.org +++ b/modules/lang/lua/README.org @@ -24,8 +24,8 @@ This module adds Lua support to Doom Emacs. (supports EmmyLua, lua-language-server, and lua-lsp). - +tree-sitter :: Leverages tree-sitter for better syntax highlighting and structural text - editing. Requires [[doom-module::tools tree-sitter]]. Has support for both Lua and - Fennel. + editing. Requires Emacs 30.1+ and [[doom-module::tools tree-sitter]]. Only + supports Lua at the moment. - +moonscript :: Enable support for the Moonscript language. diff --git a/modules/lang/markdown/README.org b/modules/lang/markdown/README.org index dc2e4660c..7e43708b0 100644 --- a/modules/lang/markdown/README.org +++ b/modules/lang/markdown/README.org @@ -34,9 +34,9 @@ for Markdown's syntax is the format of plain text email. -- John Gruber Enable [[https://github.com/seagle0128/grip-mode][grip support]] (on [[kbd:][ p]]), to provide live github-style previews of your markdown (or org) files. - +tree-sitter :: - Enable tree-sitter support for Markdown files. Note that tree-sitter support - on Emacs 31 is superior to 30 and under. Requires the [[doom-module::tools - tree-sitter]] module. + Leverages tree-sitter for better syntax highlighting and structural text + editing. Requires [[doom-module::tools tree-sitter]]. Note that tree-sitter + support on Emacs 31 is superior to 30 and under. ** Packages - [[doom-package:edit-indirect]] From 8931c48913c625eb734679a363d2307498d095ac Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 15 May 2025 18:31:55 +0200 Subject: [PATCH 15/71] fix(cc): treesit modes not remapped to c-ts-mode and c++-ts-mode weren't being remapped to from c-mode/c++-mode because of extra noise in `major-mode-remap-defaults`. I wish these packages would leave these variables alone and leave it to the user to configure; they're often inconsistent and overbearing. --- modules/lang/cc/config.el | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/lang/cc/config.el b/modules/lang/cc/config.el index ca98b4719..9ef2f5fb2 100644 --- a/modules/lang/cc/config.el +++ b/modules/lang/cc/config.el @@ -41,7 +41,7 @@ This is ignored by ccls.") (set-electric! '(c-mode c++-mode objc-mode java-mode c-ts-mode c++-ts-mode java-ts-mode) :chars '(?\n ?\} ?\{)) - (set-rotate-patterns! 'c++-mode + (set-rotate-patterns! '(c++-mode c++-ts-mode) :symbols '(("public" "protected" "private") ("class" "struct"))) (set-ligatures! '(c-mode c-ts-mode c++-mode c++-ts-mode) @@ -70,7 +70,9 @@ This is ignored by ccls.") (dolist (mode '((c++-mode . c++-ts-mode) (c-mode . c-ts-mode) (c-or-c++-mode . c-or-c++-ts-mode))) - (cl-callf2 delete mode major-mode-remap-defaults)) + (cl-callf2 delete mode major-mode-remap-defaults) + (cl-callf2 delete (list (car mode)) major-mode-remap-defaults) + (cl-callf2 rassq-delete-all (cdr mode) auto-mode-alist)) ;; HACK Suppress 'Args out of range' error in when multiple modifications are ;; performed at once in a `c++-mode' buffer, e.g. with `iedit' or @@ -142,7 +144,7 @@ This is ignored by ccls.") (use-package! glsl-mode :defer t :init - (when (modulep! +tree-sitter) ; 29+ only + (when (modulep! +tree-sitter) (set-tree-sitter! 'glsl-mode 'glsl-ts-mode '((glsl :url "https://github.com/tree-sitter-grammars/tree-sitter-glsl")))) :config From 2556cb58f263cbf2c46f62295a751a81c71e31e8 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 15 May 2025 18:55:42 +0200 Subject: [PATCH 16/71] feat(yaml): add treesit support --- modules/lang/yaml/README.org | 4 ++-- modules/lang/yaml/config.el | 20 ++++++++++++++++---- modules/lang/yaml/doctor.el | 9 +++++++++ 3 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 modules/lang/yaml/doctor.el diff --git a/modules/lang/yaml/README.org b/modules/lang/yaml/README.org index 7d9542f6c..3a50238b2 100644 --- a/modules/lang/yaml/README.org +++ b/modules/lang/yaml/README.org @@ -11,8 +11,8 @@ This module provides support for the [[https://yaml.org/][YAML file format]] to ** Module flags - +lsp :: - Enable LSP support for ~yaml-mode~. Requires [[doom-module::tools lsp]] and a langserver - (supports [[https://github.com/redhat-developer/yaml-language-server][yaml-language-server]]). + Enable LSP support for ~yaml-mode~. Requires [[doom-module::tools lsp]] and a + langserver (supports [[https://github.com/redhat-developer/yaml-language-server][yaml-language-server]]). - +tree-sitter :: Leverages tree-sitter for better syntax highlighting and structural text editing. Requires [[doom-module::tools tree-sitter]]. diff --git a/modules/lang/yaml/config.el b/modules/lang/yaml/config.el index 684568c44..8a5cbb90f 100644 --- a/modules/lang/yaml/config.el +++ b/modules/lang/yaml/config.el @@ -2,10 +2,22 @@ (use-package! yaml-mode :mode "Procfile\\'" - :init + :config (when (modulep! +lsp) (add-hook 'yaml-mode-local-vars-hook #'lsp! 'append)) - (when (modulep! +tree-sitter) - (add-hook 'yaml-mode-local-vars-hook #'tree-sitter! 'append)) - :config (setq-hook! 'yaml-mode-hook tab-width yaml-indent-offset)) + + +(use-package! yaml-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'yaml-ts-mode) ; 29.1+ only + :init + (set-tree-sitter! 'yaml-mode 'yaml-ts-mode + '((yaml :url "https://github.com/tree-sitter-grammars/tree-sitter-yaml" + :rev "v0.7.0"))) + :config + ;; HACK: Rely on `major-mode-remap-defaults'. + (cl-callf2 rassq-delete-all 'yaml-ts-mode auto-mode-alist) + + (when (modulep! +lsp) + (add-hook 'yaml-ts-mode-local-vars-hook #'lsp! 'append))) diff --git a/modules/lang/yaml/doctor.el b/modules/lang/yaml/doctor.el new file mode 100644 index 000000000..73d4086c9 --- /dev/null +++ b/modules/lang/yaml/doctor.el @@ -0,0 +1,9 @@ +;;; lang/yaml/doctor.el -*- lexical-binding: t; -*- + +(assert! (or (not (modulep! +lsp)) + (modulep! :tools lsp)) + "This module requires (:tools lsp)") + +(assert! (or (not (modulep! +tree-sitter)) + (modulep! :tools tree-sitter)) + "This module requires (:tools tree-sitter)") From b5465222573419b8880fd4e442fab4c7274f6c06 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 15 May 2025 18:55:52 +0200 Subject: [PATCH 17/71] docs(tree-sitter): revise doctor output --- modules/tools/tree-sitter/doctor.el | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/tools/tree-sitter/doctor.el b/modules/tools/tree-sitter/doctor.el index f5ebe8731..4a32abf4f 100644 --- a/modules/tools/tree-sitter/doctor.el +++ b/modules/tools/tree-sitter/doctor.el @@ -1,8 +1,10 @@ ;;; tools/tree-sitter/doctor.el -*- lexical-binding: t; -*- (unless (fboundp 'module-load) - (warn! "Emacs was not built with dynamic modules support, which the treesit.el library requires")) + (error! "Emacs not built with dynamic modules support")) -(unless (and (fboundp 'treesit-available-p) - (treesit-available-p)) - (error! "Treesit library not available. Did you build Emacs with tree-sitter support?")) +(if (version< emacs-version "29.1") + (error! "Emacs 29.1 or newer is required for tree-sitter support") + (unless (and (fboundp 'treesit-available-p) + (treesit-available-p)) + (error! "Emacs not built with tree-sitter support!"))) From 776da0dcf18e63cde43a0ddd0015e1678bfb3433 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 16 May 2025 08:46:21 +0200 Subject: [PATCH 18/71] fix(csharp): csharp-ts-mode: side-effects on auto-mode-alist Would otherwise be imposed every time the mode is activated. --- modules/lang/csharp/config.el | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/lang/csharp/config.el b/modules/lang/csharp/config.el index d92844558..08f99fab2 100644 --- a/modules/lang/csharp/config.el +++ b/modules/lang/csharp/config.el @@ -50,6 +50,14 @@ on for `csharp-mode' font lock breaks after an interpolated string or terminating simple string." :around #'csharp-disable-clear-string-fences (unless (eq major-mode 'csharp-mode) + (apply fn args))) + + ;; HACK: `csharp-ts-mode' changes `auto-mode-alist' every time the mode is + ;; activated, which runs the risk of overwriting user (or Doom) entries. + ;; REVIEW: Should be addressed upstream. + (defadvice! +csharp--undo-ts-side-effects-a (fn &rest args) + :around #'csharp-ts-mode + (let (auto-mode-alist) (apply fn args)))) From a329d63f7db541c5a056f572dbbc8b8b57b5f5c4 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 16 May 2025 08:49:20 +0200 Subject: [PATCH 19/71] fix(tree-sitter): discard COMMIT recipe argument on <=30.x Otherwise `treesit--install-language-grammar-1` will throw an arity error on Emacs <=30.x when installing grammars. Fix: #8393 --- .../tools/tree-sitter/autoload/tree-sitter.el | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/modules/tools/tree-sitter/autoload/tree-sitter.el b/modules/tools/tree-sitter/autoload/tree-sitter.el index 1797c56e4..93680a06c 100644 --- a/modules/tools/tree-sitter/autoload/tree-sitter.el +++ b/modules/tools/tree-sitter/autoload/tree-sitter.el @@ -5,16 +5,21 @@ (message "Old tree-sitter.el support is deprecated!")) ;;;###autodef (fset 'set-tree-sitter! #'ignore) -(defun set-tree-sitter! (mode ts-mode &optional langs) +(defun set-tree-sitter! (mode ts-mode &optional recipes) "Remap major MODE to TS-MODE. -MODE and TS-MODE are major mode symbols. If LANGS is provided, fall back to MODE -if LANGS don't pass `treesit-ready-p' when activating TS-MODE. Use this for ts -modes that error out instead of failing gracefully." +MODE and TS-MODE are major mode symbols. If RECIPES is provided, fall back to +MODE if RECIPES don't pass `treesit-ready-p' when activating TS-MODE. Use this +for ts modes that error out instead of failing gracefully. + +RECIPES are an alist of plists with the format (LANG &key URL REV SOURCE-DIR CC +CPP COMMIT), which will be transformed into entries for +`treesit-language-source-alist' (which descrie what each of these keys mean). +Note that COMMIT is only available in Emacs >=31." (declare (indent 2)) (cl-check-type mode symbol) (cl-check-type ts-mode symbol) - (setq langs (ensure-list langs)) + (setq recipes (ensure-list recipes)) (dolist (m (ensure-list mode)) (add-to-list 'major-mode-remap-defaults @@ -24,7 +29,7 @@ modes that error out instead of failing gracefully." (funcall ;; Because standard major-mode remapping doesn't offer graceful ;; failure in some cases, I implement it myself: - (cond ((null langs) m) + (cond ((null recipes) m) ((not (fboundp ts-mode)) (message "Couldn't find %S, using %S instead" ts-mode m) m) @@ -35,19 +40,25 @@ modes that error out instead of failing gracefully." (cl-every (if ensured? (doom-rpartial #'treesit-ready-p 'message) #'treesit-ensure-installed) - (cl-loop for lang in langs - if (listp lang) - collect (car lang) - else collect (list lang)))) + (cl-loop for r in recipes + if (listp r) + collect (car r) + else collect (list r)))) ts-mode) ((setq ensured? t) m)))))))) (with-eval-after-load 'treesit - (dolist (lang langs) - (when (and lang (listp lang)) - (cl-destructuring-bind (name &key url rev source-dir cc cpp commit) lang - (setf (alist-get name treesit-language-source-alist) - (list url rev source-dir cc cpp commit))))))) + (dolist (recipe recipes) + (cl-destructuring-bind (name &key url rev source-dir cc cpp commit) + (ensure-list recipe) + (setf (alist-get name treesit-language-source-alist) + (append (list url rev source-dir cc cpp) + ;; COMPAT: 31.1 introduced a COMMIT recipe argument. On + ;; <=30.x, extra arguments will trigger an arity error + ;; when installing grammars. + (if (eq (cdr (func-arity 'treesit--install-language-grammar-1)) + 'many) + (list commit)))))))) ;; ;; HACK: Remove and refactor when `use-package' eager macro expansion is solved or `use-package!' is removed ;; ;;;###autoload From 0c311a517250262425fafd62d162c0683434c252 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 22 May 2025 18:06:19 +0200 Subject: [PATCH 20/71] feat(elixir): add treesit support --- modules/lang/elixir/README.org | 6 ++-- modules/lang/elixir/config.el | 53 +++++++++++++++++++++-------- modules/lang/elixir/doctor.el | 4 +++ modules/tools/tree-sitter/config.el | 2 -- 4 files changed, 45 insertions(+), 20 deletions(-) diff --git a/modules/lang/elixir/README.org b/modules/lang/elixir/README.org index c1189cccf..9615660ee 100644 --- a/modules/lang/elixir/README.org +++ b/modules/lang/elixir/README.org @@ -11,11 +11,11 @@ This module provides support for [[https://elixir-lang.org/][Elixir programming ** Module flags - +lsp :: - Enable LSP support for ~elixir-mode~. Requires [[doom-module::tools lsp]] and a langserver - (supports [[https://github.com/elixir-lsp/elixir-ls/][elixir-ls]]). + Enable LSP support for ~elixir-mode~. Requires [[doom-module::tools lsp]] and a + langserver (supports [[https://github.com/elixir-lsp/elixir-ls/][elixir-ls]]). - +tree-sitter :: Leverages tree-sitter for better syntax highlighting and structural text - editing. Requires [[doom-module::tools tree-sitter]]. + editing. Requires Emacs 30.1+ and [[doom-module::tools tree-sitter]]. ** Packages - [[doom-package:elixir-mode]] diff --git a/modules/lang/elixir/config.el b/modules/lang/elixir/config.el index d49f5d9aa..8d1f6a1aa 100644 --- a/modules/lang/elixir/config.el +++ b/modules/lang/elixir/config.el @@ -8,14 +8,8 @@ ;; ;;; Packages -(use-package! elixir-mode - :defer t - :init - ;; Disable default smartparens config. There are too many pairs; we only want - ;; a subset of them (defined below). - (provide 'smartparens-elixir) - :config - (set-ligatures! 'elixir-mode +(defun +elixir-common-config (mode) + (set-ligatures! mode ;; Functional :def "def" :lambda "fn" @@ -29,7 +23,7 @@ :return "return" :yield "use") ;; ...and only complete the basics - (sp-with-modes 'elixir-mode + (sp-with-modes mode (sp-local-pair "do" "end" :when '(("RET" "")) :unless '(sp-in-comment-p sp-in-string-p) @@ -37,16 +31,22 @@ (sp-local-pair "do " " end" :unless '(sp-in-comment-p sp-in-string-p)) (sp-local-pair "fn " " end" :unless '(sp-in-comment-p sp-in-string-p))) - (when (modulep! +lsp +tree-sitter) - (add-hook 'elixir-ts-mode-local-vars-hook #'lsp! 'append)) + (when (modulep! +lsp) + (add-hook (intern (format "%s-local-vars-hook" mode)) #'lsp! 'append))) + + +(use-package! elixir-mode + :defer t + :init + ;; Disable default smartparens config. There are too many pairs; we only want + ;; a subset of them (defined below). + (provide 'smartparens-elixir) (when (modulep! +lsp) - (add-hook 'elixir-mode-local-vars-hook #'lsp! 'append) (after! lsp-mode (add-to-list 'lsp-file-watch-ignored-directories "[/\\\\]_build\\'"))) - - (when (modulep! +tree-sitter) - (add-hook 'elixir-mode-local-vars-hook #'tree-sitter! 'append)) + :config + (+elixir-common-config 'elixir-mode) (after! highlight-numbers (puthash 'elixir-mode @@ -54,6 +54,29 @@ highlight-numbers-modelist))) +(use-package! elixir-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'elixir-ts-mode) ; 30.1+ only + :defer t + :init + (set-tree-sitter! 'elixir-mode 'elixir-ts-mode + '((elixir :url "https://github.com/elixir-lang/tree-sitter-elixir" + :rev "v0.3.3") + (heex :url "https://github.com/phoenixframework/tree-sitter-heex" + :rev "v0.7.0"))) + :config + ;; HACK: Rely on `major-mode-remap-defaults'. + (cl-callf2 rassq-delete-all 'php-ts-mode auto-mode-alist) + + (+elixir-common-config 'elixir-ts-mode)) + + +(use-package! heex-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'heex-ts-mode) ; 30.1+ only + :mode "\\.[hl]?eex\\'") + + (use-package! flycheck-credo :when (modulep! :checkers syntax -flymake) :after elixir-mode diff --git a/modules/lang/elixir/doctor.el b/modules/lang/elixir/doctor.el index 2c0306692..a6c454108 100644 --- a/modules/lang/elixir/doctor.el +++ b/modules/lang/elixir/doctor.el @@ -4,3 +4,7 @@ (assert! (or (not (modulep! +tree-sitter)) (modulep! :tools tree-sitter)) "This module requires (:tools tree-sitter)") + +(assert! (or (not (modulep! +tree-sitter)) + (fboundp 'elixir-ts-mode)) + "Can't find `elixir-ts-mode'; Emacs 30.1+ is required") diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index 78c32cc03..d6f14220e 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -26,10 +26,8 @@ (css "https://github.com/tree-sitter/tree-sitter-css" nil nil nil nil) (dart "https://github.com/ast-grep/tree-sitter-dart" nil nil nil nil) (dockerfile "https://github.com/camdencheek/tree-sitter-dockerfile" nil nil nil nil) - (elixir "https://github.com/elixir-lang/tree-sitter-elixir" nil nil nil nil) (go "https://github.com/tree-sitter/tree-sitter-go" nil nil nil nil) (gomod "https://github.com/camdencheek/tree-sitter-go-mod" nil nil nil nil) - (heex "https://github.com/phoenixframework/tree-sitter-heex" nil nil nil nil) (html "https://github.com/tree-sitter/tree-sitter-html" nil nil nil nil) (java "https://github.com/tree-sitter/tree-sitter-java" nil nil nil nil) (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src" nil nil) From 5db361b4747b6b5dc2b9159dff071a488ce959bb Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 22 May 2025 18:29:43 +0200 Subject: [PATCH 21/71] fix(tree-sitter): remove redundant yaml source Amend: 2556cb58f263 --- modules/tools/tree-sitter/config.el | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index d6f14220e..d74a8a3c2 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -54,8 +54,7 @@ (vue "https://github.com/tree-sitter-grammars/tree-sitter-vue" nil nil nil nil) (wast "https://github.com/wasm-lsp/tree-sitter-wasm" nil "wast/src" nil nil) (wat "https://github.com/wasm-lsp/tree-sitter-wasm" nil "wat/src" nil nil) - (wgsl "https://github.com/mehmetoguzderin/tree-sitter-wgsl" nil nil nil nil) - (yaml "https://github.com/tree-sitter-grammars/tree-sitter-yaml" nil nil nil nil))) + (wgsl "https://github.com/mehmetoguzderin/tree-sitter-wgsl" nil nil nil nil))) (cl-pushnew map treesit-language-source-alist :test #'eq :key #'car))) From c5dd2847ffafd41f4f652983959c491dfbf2e362 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 22 May 2025 19:32:30 +0200 Subject: [PATCH 22/71] feat(scala): add treesit support --- modules/lang/scala/README.org | 3 +- modules/lang/scala/config.el | 62 +++++++++++++++++++---------- modules/lang/scala/doctor.el | 4 ++ modules/lang/scala/packages.el | 4 ++ modules/tools/tree-sitter/config.el | 1 - 5 files changed, 52 insertions(+), 22 deletions(-) diff --git a/modules/lang/scala/README.org b/modules/lang/scala/README.org index e6107a387..d22a6ab77 100644 --- a/modules/lang/scala/README.org +++ b/modules/lang/scala/README.org @@ -30,11 +30,12 @@ Through the power of [[https://scalameta.org/metals/docs/editors/overview.html][ (supports metals). - +tree-sitter :: Leverages tree-sitter for better syntax highlighting and structural text - editing. Requires [[doom-module::tools tree-sitter]]. + editing. Requires Emacs 29.1+ and [[doom-module::tools tree-sitter]]. ** Packages - [[doom-package:sbt-mode]] - [[doom-package:scala-mode]] +- [[doom-package:scala-ts-mode]] if [[doom-module:+tree-sitter]] - [[doom-package:lsp-metals]] if [[doom-module:+lsp]] ** Hacks diff --git a/modules/lang/scala/config.el b/modules/lang/scala/config.el index d42e879db..80a9ed0f0 100644 --- a/modules/lang/scala/config.el +++ b/modules/lang/scala/config.el @@ -7,24 +7,12 @@ ;; ;;; Packages -(after! scala-mode - (setq scala-indent:align-parameters t - ;; indent block comments to first asterix, not second - scala-indent:use-javadoc-style t) - - (setq-hook! 'scala-mode-hook - comment-line-break-function #'+scala-comment-indent-new-line-fn) - - (when (modulep! +lsp) - (setq-hook! 'scala-mode-hook lsp-enable-indentation nil) - (add-hook 'scala-mode-local-vars-hook #'lsp! 'append)) - - (when (modulep! +tree-sitter) - (add-hook 'scala-mode-local-vars-hook #'tree-sitter! 'append)) - - (set-formatter! 'scalafmt '("scalafmt" "--stdin") :modes '(scala-mode)) - - (set-ligatures! 'scala-mode +(defun +scala-common-config (mode) + (set-formatter! 'scalafmt '("scalafmt" "--stdin") + :modes (list mode)) + (set-repl-handler! mode #'+scala/open-repl + :persist t) + (set-ligatures! mode ;; Functional :def "def" :composition "compose" @@ -49,9 +37,43 @@ ;; Other :union "union" :intersect "intersect" - :diff "diff")) + :diff "diff") + + (when (modulep! +lsp) + (add-hook (intern (format "%s-local-vars-hook" mode)) #'lsp! 'append))) + + +(after! scala-mode + (setq scala-indent:align-parameters t + ;; indent block comments to first asterix, not second + scala-indent:use-javadoc-style t) + + (setq-hook! 'scala-mode-hook + comment-line-break-function #'+scala-comment-indent-new-line-fn + lsp-enable-indentation nil) + + (+scala-common-config 'scala-mode)) + + +(use-package! scala-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'treesit-available-p) + :defer t + :init + (set-tree-sitter! 'scala-mode 'scala-ts-mode + '((scala :url "https://github.com/tree-sitter/tree-sitter-scala"))) + + :config + (when (modulep! +lsp) + (setq-hook! 'scala-ts-mode-hook lsp-enable-indentation nil) + (add-hook 'scala-ts-mode-local-vars-hook #'lsp! 'append)) + + ;; HACK: Rely on `major-mode-remap-defaults'. + (cl-callf2 assq-delete-all 'scala-ts-mode auto-mode-alist) + + (+scala-common-config 'scala-ts-mode)) (use-package! sbt-mode :after scala-mode - :config (set-repl-handler! 'scala-mode #'+scala/open-repl :persist t)) + :config (set-repl-handler! '(scala-mode scala-ts-mode) #'+scala/open-repl :persist t)) diff --git a/modules/lang/scala/doctor.el b/modules/lang/scala/doctor.el index fc72e2f18..4ba6b07d2 100644 --- a/modules/lang/scala/doctor.el +++ b/modules/lang/scala/doctor.el @@ -8,6 +8,10 @@ (modulep! :tools tree-sitter)) "This module requires (:tools tree-sitter)") +(assert! (or (not (modulep! +tree-sitter)) + (version< emacs-version "29.1")) + "Emacs 29.1+ is required for tree-sitter support") + (if (and (modulep! +lsp) (not (executable-find "metals"))) (warn! "metals isn't installed")) diff --git a/modules/lang/scala/packages.el b/modules/lang/scala/packages.el index 6289243ff..ea3e43fa5 100644 --- a/modules/lang/scala/packages.el +++ b/modules/lang/scala/packages.el @@ -4,6 +4,10 @@ (package! sbt-mode :pin "cc68728a6ef0600aad369157b3a2d0ce56afba9b") (package! scala-mode :pin "661337d8aa0a0cb418184c83757661603de3b2e3") +(when (and (modulep! +tree-sitter) + (fboundp 'treesit-available-p)) + (package! scala-ts-mode :pin "c7671e10419261ef70b1820d3b970ad39f6fcfe2")) + (when (and (modulep! +lsp) (modulep! :tools lsp -eglot)) (package! lsp-metals :pin "e1d9d04f3bab7e6e74916054b36ab1a87e831367")) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index d74a8a3c2..2bd9cb31c 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -42,7 +42,6 @@ (proto "https://github.com/mitchellh/tree-sitter-proto" nil nil nil nil) (r "https://github.com/r-lib/tree-sitter-r" nil nil nil nil) (rust "https://github.com/tree-sitter/tree-sitter-rust" nil nil nil nil) - (scala "https://github.com/tree-sitter/tree-sitter-scala" nil nil nil nil) (sql "https://github.com/DerekStride/tree-sitter-sql" "gh-pages" nil nil nil) (surface "https://github.com/connorlay/tree-sitter-surface" nil nil nil nil) (toml "https://github.com/tree-sitter/tree-sitter-toml" nil nil nil nil) From f5a1af4bf62be1070c66c797ce8cd423d667bdab Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 22 May 2025 19:50:04 +0200 Subject: [PATCH 23/71] feat(kotlin): add treesit support --- modules/lang/kotlin/README.org | 4 ++++ modules/lang/kotlin/config.el | 17 +++++++++++++++-- modules/lang/kotlin/packages.el | 4 ++++ modules/tools/tree-sitter/config.el | 1 - 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/modules/lang/kotlin/README.org b/modules/lang/kotlin/README.org index af35162ab..878071c01 100644 --- a/modules/lang/kotlin/README.org +++ b/modules/lang/kotlin/README.org @@ -13,10 +13,14 @@ This module adds [[https://kotlinlang.org/][Kotlin]] support to Doom Emacs. - +lsp :: Enable LSP support for ~kotlin-mode~. Requires [[doom-module::tools lsp]] and a langserver (supports [[https://github.com/emacs-lsp/lsp-mode][kotlin-language-server]]). +- +tree-sitter :: + Leverages tree-sitter for better syntax highlighting and structural text + editing. Requires Emacs 29.1+ and [[doom-module::tools tree-sitter]]. ** Packages - [[doom-package:flycheck-kotlin]] if [[doom-module::checkers syntax]] - [[doom-package:kotlin-mode]] +- [[doom-package:kotlin-ts-mode]] ** Hacks /No hacks documented for this module./ diff --git a/modules/lang/kotlin/config.el b/modules/lang/kotlin/config.el index db22b89ac..06a6a34bb 100644 --- a/modules/lang/kotlin/config.el +++ b/modules/lang/kotlin/config.el @@ -1,11 +1,12 @@ ;;; lang/kotlin/config.el -*- lexical-binding: t; -*- (after! kotlin-mode - (when (modulep! +lsp) - (add-hook 'kotlin-mode-local-vars-hook #'lsp! 'append)) (set-docsets! 'kotlin-mode "Kotlin") (set-repl-handler! 'kotlin-mode #'kotlin-repl) + (when (modulep! +lsp) + (add-hook 'kotlin-mode-local-vars-hook #'lsp! 'append)) + (map! :map kotlin-mode-map :localleader :prefix ("b" . "build") @@ -17,3 +18,15 @@ (use-package! flycheck-kotlin :when (modulep! :checkers syntax -flymake) :hook (kotlin-mode . flycheck-kotlin-setup)) + + +(use-package! kotlin-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'treesit-available-p) + :defer t + :init + (set-tree-sitter! 'kotlin-mode 'kotlin-ts-mode + '((kotlin :url "https://github.com/fwcd/tree-sitter-kotlin"))) + :config + (when (modulep! +lsp) + (add-hook 'kotlin-ts-mode-local-vars-hook #'lsp! 'append))) diff --git a/modules/lang/kotlin/packages.el b/modules/lang/kotlin/packages.el index 8d1c42bc0..849823a42 100644 --- a/modules/lang/kotlin/packages.el +++ b/modules/lang/kotlin/packages.el @@ -3,5 +3,9 @@ (package! kotlin-mode :pin "fddd747e5b4736e8b27a147960f369b86179ddff") +(when (and (modulep! +tree-sitter) + (fboundp 'treesit-available-p)) + (package! kotlin-ts-mode :pin "a25d56cecac9160ba7c140f982ec16ca7b2fe97f")) + (when (modulep! :checkers syntax -flymake) (package! flycheck-kotlin :pin "a2a6abb9a7f85c6fb15ce327459ec3c8ff780188")) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index 2bd9cb31c..640005c81 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -32,7 +32,6 @@ (java "https://github.com/tree-sitter/tree-sitter-java" nil nil nil nil) (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src" nil nil) (json "https://github.com/tree-sitter/tree-sitter-json" nil nil nil nil) - (kotlin "https://github.com/fwcd/tree-sitter-kotlin" nil nil nil nil) (latex "https://github.com/latex-lsp/tree-sitter-latex" nil nil nil nil) (make "https://github.com/tree-sitter-grammars/tree-sitter-make" nil nil nil nil) (nix "https://github.com/nix-community/tree-sitter-nix" nil nil nil nil) From 7af7280f9ec1b5543dddf5d5fb32db5f574933ef Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 22 May 2025 19:53:10 +0200 Subject: [PATCH 24/71] feat(json): add treesit support --- modules/lang/json/README.org | 2 +- modules/lang/json/config.el | 25 ++++++++++++++++++------- modules/tools/tree-sitter/config.el | 1 - 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/modules/lang/json/README.org b/modules/lang/json/README.org index 996335237..5bcecde7b 100644 --- a/modules/lang/json/README.org +++ b/modules/lang/json/README.org @@ -15,7 +15,7 @@ This module adds [[https://www.json.org/json-en.html][JSON]] support to Doom Ema (supports [[https://github.com/vscode-langservers/vscode-json-languageserver][vscode-json-languageserver]]). - +tree-sitter :: Leverages tree-sitter for better syntax highlighting and structural text - editing. Requires [[doom-module::tools tree-sitter]]. + editing. Requires Emacs 29.1+ and [[doom-module::tools tree-sitter]]. ** Packages - [[doom-package:counsel-jq]] if [[doom-module::completion ivy]] diff --git a/modules/lang/json/config.el b/modules/lang/json/config.el index cd789b2a0..3f9fe6529 100644 --- a/modules/lang/json/config.el +++ b/modules/lang/json/config.el @@ -2,16 +2,12 @@ (use-package! json-mode :mode "\\.js\\(?:on\\|[hl]int\\(?:rc\\)?\\)\\'" - :init - (when (modulep! +lsp) - (add-hook 'json-mode-local-vars-hook #'lsp! 'append)) - (when (modulep! +tree-sitter) - (add-hook! '(json-mode-local-vars-hook - jsonc-mode-local-vars-hook) - :append #'tree-sitter!)) :config (set-electric! 'json-mode :chars '(?\n ?: ?{ ?})) + (when (modulep! +lsp) + (add-hook 'json-mode-local-vars-hook #'lsp! 'append)) + (map! :after json-mode :map json-mode-map :localleader @@ -24,6 +20,21 @@ "f" #'json-mode-beautify)) +(use-package! json-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'json-ts-mode) ; 29.1+ only + :defer t + :init + (set-tree-sitter! 'json-mode 'json-ts-mode + '((json :url "https://github.com/tree-sitter/tree-sitter-json" + :rev "v0.24.8"))) + :config + ;; HACK: Rely on `major-mode-remap-defaults'. + (cl-callf2 assq-delete-all 'json-ts-mode auto-mode-alist) + + (when (modulep! +lsp) + (add-hook 'json-ts-mode-local-vars-hook #'lsp! 'append))) + (use-package! counsel-jq :when (modulep! :completion ivy) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index 640005c81..3fffcfeb7 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -31,7 +31,6 @@ (html "https://github.com/tree-sitter/tree-sitter-html" nil nil nil nil) (java "https://github.com/tree-sitter/tree-sitter-java" nil nil nil nil) (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src" nil nil) - (json "https://github.com/tree-sitter/tree-sitter-json" nil nil nil nil) (latex "https://github.com/latex-lsp/tree-sitter-latex" nil nil nil nil) (make "https://github.com/tree-sitter-grammars/tree-sitter-make" nil nil nil nil) (nix "https://github.com/nix-community/tree-sitter-nix" nil nil nil nil) From 3b2caa7dcd0380b23fa464e47c91fccee6d2cbd5 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 24 May 2025 16:56:48 +0200 Subject: [PATCH 25/71] feat(docker): add treesit support --- modules/tools/docker/README.org | 3 +++ modules/tools/docker/config.el | 13 +++++++++++++ modules/tools/docker/doctor.el | 8 ++++++++ modules/tools/tree-sitter/config.el | 1 - 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/modules/tools/docker/README.org b/modules/tools/docker/README.org index bc42c463d..64936fb34 100644 --- a/modules/tools/docker/README.org +++ b/modules/tools/docker/README.org @@ -18,6 +18,9 @@ functions allow images to be built easily. ** Module flags - +lsp :: Enable integration for the Dockerfile Language Server. +- +tree-sitter :: + Leverages tree-sitter for better syntax highlighting and structural text + editing. Requires Emacs 29.1+ and [[doom-module::tools tree-sitter]]. ** Packages - [[doom-package:docker]] diff --git a/modules/tools/docker/config.el b/modules/tools/docker/config.el index d030acd85..3e523be48 100644 --- a/modules/tools/docker/config.el +++ b/modules/tools/docker/config.el @@ -6,3 +6,16 @@ (when (modulep! +lsp) (add-hook 'dockerfile-mode-local-vars-hook #'lsp! 'append))) + + +(use-package! dockerfile-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'dockerfile-ts-mode) ; 29.1+ only + :defer t + :init + (set-tree-sitter! 'dockerfile-mode 'dockerfile-ts-mode + '((dockerfile :url "https://github.com/camdencheek/tree-sitter-dockerfile" + :rev "v0.2.0"))) + :config + ;; HACK: Rely on `major-mode-remap-defaults' instead + (cl-callf2 rassq-delete-all 'dockerfile-ts-mode auto-mode-alist)) diff --git a/modules/tools/docker/doctor.el b/modules/tools/docker/doctor.el index d84713e7c..597781cd7 100644 --- a/modules/tools/docker/doctor.el +++ b/modules/tools/docker/doctor.el @@ -1,5 +1,13 @@ ;;; tools/docker/doctor.el -*- lexical-binding: t; -*- +(assert! (or (not (modulep! +tree-sitter)) + (modulep! :tools tree-sitter)) + "This module requires (:tools tree-sitter)") + +(assert! (or (not (modulep! +tree-sitter)) + (fboundp 'dockerfile-ts-mode)) + "Can't find `dockerfile-ts-mode'; Emacs 29.1+ is required") + (when (modulep! :editor format) (unless (executable-find "dockfmt") (warn! "Couldn't find dockfmt. Formatting will be disabled."))) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index 3fffcfeb7..4857193f5 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -25,7 +25,6 @@ (commonlisp "https://github.com/tree-sitter-grammars/tree-sitter-commonlisp" nil nil nil nil) (css "https://github.com/tree-sitter/tree-sitter-css" nil nil nil nil) (dart "https://github.com/ast-grep/tree-sitter-dart" nil nil nil nil) - (dockerfile "https://github.com/camdencheek/tree-sitter-dockerfile" nil nil nil nil) (go "https://github.com/tree-sitter/tree-sitter-go" nil nil nil nil) (gomod "https://github.com/camdencheek/tree-sitter-go-mod" nil nil nil nil) (html "https://github.com/tree-sitter/tree-sitter-html" nil nil nil nil) From 9acc5f48b6e2d8b8d29a0d5c07a775cc33904116 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 24 May 2025 17:18:08 +0200 Subject: [PATCH 26/71] feat(zig): add treesit support --- modules/lang/zig/README.org | 3 ++- modules/lang/zig/config.el | 50 ++++++++++++++++++++++++------------ modules/lang/zig/packages.el | 4 +++ 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/modules/lang/zig/README.org b/modules/lang/zig/README.org index 4a0e7aa70..41dad18d1 100644 --- a/modules/lang/zig/README.org +++ b/modules/lang/zig/README.org @@ -22,10 +22,11 @@ This module adds [[https://ziglang.org/][Zig]] support, with optional (but recom this. - +tree-sitter :: Leverages tree-sitter for better syntax highlighting and structural text - editing. Requires [[doom-module::tools tree-sitter]]. + editing. Requires Emacs 29.1+ and [[doom-module::tools tree-sitter]]. ** Packages - [[doom-package:zig-mode]] +- [[doom-package:zig-ts-mode]] if [[doom-module:+tree-sitter]] ** Hacks /No hacks documented for this module./ diff --git a/modules/lang/zig/config.el b/modules/lang/zig/config.el index 8bf21a29c..52adc3bf2 100644 --- a/modules/lang/zig/config.el +++ b/modules/lang/zig/config.el @@ -8,30 +8,46 @@ ;; ;;; Packages -(use-package! zig-mode - :hook (zig-mode . rainbow-delimiters-mode) - :config - (setq zig-format-on-save nil) ; rely on :editor format instead - +(defun +zig-common-config (mode) (when (modulep! +lsp) - (add-hook 'zig-mode-local-vars-hook #'lsp! 'append)) + (add-hook (intern (format "%s-local-vars-hook" mode)) #'lsp! 'append)) + (map! :localleader + :map ,(symbol-value (intern (format "%s-map" mode))) + "b" #'zig-compile + "f" #'zig-format-buffer + "r" #'zig-run + "t" #'zig-test-buffer)) - (when (modulep! +tree-sitter) - (add-hook 'zig-mode-local-vars-hook #'tree-sitter! 'append)) - (when (modulep! :checkers syntax -flymake) +(when (modulep! :checkers syntax -flymake) + (after! flycheck (eval '(flycheck-define-checker zig "A zig syntax checker using zig's `ast-check` command." :command ("zig" "ast-check" (eval (buffer-file-name))) :error-patterns ((error line-start (file-name) ":" line ":" column ": error: " (message) line-end)) - :modes zig-mode) + :modes (zig-mode zig-ts-mode)) t) - (add-to-list 'flycheck-checkers 'zig)) + (add-to-list 'flycheck-checkers 'zig))) - (map! :localleader - :map zig-mode-map - "b" #'zig-compile - "f" #'zig-format-buffer - "r" #'zig-run - "t" #'zig-test-buffer)) + +(use-package! zig-mode + :hook (zig-mode . rainbow-delimiters-mode) + :config + (setq zig-format-on-save nil) ; rely on :editor format instead + (+zig-common-config 'zig-mode)) + + +(use-package! zig-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'zig-ts-mode) + :defer t + :init + (set-tree-sitter! 'zig-mode 'zig-ts-mode + '((zig :url "https://github.com/tree-sitter/zig-tree-sitter" + :rev "v0.25.0"))) + :config + ;; HACK: Rely on `major-mode-remap-defaults' + (cl-callf2 rassq-delete-all 'zig-ts-mode auto-mode-alist) + + (+zig-common-config 'zig-ts-mode)) diff --git a/modules/lang/zig/packages.el b/modules/lang/zig/packages.el index 0a86d0cf5..a37af95db 100644 --- a/modules/lang/zig/packages.el +++ b/modules/lang/zig/packages.el @@ -2,3 +2,7 @@ ;;; lang/zig/packages.el (package! zig-mode :pin "c46d024733b7c1d6af829bb610fc9629b060bc9e") + +(when (and (modulep! +tree-sitter) + (fboundp 'treesit-available-p)) + (package! zig-ts-mode :pin "3898b70d6f72da688e086323fa2922f1542d1318")) From 5b37bfee23fdc7e5b800489b29b7dd9470355e98 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 24 May 2025 17:27:30 +0200 Subject: [PATCH 27/71] feat(nix): add treesit support --- modules/lang/nix/README.org | 12 +++--- modules/lang/nix/config.el | 60 +++++++++++++++++++---------- modules/lang/nix/doctor.el | 8 ++-- modules/lang/nix/packages.el | 4 ++ modules/tools/tree-sitter/config.el | 1 - 5 files changed, 52 insertions(+), 33 deletions(-) diff --git a/modules/lang/nix/README.org b/modules/lang/nix/README.org index 1752a3b84..e4931cee7 100644 --- a/modules/lang/nix/README.org +++ b/modules/lang/nix/README.org @@ -19,20 +19,18 @@ Includes: [[doom-contrib-maintainer:][Become a maintainer?]] ** Module flags +- +lsp :: + Enable an LSP hook for ~nix-mode~. Requires [[doom-module::tools lsp]] and a + language server (one of either ~nil~ or ~rnix-lsp~). - +tree-sitter :: Leverages tree-sitter for better syntax highlighting and structural text - editing. Requires [[doom-module::tools tree-sitter]]. -- +lsp :: - Enable an LSP hook for ~nix-mode~. Requires [[doom-module::tools lsp]] and a language - server (one of either ~nil~ or ~rnix-lsp~). - - You can still start a nix lsp manually without this flag, this just adds - a hook to always start the lsp when loading ~nix-mode~. + editing. Requires Emacs 29.1+ and [[doom-module::tools tree-sitter]]. ** Packages - [[doom-package:company-nixos-options]] if [[doom-module::completion company]] - [[doom-package:helm-nixos-options]] if [[doom-module::completion helm]] - [[doom-package:nix-mode]] +- [[doom-package:nix-ts-mode]] if [[doom-module:+tree-sitter]] - [[doom-package:nix-update]] ** Hacks diff --git a/modules/lang/nix/config.el b/modules/lang/nix/config.el index 10bfb1731..ced4ef98a 100644 --- a/modules/lang/nix/config.el +++ b/modules/lang/nix/config.el @@ -7,33 +7,25 @@ ;; ;;; Plugins -(use-package! nix-mode - :interpreter ("\\(?:cached-\\)?nix-shell" . +nix-shell-init-mode) - :mode "\\.nix\\'" - :init - (add-to-list 'auto-mode-alist - (cons "/flake\\.lock\\'" - (if (modulep! :lang json) - 'json-mode - 'js-mode))) - :config - (set-repl-handler! 'nix-mode #'+nix/open-repl) - (set-company-backend! 'nix-mode 'company-nixos-options) - (set-lookup-handlers! 'nix-mode +(add-to-list 'auto-mode-alist + (cons "/flake\\.lock\\'" + (if (modulep! :lang json) + 'json-mode + 'js-mode))) + + +(defun +nix-common-config (mode) + (set-repl-handler! mode #'+nix/open-repl) + (set-company-backend! mode 'company-nixos-options) + (set-lookup-handlers! mode :documentation '(+nix/lookup-option :async t)) (set-popup-rule! "^\\*nixos-options-doc\\*$" :ttl 0 :quit t) - ;; Fix #3927: disable idle completion because `company-nixos-options' is - ;; dreadfully slow. It can still be invoked manually.. - (setq-hook! 'nix-mode-hook company-idle-delay nil) - (when (modulep! +lsp) - (add-hook 'nix-mode-local-vars-hook #'lsp! 'append)) - (when (modulep! +tree-sitter) - (add-hook 'nix-mode-local-vars-hook #'tree-sitter! 'append)) + (add-hook (intern (format "%s-local-vars-hook" mode)) #'lsp! 'append)) (map! :localleader - :map nix-mode-map + :map ,(symbol-value (intern (format "%s-map" mode))) "f" #'nix-update-fetch "p" #'nix-format-buffer "r" #'nix-repl-show @@ -43,6 +35,32 @@ "o" #'+nix/lookup-option)) +(use-package! nix-mode + :interpreter ("\\(?:cached-\\)?nix-shell" . +nix-shell-init-mode) + :mode "\\.nix\\'" + :config + (+nix-common-config 'nix-mode)) + + +(use-package! nix-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'treesit-available-p) + :defer t + :init + (set-tree-sitter! 'nix-mode 'nix-ts-mode + '((nix :url "https://github.com/nix-community/tree-sitter-nix"))) + :config + (+nix-common-config 'nix-ts-mode)) + + +(use-package! company-nixos-options + :defer t + :init + ;; Fix #3927: disable idle completion because `company-nixos-options' is + ;; dreadfully slow. It can still be invoked manually.. + (setq-hook! '(nix-mode-hook nix-ts-mode-hook) company-idle-delay nil)) + + (use-package! nix-update :commands nix-update-fetch) diff --git a/modules/lang/nix/doctor.el b/modules/lang/nix/doctor.el index 366d273e7..1a8c0f0e3 100644 --- a/modules/lang/nix/doctor.el +++ b/modules/lang/nix/doctor.el @@ -1,13 +1,13 @@ ;; -*- lexical-binding: t; no-byte-compile: t; -*- ;;; lang/nix/doctor.el +(assert! (or (modulep! -tree-sitter) + (modulep! :tools tree-sitter)) + "This module requires (:tools tree-sitter)") + (unless (executable-find "nix") (warn! "Couldn't find the nix package manager. nix-mode won't work.")) (when (require 'nix-mode nil t) (unless (executable-find nix-nixfmt-bin) (warn! (concat "Couldn't find " nix-nixfmt-bin ". nix-format-buffer won't work.")))) - -(assert! (or (modulep! -tree-sitter) - (modulep! :tools tree-sitter)) - "This module requires (:tools tree-sitter)") diff --git a/modules/lang/nix/packages.el b/modules/lang/nix/packages.el index 6ce4debbc..f76d55da8 100644 --- a/modules/lang/nix/packages.el +++ b/modules/lang/nix/packages.el @@ -4,6 +4,10 @@ (package! nix-mode :pin "719feb7868fb567ecfe5578f6119892c771ac5e5") (package! nix-update :pin "77022ccd918d665acbb519b243e7e3dc5eae1c47") +(when (and (modulep! +tree-sitter) + (fboundp 'treesit-available-p)) + (package! nix-ts-mode :pin "62ce3a2dc39529c5db3516427e84b2c96b8efcfd")) + (when (modulep! :completion company) (package! company-nixos-options :pin "053a2d5110ce05b7f99bcc2ac4804b70cbe87916")) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index 4857193f5..299cf2796 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -32,7 +32,6 @@ (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src" nil nil) (latex "https://github.com/latex-lsp/tree-sitter-latex" nil nil nil nil) (make "https://github.com/tree-sitter-grammars/tree-sitter-make" nil nil nil nil) - (nix "https://github.com/nix-community/tree-sitter-nix" nil nil nil nil) (nu "https://github.com/nushell/tree-sitter-nu" nil nil nil nil) (org "https://github.com/milisims/tree-sitter-org" nil nil nil nil) (perl "https://github.com/ganezdragon/tree-sitter-perl" nil nil nil nil) From 4df993d683ec1f228c94c745375a3c48906264fe Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 28 Jun 2025 17:37:24 +0200 Subject: [PATCH 28/71] fix(tree-sitter): unable to find local grammars Ref: #7623 --- modules/tools/tree-sitter/config.el | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index 299cf2796..1791b5a6b 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -9,6 +9,7 @@ :defer t :config ;; HACK: treesit lacks any way to dictate where to install grammars. + (add-to-list 'treesit-extra-load-path doom-profile-data-dir) (defadvice! +tree-sitter--install-grammar-to-local-dir-a (fn &rest args) "Write grammars to `doom-profile-data-dir'." :around #'treesit-install-language-grammar From 22e03d7e9018b1a6252cf1d50f89e27cf5f96cd1 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 28 Jun 2025 17:40:18 +0200 Subject: [PATCH 29/71] fix(elixir): duplicate auto-mode-alist entries Due to copypasta typo. Amend: 0c311a517250 --- modules/lang/elixir/config.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/lang/elixir/config.el b/modules/lang/elixir/config.el index 8d1f6a1aa..6572fc195 100644 --- a/modules/lang/elixir/config.el +++ b/modules/lang/elixir/config.el @@ -65,8 +65,9 @@ (heex :url "https://github.com/phoenixframework/tree-sitter-heex" :rev "v0.7.0"))) :config - ;; HACK: Rely on `major-mode-remap-defaults'. - (cl-callf2 rassq-delete-all 'php-ts-mode auto-mode-alist) + ;; HACK: Rely on `major-mode-remap-defaults' (and elixir-mode's autoloaded + ;; auto-mode-alist entries). + (cl-callf2 rassq-delete-all 'elixir-ts-mode auto-mode-alist) (+elixir-common-config 'elixir-ts-mode)) From 617d8411e6a1ef5141ac93a1c881c0ef3f081f57 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 28 Jun 2025 19:32:27 +0200 Subject: [PATCH 30/71] fix(tree-sitter): ignore major-mode-remap-defaults for ts modes ...registered with `set-tree-sitter!`. Then we don't have to chase after packages inconsistently modifying `major-mode-remap-defaults`. --- modules/lang/cc/config.el | 11 ----------- .../tools/tree-sitter/autoload/tree-sitter.el | 2 +- modules/tools/tree-sitter/config.el | 17 +++++++++++++++++ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/modules/lang/cc/config.el b/modules/lang/cc/config.el index 9ef2f5fb2..a5ffeb737 100644 --- a/modules/lang/cc/config.el +++ b/modules/lang/cc/config.el @@ -63,17 +63,6 @@ This is ignored by ccls.") (add-to-list 'find-sibling-rules '("/\\([^/]+\\)\\.c\\(c\\|pp\\)?\\'" "\\1.h\\(h\\|pp\\)?\\'")) (add-to-list 'find-sibling-rules '("/\\([^/]+\\)\\.h\\(h\\|pp\\)?\\'" "\\1.c\\(c\\|pp\\)?\\'")) - ;; Delete all the default remappings created by the cc-mode package. We define - ;; better ones with `set-tree-sitter!' further below, otherwise there should - ;; be no remapping if the user hasn't explicitly asked for tree-sitter - ;; integration. - (dolist (mode '((c++-mode . c++-ts-mode) - (c-mode . c-ts-mode) - (c-or-c++-mode . c-or-c++-ts-mode))) - (cl-callf2 delete mode major-mode-remap-defaults) - (cl-callf2 delete (list (car mode)) major-mode-remap-defaults) - (cl-callf2 rassq-delete-all (cdr mode) auto-mode-alist)) - ;; HACK Suppress 'Args out of range' error in when multiple modifications are ;; performed at once in a `c++-mode' buffer, e.g. with `iedit' or ;; multiple cursors. diff --git a/modules/tools/tree-sitter/autoload/tree-sitter.el b/modules/tools/tree-sitter/autoload/tree-sitter.el index 93680a06c..b0721316c 100644 --- a/modules/tools/tree-sitter/autoload/tree-sitter.el +++ b/modules/tools/tree-sitter/autoload/tree-sitter.el @@ -22,7 +22,7 @@ Note that COMMIT is only available in Emacs >=31." (setq recipes (ensure-list recipes)) (dolist (m (ensure-list mode)) (add-to-list - 'major-mode-remap-defaults + '+tree-sitter--major-mode-remaps-alist (cons m (let (ensured?) (lambda () diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index 1791b5a6b..c3f4e8017 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -1,5 +1,8 @@ ;;; tools/tree-sitter/config.el -*- lexical-binding: t; -*- +(defvar +tree-sitter--major-mode-remaps-alist nil) + + ;; ;;; Packages @@ -17,6 +20,20 @@ (let ((user-emacs-directory doom-profile-data-dir)) (apply fn args))) + ;; HACK: Some *-ts-mode packages modify `major-mode-remap-defaults' + ;; inconsistently. Playing whack-a-mole to undo those changes is more hassle + ;; then simply ignoring them (by overriding `major-mode-remap-defaults' for + ;; any modes remapped with `set-tree-sitter!'). The user shouldn't touch + ;; `major-mode-remap-defaults' anyway; `major-mode-remap-alist' will always + ;; have precedence. + (defadvice! +tree-sitter--ignore-default-major-mode-remaps-a (fn mode) + :around #'major-mode-remap + (let ((major-mode-remap-defaults + (if-let* ((m (assq mode +tree-sitter--major-mode-remaps-alist))) + +tree-sitter--major-mode-remaps-alist + major-mode-remap-defaults))) + (funcall fn mode))) + ;; TODO: Move most of these out to modules (dolist (map '((awk "https://github.com/Beaglefoot/tree-sitter-awk" nil nil nil nil) (bibtex "https://github.com/latex-lsp/tree-sitter-bibtex" nil nil nil nil) From 3155fefd470164e0c5bca4f01f37f5662ba13d30 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 28 Jun 2025 19:41:29 +0200 Subject: [PATCH 31/71] feat(swift): add treesit support --- modules/lang/swift/README.org | 1 + modules/lang/swift/config.el | 13 +++++++++---- modules/lang/swift/packages.el | 3 +++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/modules/lang/swift/README.org b/modules/lang/swift/README.org index 510653c2b..dabc650d4 100644 --- a/modules/lang/swift/README.org +++ b/modules/lang/swift/README.org @@ -19,6 +19,7 @@ This module adds support for the [[https://developer.apple.com/swift/][Swift pro ** Packages - [[doom-package:swift-mode]] +- [[doom-package:swift-ts-mode]] if [[doom-module:+tree-sitter]] - if [[doom-module:+lsp]] - [[doom-package:lsp-sourcekit]] - else diff --git a/modules/lang/swift/config.el b/modules/lang/swift/config.el index de11b40a2..8a16bdb0f 100644 --- a/modules/lang/swift/config.el +++ b/modules/lang/swift/config.el @@ -1,13 +1,18 @@ ;;; lang/swift/config.el -*- lexical-binding: t; -*- -(after! swift-mode +(use-package! swift-mode + :defer t + :init + (when (modulep! +tree-sitter) + (set-tree-sitter! 'swift-mode 'swift-ts-mode + '((swift :url "https://github.com/alex-pinkus/tree-sitter-swift")))) + + :config (set-repl-handler! 'swift-mode #'run-swift) (set-eglot-client! 'swift-mode '("sourcekit-lsp")) (when (modulep! +lsp) - (add-hook 'swift-mode-local-vars-hook #'lsp! 'append)) - (when (modulep! +tree-sitter) - (add-hook 'swift-mode-local-vars-hook #'tree-sitter! 'append))) + (add-hook 'swift-mode-local-vars-hook #'lsp! 'append))) (use-package! flycheck-swift diff --git a/modules/lang/swift/packages.el b/modules/lang/swift/packages.el index 2448d0ab0..56206450b 100644 --- a/modules/lang/swift/packages.el +++ b/modules/lang/swift/packages.el @@ -10,3 +10,6 @@ (package! company-sourcekit :pin "a1860ad4dd3a542acd2fa0dfac2a388cbdf4af0c")) (when (modulep! :checkers syntax -flymake) (package! flycheck-swift :pin "4c5ad401252400a78da395fd56a71e67ff8c2761"))) + +(when (modulep! +tree-sitter) + (package! swift-ts-mode :pin "43a0be79f9758fc444f5fafdff6023c4c7bf80f7")) From 7c6e1950e8d46a2ef904224602ebd7940623657c Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 28 Jun 2025 20:10:08 +0200 Subject: [PATCH 32/71] feat(go): add treesit support --- modules/lang/go/config.el | 35 ++++++++++++++++++++--------- modules/lang/go/doctor.el | 4 ++++ modules/tools/tree-sitter/config.el | 2 -- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/modules/lang/go/config.el b/modules/lang/go/config.el index e26bf19ec..469f5189b 100644 --- a/modules/lang/go/config.el +++ b/modules/lang/go/config.el @@ -3,19 +3,16 @@ ;; ;;; Packages -(after! go-mode - (set-docsets! 'go-mode "Go") - (set-repl-handler! 'go-mode #'gorepl-run) - (set-lookup-handlers! 'go-mode +(defun +go-common-config (mode) + (set-docsets! mode "Go") + (set-repl-handler! mode #'gorepl-run) + (set-lookup-handlers! mode :documentation #'godoc-at-point) (when (modulep! +lsp) - (add-hook 'go-mode-local-vars-hook #'lsp! 'append)) + (add-hook (intern (format "%s-local-vars-hook" mode)) #'lsp! 'append)) - (when (modulep! +tree-sitter) - (add-hook 'go-mode-local-vars-hook #'tree-sitter! 'append)) - - (map! :map go-mode-map + (map! :map ,(symbol-value (intern (format "%s-map" mode))) :localleader "a" #'go-tag-add "d" #'go-tag-remove @@ -47,10 +44,28 @@ "a" #'+go/bench-all)))) +(after! go-mode + (+go-common-config 'go-mode)) + + +(use-package! go-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'go-ts-mode) ; 31.1+ only + :defer t + :init + (set-tree-sitter! 'go-mode 'go-ts-mode + '((go :url "https://github.com/tree-sitter/tree-sitter-go" :ref "v0.23.4") + (gomod :url "https://github.com/camdencheek/tree-sitter-go-mod" :ref "v1.1.0") + (gowork :url "https://github.com/omertuc/tree-sitter-go-work"))) + :config + (+go-common-config 'go-ts-mode)) + + (use-package! gorepl-mode :commands gorepl-run-load-current-file) (use-package! flycheck-golangci-lint :when (modulep! :checkers syntax -flymake) - :hook (go-mode . flycheck-golangci-lint-setup)) + :hook (go-mode . flycheck-golangci-lint-setup) + :hook (go-ts-mode . flycheck-golangci-lint-setup)) diff --git a/modules/lang/go/doctor.el b/modules/lang/go/doctor.el index 9ab40bb49..ac0887afe 100644 --- a/modules/lang/go/doctor.el +++ b/modules/lang/go/doctor.el @@ -9,6 +9,10 @@ (modulep! :tools tree-sitter)) "This module requires (:tools tree-sitter)") +(assert! (or (not (modulep! +tree-sitter)) + (fboundp 'go-ts-mode)) + "Can't find `go-ts-mode'; Emacs 31.1+ is required") + (unless (executable-find "gore") (warn! "Couldn't find gore. REPL will not work")) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index c3f4e8017..85a3adecc 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -43,8 +43,6 @@ (commonlisp "https://github.com/tree-sitter-grammars/tree-sitter-commonlisp" nil nil nil nil) (css "https://github.com/tree-sitter/tree-sitter-css" nil nil nil nil) (dart "https://github.com/ast-grep/tree-sitter-dart" nil nil nil nil) - (go "https://github.com/tree-sitter/tree-sitter-go" nil nil nil nil) - (gomod "https://github.com/camdencheek/tree-sitter-go-mod" nil nil nil nil) (html "https://github.com/tree-sitter/tree-sitter-html" nil nil nil nil) (java "https://github.com/tree-sitter/tree-sitter-java" nil nil nil nil) (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src" nil nil) From a287a96acabf0b701ab13b274e20e50f2d0de015 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 28 Jun 2025 21:13:11 +0200 Subject: [PATCH 33/71] feat(dart): add treesit support This does not port over the keybinds to dart-ts-mode. Those will be done separately. --- modules/lang/dart/README.org | 4 ++++ modules/lang/dart/config.el | 28 +++++++++++++++++++++------- modules/lang/dart/doctor.el | 4 ++++ modules/lang/dart/packages.el | 6 ++++++ 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/modules/lang/dart/README.org b/modules/lang/dart/README.org index 5c875e7ab..3fe7ed533 100644 --- a/modules/lang/dart/README.org +++ b/modules/lang/dart/README.org @@ -23,9 +23,13 @@ This module wraps ~dart-mode~, with [[https://microsoft.github.io/language-serve - +lsp :: Enable LSP support for ~dart-mode~. Requires [[doom-module::tools lsp]] and a langserver (supports flutter). +- +tree-sitter :: + Leverages tree-sitter for better syntax highlighting and structural text + editing. Requires [[doom-module::tools tree-sitter]]. ** Packages - [[doom-package:dart-mode]] +- [[doom-package:dart-ts-mode]] if [[doom-module:+tree-sitter]] - [[doom-package:flutter.el]] - [[doom-package:hover.el]] diff --git a/modules/lang/dart/config.el b/modules/lang/dart/config.el index 19f8c9f63..3975f113c 100644 --- a/modules/lang/dart/config.el +++ b/modules/lang/dart/config.el @@ -1,11 +1,7 @@ ;;; lang/dart/config.el -*- lexical-binding: t; -*- -(use-package! dart-mode - :hook (dart-mode . rainbow-delimiters-mode) - :config - (when (modulep! +lsp) - (add-hook 'dart-mode-local-vars-hook #'lsp! 'append)) - (set-ligatures! '(dart-mode) +(defun +dart-common-config (mode) + (set-ligatures! mode ;; Functional :def "Function" :lambda "() =>" @@ -23,7 +19,25 @@ :for "for" :return "return" ;; Other - :yield "yield")) + :yield "yield") + + (when (modulep! +lsp) + (add-hook (intern (format "%s-local-vars-hook" mode)) #'lsp! 'append))) + +(use-package! dart-mode + :hook (dart-mode . rainbow-delimiters-mode) + :config + (+dart-common-config 'dart-mode)) + + +(use-package! dart-ts-mode + :when (modulep! +tree-sitter) + :defer t + :init + (set-tree-sitter! 'dart-mode 'dart-ts-mode + '((dart :url "https://github.com/ast-grep/tree-sitter-dart"))) + :config + (+dart-common-config 'dart-ts-mode)) (use-package! flutter diff --git a/modules/lang/dart/doctor.el b/modules/lang/dart/doctor.el index 74b43a676..3f813bffc 100644 --- a/modules/lang/dart/doctor.el +++ b/modules/lang/dart/doctor.el @@ -4,5 +4,9 @@ (modulep! :tools lsp)) "This module requires (:tools lsp)") +(assert! (or (not (modulep! +tree-sitter)) + (modulep! :tools tree-sitter)) + "This module requires (:tools tree-sitter)") + (unless (executable-find "dart") (warn! "Dart isn't on PATH.")) diff --git a/modules/lang/dart/packages.el b/modules/lang/dart/packages.el index 27f47df62..16641568e 100644 --- a/modules/lang/dart/packages.el +++ b/modules/lang/dart/packages.el @@ -3,6 +3,12 @@ (package! dart-mode :pin "f82ff052309125b93d19bdd3f619266f908f43ce") +(when (modulep! +tree-sitter) + (package! dart-ts-mode + :recipe (:host github + :repo "50ways2sayhard/dart-ts-mode") + :pin "ab87873f25f7e0cc8d22daa2501aae141dbe98ad")) + (when (and (modulep! +lsp) (modulep! :tools lsp -eglot)) (package! lsp-dart :pin "34e2a1191f723792d5f366b314cd6b07de4f1566")) From 0d9cf54c842e8e57068a108e8f8815f521ba44c0 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 28 Jun 2025 21:17:15 +0200 Subject: [PATCH 34/71] refactor(tree-sitter): remove redundant dart grammar Amend: a287a96acabf --- modules/tools/tree-sitter/config.el | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index 85a3adecc..d1f962648 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -42,7 +42,6 @@ (clojure "https://github.com/sogaiu/tree-sitter-clojure" nil nil nil nil) (commonlisp "https://github.com/tree-sitter-grammars/tree-sitter-commonlisp" nil nil nil nil) (css "https://github.com/tree-sitter/tree-sitter-css" nil nil nil nil) - (dart "https://github.com/ast-grep/tree-sitter-dart" nil nil nil nil) (html "https://github.com/tree-sitter/tree-sitter-html" nil nil nil nil) (java "https://github.com/tree-sitter/tree-sitter-java" nil nil nil nil) (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src" nil nil) From a8ccd2d47a814aeb5bdcd43f1d7b854e2054ef85 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Mon, 30 Jun 2025 14:47:35 +0200 Subject: [PATCH 35/71] fix(tree-sitter): unable to find local grammars (part 2) Ref: #7623 Amend: 4df993d683ec --- modules/tools/tree-sitter/config.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index d1f962648..a210ac064 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -12,7 +12,7 @@ :defer t :config ;; HACK: treesit lacks any way to dictate where to install grammars. - (add-to-list 'treesit-extra-load-path doom-profile-data-dir) + (add-to-list 'treesit-extra-load-path (concat doom-profile-data-dir "tree-sitter")) (defadvice! +tree-sitter--install-grammar-to-local-dir-a (fn &rest args) "Write grammars to `doom-profile-data-dir'." :around #'treesit-install-language-grammar From 7949d1bf274f19c51d4b1799fe8e009b9e272207 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Mon, 30 Jun 2025 14:48:54 +0200 Subject: [PATCH 36/71] fix(tree-sitter): void-variable +tree-sitter--major-mode-remaps-alist This is a temporary solution and will be polished up before the treesit branch is merged into master. Ref: #7623 Amend: 617d8411e6a1 --- modules/tools/tree-sitter/autoload/tree-sitter.el | 3 +++ modules/tools/tree-sitter/config.el | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/tools/tree-sitter/autoload/tree-sitter.el b/modules/tools/tree-sitter/autoload/tree-sitter.el index b0721316c..23f2d0b3d 100644 --- a/modules/tools/tree-sitter/autoload/tree-sitter.el +++ b/modules/tools/tree-sitter/autoload/tree-sitter.el @@ -1,5 +1,8 @@ ;;; tools/tree-sitter/autoload/tree-sitter.el -*- lexical-binding: t; -*- +;;;###autoload +(defvar +tree-sitter--major-mode-remaps-alist nil) + ;;;###autodef (fset 'tree-sitter! #'ignore) (defun tree-sitter! () (message "Old tree-sitter.el support is deprecated!")) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index a210ac064..5b990fee2 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -1,8 +1,5 @@ ;;; tools/tree-sitter/config.el -*- lexical-binding: t; -*- -(defvar +tree-sitter--major-mode-remaps-alist nil) - - ;; ;;; Packages From 2adbdf136061a42b189ba3523e04d1d03089d205 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Mon, 30 Jun 2025 15:16:26 +0200 Subject: [PATCH 37/71] feat(clojure): add treesit support --- modules/lang/clojure/README.org | 4 +++ modules/lang/clojure/config.el | 38 ++++++++++++++++++++++++++--- modules/lang/clojure/doctor.el | 4 +++ modules/lang/clojure/packages.el | 2 ++ modules/tools/tree-sitter/config.el | 1 - 5 files changed, 45 insertions(+), 4 deletions(-) diff --git a/modules/lang/clojure/README.org b/modules/lang/clojure/README.org index d9d98d2e8..98d230eb4 100644 --- a/modules/lang/clojure/README.org +++ b/modules/lang/clojure/README.org @@ -27,7 +27,11 @@ This module adds support for the Clojure(Script) language. ** Packages - [[doom-package:cider]] - [[doom-package:clj-refactor]] +- [[doom-package:clojure-mode]] +- [[doom-package:clojure-ts-mode]] if [[doom-module:+tree-sitter]] - [[doom-package:flycheck-clj-kondo]] if [[doom-module::checkers syntax]] +- [[doom-package:jet]] +- [[doom-package:neil]] ** Hacks - Error messages emitted from CIDER are piped into the REPL buffer when it is diff --git a/modules/lang/clojure/config.el b/modules/lang/clojure/config.el index a1ace2228..d3cd41387 100644 --- a/modules/lang/clojure/config.el +++ b/modules/lang/clojure/config.el @@ -46,17 +46,48 @@ (add-to-list 'tree-sitter-major-mode-language-alist '(clojurescript-mode . clojure))))) +(use-package! clojure-ts-mode + :when (modulep! +tree-sitter) + :defer t + :init + (setq clojure-ts-auto-remap nil) ; we do it ourselves + (set-tree-sitter! 'clojure-mode 'clojure-ts-mode + '((clojure :url "https://github.com/sogaiu/tree-sitter-clojure"))) + (set-tree-sitter! 'clojurec-mode 'clojure-ts-clojurec-mode 'clojure) + (set-tree-sitter! 'clojuredart-mode 'clojure-ts-clojuredart-mode 'clojure) + (set-tree-sitter! 'clojurescript-mode 'clojure-ts-clojurescript-mode 'javascript) + (set-tree-sitter! 'jank-mode 'clojure-ts-jank-mode 'cpp) + (set-tree-sitter! 'joker-mode 'clojure-ts-joker-mode 'clojure) + :config + ;; HACK: Rely on `major-mode-remap-defaults' instead (upstream also doesn't + ;; check if the grammars are ready before adding these entries, which will + ;; bork clojure buffers. + (cl-callf2 rassq-delete-all 'clojure-ts-mode auto-mode-alist) + (cl-callf2 rassq-delete-all 'clojure-ts-clojurescript-mode auto-mode-alist) + (cl-callf2 rassq-delete-all 'clojure-ts-clojurec-mode auto-mode-alist) + (cl-callf2 rassq-delete-all 'clojure-ts-clojuredart-mode auto-mode-alist) + (cl-callf2 rassq-delete-all 'clojure-ts-jank-mode auto-mode-alist) + (cl-callf2 rassq-delete-all 'clojure-ts-joker-mode auto-mode-alist)) + + ;; `cider-mode' is used instead of the typical `cider' package due to the main ;; library being loaded only when is absolutely needed, which is too late for ;; reconfiguration in many cases. (use-package! cider-mode ;; NOTE if `org-directory' doesn't exist, `cider-jack' in won't work :hook (clojure-mode-local-vars . cider-mode) + :hook (clojure-ts-mode-local-vars . cider-mode) :init (after! clojure-mode - (set-repl-handler! '(clojure-mode clojurec-mode) #'+clojure/open-repl :persist t) - (set-repl-handler! 'clojurescript-mode #'+clojure/open-cljs-repl :persist t) - (set-eval-handler! '(clojure-mode clojurescript-mode clojurec-mode) #'cider-eval-region)) + (set-repl-handler! '(clojure-mode clojure-ts-mode + clojurec-mode clojure-ts-clojurec-mode) + #'+clojure/open-repl :persist t) + (set-repl-handler! '(clojurescript-mode clojure-ts-clojurescript-mode) + #'+clojure/open-cljs-repl :persist t) + (set-eval-handler! '(clojure-mode clojure-ts-mode + clojurescript-mode clojure-ts-clojurescript-mode + clojurec-mode clojure-ts-clojurec-mode) + #'cider-eval-region)) ;; HACK Fix radian-software/radian#446: CIDER tries to calculate the frame's ;; background too early; sometimes before the initial frame has been @@ -285,6 +316,7 @@ :when (or (modulep! -lsp) +clojure-load-clj-refactor-with-lsp) :hook (clojure-mode . clj-refactor-mode) + :hook (clojure-ts-mode . clj-refactor-mode) :config (set-lookup-handlers! 'clj-refactor-mode :references #'cljr-find-usages) diff --git a/modules/lang/clojure/doctor.el b/modules/lang/clojure/doctor.el index 22455011e..7238477ac 100644 --- a/modules/lang/clojure/doctor.el +++ b/modules/lang/clojure/doctor.el @@ -1,6 +1,10 @@ ;; -*- lexical-binding: t; no-byte-compile: t; -*- ;;; lang/clojure/doctor.el +(assert! (or (not (modulep! +tree-sitter)) + (modulep! :tools tree-sitter)) + "This module requires (:tools tree-sitter)") + (when (and (modulep! :checkers syntax) (modulep! -lsp)) (unless (executable-find "clj-kondo") diff --git a/modules/lang/clojure/packages.el b/modules/lang/clojure/packages.el index 4291a46ca..a18287185 100644 --- a/modules/lang/clojure/packages.el +++ b/modules/lang/clojure/packages.el @@ -15,6 +15,8 @@ ;;; Core packages (package! clojure-mode :pin "b766094aea28bdc7b44ce1960d96434fe7d1d9cf") +(when (modulep! +tree-sitter) + (package! clojure-ts-mode :pin "da56a6938f525c8ead1fb3d79eced4d892df1661")) (package! clj-refactor :pin "dc1bbc8cdaa723bdbb6669ea7d280625c370755d") (package! cider :pin "12f10a6f4b3052a9b437f92cf97d551a5964f4cb") (when (modulep! :checkers syntax -flymake) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index 5b990fee2..62788322b 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -36,7 +36,6 @@ (bibtex "https://github.com/latex-lsp/tree-sitter-bibtex" nil nil nil nil) (blueprint "https://github.com/huanie/tree-sitter-blueprint" nil nil nil nil) (c-sharp "https://github.com/tree-sitter/tree-sitter-c-sharp" nil nil nil nil) - (clojure "https://github.com/sogaiu/tree-sitter-clojure" nil nil nil nil) (commonlisp "https://github.com/tree-sitter-grammars/tree-sitter-commonlisp" nil nil nil nil) (css "https://github.com/tree-sitter/tree-sitter-css" nil nil nil nil) (html "https://github.com/tree-sitter/tree-sitter-html" nil nil nil nil) From 6009c2b8382b9c56288b9588a2760d7ffc919319 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 23 Aug 2025 13:03:37 +0200 Subject: [PATCH 38/71] fix(tree-sitter): backport treesit-{enabled-modes,major-mode-remap-alist} And ignore `treesit-major-mode-remap-alist`, because they could interfere with our UX improvements. --- .../tools/tree-sitter/autoload/compat-30.el | 28 +++++++++++++++++++ .../tools/tree-sitter/autoload/tree-sitter.el | 2 ++ modules/tools/tree-sitter/config.el | 25 +++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/modules/tools/tree-sitter/autoload/compat-30.el b/modules/tools/tree-sitter/autoload/compat-30.el index a4fe39300..d37f936b6 100644 --- a/modules/tools/tree-sitter/autoload/compat-30.el +++ b/modules/tools/tree-sitter/autoload/compat-30.el @@ -40,4 +40,32 @@ Tree-sitter grammar for `%s' is missing; install it?" ;; Check that the grammar was installed successfully (treesit-ready-p lang)))) +;;; Introduced in later commits of 31.X +;;;###autoload +(unless (boundp 'treesit-major-mode-remap-alist) + (defvar treesit-major-mode-remap-alist nil)) + +;;;###autoload +(defcustom treesit-enabled-modes nil + "Specify what treesit modes to enable by default. +The value can be either a list of ts-modes to enable, +or t to enable all ts-modes." + :type `(choice + (const :tag "Disable all automatic associations" nil) + (const :tag "Enable all available ts-modes" t) + (set :tag "List of enabled ts-modes" + ,@(when (treesit-available-p) + (sort (mapcar (lambda (m) `(function-item ,m)) + (seq-uniq (mapcar #'cdr treesit-major-mode-remap-alist))))))) + :initialize #'custom-initialize-default + :set (lambda (sym val) + (set-default sym val) + (when (treesit-available-p) + (dolist (m treesit-major-mode-remap-alist) + (setq major-mode-remap-alist + (if (or (eq val t) (memq (cdr m) val)) + (cons m major-mode-remap-alist) + (delete m major-mode-remap-alist)))))) + :version "31.1") + ;;; compat-30.el ends here diff --git a/modules/tools/tree-sitter/autoload/tree-sitter.el b/modules/tools/tree-sitter/autoload/tree-sitter.el index 23f2d0b3d..b3dde5490 100644 --- a/modules/tools/tree-sitter/autoload/tree-sitter.el +++ b/modules/tools/tree-sitter/autoload/tree-sitter.el @@ -39,6 +39,8 @@ Note that COMMIT is only available in Emacs >=31." ((and (fboundp 'treesit-available-p) (treesit-available-p) (fboundp ts-mode) + (or (eq treesit-enabled-modes t) + (memq ts-mode treesit-enabled-modes)) ;; Only prompt once, and log other times. (cl-every (if ensured? (doom-rpartial #'treesit-ready-p 'message) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index 62788322b..4c2cd9133 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -7,7 +7,32 @@ :when (fboundp 'treesit-available-p) :when (treesit-available-p) :defer t + :preface + (setq treesit-enabled-modes t) + + ;; HACK: These *-ts-mode-maybe functions all treat `treesit-enabled-modes' + ;; strangely in the event the language's grammar is unavailable. Plus, they + ;; add yet-another-layer of complexity for users to be cognicent of. Get rid + ;; of them. + ;; REVIEW: Handle this during the 'doom sync' process instead. + (setq auto-mode-alist + (save-match-data + (cl-loop for (src . fn) in auto-mode-alist + unless (and (functionp fn) + (string-match "-ts-mode-maybe$" (symbol-name fn))) + collect (cons src fn)))) + :config + ;; HACK: The implementation of `treesit-enabled-modes's setter and + ;; `treesit-major-mode-remap-alist' are intrusively opinionated, so I + ;; disable it altogether as to not unexpectedly modify + ;; `major-mode-remap-alist' at runtime. What's more, there's no guarantee + ;; this will be populated correctly unless the user is on a particular + ;; commit of Emacs 31 or newer. Best we simply ignore it. + (dolist (m treesit-major-mode-remap-alist) + (setq major-mode-remap-alist (delete m major-mode-remap-alist))) + (setq treesit-major-mode-remap-alist nil) + ;; HACK: treesit lacks any way to dictate where to install grammars. (add-to-list 'treesit-extra-load-path (concat doom-profile-data-dir "tree-sitter")) (defadvice! +tree-sitter--install-grammar-to-local-dir-a (fn &rest args) From 3b587415224e2aa14280ea1e4a1ab3935449f40d Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 27 Aug 2025 00:35:39 +0200 Subject: [PATCH 39/71] refactor(tree-sitter): centralize grammar config & hacks Easier to track and maintain. --- modules/lang/cc/config.el | 16 ++--- modules/lang/clojure/config.el | 1 - modules/lang/csharp/config.el | 17 +---- modules/lang/elixir/config.el | 10 +-- modules/lang/go/config.el | 5 +- modules/lang/janet/config.el | 7 +- modules/lang/json/config.el | 4 +- modules/lang/julia/config.el | 4 +- modules/lang/lua/config.el | 4 +- modules/lang/markdown/config.el | 9 +-- modules/lang/php/config.el | 10 +-- modules/lang/python/config.el | 14 +--- modules/lang/ruby/config.el | 3 +- modules/lang/yaml/config.el | 7 +- modules/lang/zig/config.el | 3 - modules/tools/docker/config.el | 7 +- .../tools/tree-sitter/autoload/tree-sitter.el | 39 +++++++---- modules/tools/tree-sitter/config.el | 67 +++++++++++-------- 18 files changed, 85 insertions(+), 142 deletions(-) diff --git a/modules/lang/cc/config.el b/modules/lang/cc/config.el index a5ffeb737..0af20dedf 100644 --- a/modules/lang/cc/config.el +++ b/modules/lang/cc/config.el @@ -30,10 +30,8 @@ This is ignored by ccls.") :hook (c-mode-common . rainbow-delimiters-mode) :init (when (modulep! +tree-sitter) - (set-tree-sitter! 'c-mode 'c-ts-mode - '((c :url "https://github.com/tree-sitter/tree-sitter-c"))) - (set-tree-sitter! 'c++-mode 'c++-ts-mode - '((cpp :url "https://github.com/tree-sitter/tree-sitter-cpp")))) + (set-tree-sitter! 'c-mode 'c-ts-mode 'c) + (set-tree-sitter! 'c++-mode 'c++-ts-mode 'cpp)) :config (set-docsets! '(c-mode c-ts-mode) "C") @@ -116,8 +114,7 @@ This is ignored by ccls.") :init (when (and (modulep! +tree-sitter) (boundp 'cmake-ts-mode)) ; 29+ only - (set-tree-sitter! 'cmake-mode 'cmake-ts-mode - '((cmake :url "https://github.com/uyha/tree-sitter-cmake")))) + (set-tree-sitter! 'cmake-mode 'cmake-ts-mode 'cmake)) :config (set-docsets! '(cmake-mode cmake-ts-mode) "CMake") (set-popup-rule! "^\\*CMake Help\\*" :size 0.4 :ttl t) @@ -160,12 +157,7 @@ This is ignored by ccls.") '((cuda :url "https://github.com/tree-sitter-grammars/tree-sitter-cuda"))) :config (when (modulep! +lsp) - (add-hook 'cuda-ts-mode-local-vars-hook #'lsp! 'append)) - ;; HACK: Remove redundant entries so we can rely solely on - ;; `major-mode-remap-defaults' et co. - (rassq-delete-all 'cuda-ts-mode auto-mode-alist) - (cl-callf2 delete '(cuda "https://github.com/tree-sitter-grammars/tree-sitter-cuda" nil nil nil nil) - treesit-language-source-alist)) + (add-hook 'cuda-ts-mode-local-vars-hook #'lsp! 'append))) (use-package! demangle-mode diff --git a/modules/lang/clojure/config.el b/modules/lang/clojure/config.el index d3cd41387..dd3206aec 100644 --- a/modules/lang/clojure/config.el +++ b/modules/lang/clojure/config.el @@ -62,7 +62,6 @@ ;; HACK: Rely on `major-mode-remap-defaults' instead (upstream also doesn't ;; check if the grammars are ready before adding these entries, which will ;; bork clojure buffers. - (cl-callf2 rassq-delete-all 'clojure-ts-mode auto-mode-alist) (cl-callf2 rassq-delete-all 'clojure-ts-clojurescript-mode auto-mode-alist) (cl-callf2 rassq-delete-all 'clojure-ts-clojurec-mode auto-mode-alist) (cl-callf2 rassq-delete-all 'clojure-ts-clojuredart-mode auto-mode-alist) diff --git a/modules/lang/csharp/config.el b/modules/lang/csharp/config.el index 08f99fab2..70a4a9884 100644 --- a/modules/lang/csharp/config.el +++ b/modules/lang/csharp/config.el @@ -2,6 +2,9 @@ (use-package! csharp-mode :hook (csharp-mode . rainbow-delimiters-mode) + :init + (when (modulep! +tree-sitter) + (set-tree-sitter! 'csharp-mode 'csharp-ts-mode 'c-sharp)) :config (set-formatter! 'csharpier '("csharpier" "format" "--write-stdout") :modes '(csharp-mode csharp-ts-mode)) @@ -38,26 +41,12 @@ (add-hook 'csharp-mode-local-vars-hook #'lsp! 'append) (add-hook 'csharp-ts-mode-local-vars-hook #'lsp! 'append)) - (when (and (modulep! +tree-sitter) - (fboundp 'csharp-ts-mode)) ; 29.1+ only - (set-tree-sitter! 'csharp-mode 'csharp-ts-mode - '((c-sharp :url "https://github.com/tree-sitter/tree-sitter-c-sharp" - :rev "v0.23.1")))) - (defadvice! +csharp-disable-clear-string-fences-a (fn &rest args) "This turns off `c-clear-string-fences' for `csharp-mode'. When on for `csharp-mode' font lock breaks after an interpolated string or terminating simple string." :around #'csharp-disable-clear-string-fences (unless (eq major-mode 'csharp-mode) - (apply fn args))) - - ;; HACK: `csharp-ts-mode' changes `auto-mode-alist' every time the mode is - ;; activated, which runs the risk of overwriting user (or Doom) entries. - ;; REVIEW: Should be addressed upstream. - (defadvice! +csharp--undo-ts-side-effects-a (fn &rest args) - :around #'csharp-ts-mode - (let (auto-mode-alist) (apply fn args)))) diff --git a/modules/lang/elixir/config.el b/modules/lang/elixir/config.el index 6572fc195..81bd247dd 100644 --- a/modules/lang/elixir/config.el +++ b/modules/lang/elixir/config.el @@ -59,16 +59,8 @@ :when (fboundp 'elixir-ts-mode) ; 30.1+ only :defer t :init - (set-tree-sitter! 'elixir-mode 'elixir-ts-mode - '((elixir :url "https://github.com/elixir-lang/tree-sitter-elixir" - :rev "v0.3.3") - (heex :url "https://github.com/phoenixframework/tree-sitter-heex" - :rev "v0.7.0"))) + (set-tree-sitter! 'elixir-mode 'elixir-ts-mode '(elixir heex)) :config - ;; HACK: Rely on `major-mode-remap-defaults' (and elixir-mode's autoloaded - ;; auto-mode-alist entries). - (cl-callf2 rassq-delete-all 'elixir-ts-mode auto-mode-alist) - (+elixir-common-config 'elixir-ts-mode)) diff --git a/modules/lang/go/config.el b/modules/lang/go/config.el index 469f5189b..d526f2fc8 100644 --- a/modules/lang/go/config.el +++ b/modules/lang/go/config.el @@ -53,10 +53,7 @@ :when (fboundp 'go-ts-mode) ; 31.1+ only :defer t :init - (set-tree-sitter! 'go-mode 'go-ts-mode - '((go :url "https://github.com/tree-sitter/tree-sitter-go" :ref "v0.23.4") - (gomod :url "https://github.com/camdencheek/tree-sitter-go-mod" :ref "v1.1.0") - (gowork :url "https://github.com/omertuc/tree-sitter-go-work"))) + (set-tree-sitter! 'go-mode 'go-ts-mode '(go gomod gowork)) :config (+go-common-config 'go-ts-mode)) diff --git a/modules/lang/janet/config.el b/modules/lang/janet/config.el index 00c4f0a42..fa49da13a 100644 --- a/modules/lang/janet/config.el +++ b/modules/lang/janet/config.el @@ -30,9 +30,4 @@ :init (set-tree-sitter! 'janet-mode 'janet-ts-mode `(janet-simple :url "https://github.com/sogaiu/tree-sitter-janet-simple" - :cc ,(if (featurep :system 'windows) "gcc.exe"))) - :config - ;; HACK: These entries are inserted twice by this package, so remove them so - ;; this module can be the single source of truth. - (cl-callf2 rassq-delete-all 'janet-ts-mode auto-mode-alist) - (cl-callf2 rassq-delete-all 'janet-ts-mode interpreter-mode-alist)) + :cc ,(if (featurep :system 'windows) "gcc.exe")))) diff --git a/modules/lang/json/config.el b/modules/lang/json/config.el index 3f9fe6529..a2d385c56 100644 --- a/modules/lang/json/config.el +++ b/modules/lang/json/config.el @@ -25,9 +25,7 @@ :when (fboundp 'json-ts-mode) ; 29.1+ only :defer t :init - (set-tree-sitter! 'json-mode 'json-ts-mode - '((json :url "https://github.com/tree-sitter/tree-sitter-json" - :rev "v0.24.8"))) + (set-tree-sitter! 'json-mode 'json-ts-mode 'json) :config ;; HACK: Rely on `major-mode-remap-defaults'. (cl-callf2 assq-delete-all 'json-ts-mode auto-mode-alist) diff --git a/modules/lang/julia/config.el b/modules/lang/julia/config.el index 5e944741f..43ae499b3 100644 --- a/modules/lang/julia/config.el +++ b/modules/lang/julia/config.el @@ -48,9 +48,7 @@ :when (modulep! +tree-sitter) :defer t :init - (set-tree-sitter! 'julia-mode 'julia-ts-mode - '((julia :url "https://github.com/tree-sitter/tree-sitter-julia" - :rev "v0.23.1"))) + (set-tree-sitter! 'julia-mode 'julia-ts-mode 'julia) :config (when (modulep! +lsp) (add-hook 'julia-ts-mode-local-vars-hook #'lsp! 'append))) diff --git a/modules/lang/lua/config.el b/modules/lang/lua/config.el index 91d95c307..e57d8a150 100644 --- a/modules/lang/lua/config.el +++ b/modules/lang/lua/config.el @@ -30,9 +30,7 @@ :when (fboundp 'lua-ts-mode) ; 30.1+ only :defer t :init - (set-tree-sitter! 'lua-mode 'lua-ts-mode - '((lua :url "https://github.com/tree-sitter-grammars/tree-sitter-lua" - :rev "v0.3.0"))) + (set-tree-sitter! 'lua-mode 'lua-ts-mode 'lua) :config (set-lookup-handlers! 'lua-ts-mode :documentation 'lua-search-documentation) (set-electric! 'lua-ts-mode :words '("else" "end")) diff --git a/modules/lang/markdown/config.el b/modules/lang/markdown/config.el index 6f5e2111e..9fea6ecad 100644 --- a/modules/lang/markdown/config.el +++ b/modules/lang/markdown/config.el @@ -131,14 +131,7 @@ capture, the end position, and the output buffer.") :when (fboundp 'markdown-ts-mode) :defer t :init - (set-tree-sitter! 'markdown-mode 'markdown-ts-mode - '((markdown :url "https://github.com/tree-sitter-grammars/tree-sitter-markdown" - :rev "v0.4.1" - :source-dir "tree-sitter-markdown-inline/src") - (markdown-inline :url "https://github.com/tree-sitter-grammars/tree-sitter-markdown" - :rev "v0.4.1" - :source-dir "tree-sitter-markdown-inline/src"))) - + (set-tree-sitter! 'markdown-mode 'markdown-ts-mode '(markdown markdown-inline)) :config (cl-callf2 delete '("\\.md\\'" . markdown-ts-mode) auto-mode-alist)) diff --git a/modules/lang/php/config.el b/modules/lang/php/config.el index fe7460e0f..e96d23683 100644 --- a/modules/lang/php/config.el +++ b/modules/lang/php/config.el @@ -83,16 +83,8 @@ :when (fboundp 'php-ts-mode) ; 30.1+ only :defer t :init - (set-tree-sitter! 'php-mode 'php-ts-mode - '((php :url "https://github.com/tree-sitter/tree-sitter-php" - :rev "v0.23.11" - :source-dir "php/src") - (phpdoc :url "https://github.com/claytonrcarter/tree-sitter-phpdoc"))) + (set-tree-sitter! 'php-mode 'php-ts-mode '(php phpdoc)) :config - ;; HACK: Rely on `major-mode-remap-defaults'. - (cl-callf2 rassq-delete-all 'php-ts-mode auto-mode-alist) - (cl-callf2 rassq-delete-all 'php-ts-mode interpreter-mode-alist) - (+php-common-config 'php-ts-mode)) diff --git a/modules/lang/python/config.el b/modules/lang/python/config.el index 1e61c960c..44360d038 100644 --- a/modules/lang/python/config.el +++ b/modules/lang/python/config.el @@ -20,8 +20,7 @@ python-indent-guess-indent-offset-verbose nil) (when (modulep! +tree-sitter) - (set-tree-sitter! 'python-mode 'python-ts-mode - '((python :url "https://github.com/tree-sitter/tree-sitter-python")))) + (set-tree-sitter! 'python-mode 'python-ts-mode 'python)) :config ;; HACK: `python-base-mode' (and `python-ts-mode') don't exist on pre-29 @@ -98,16 +97,7 @@ ;; HACK: `python-mode' doesn't update `tab-width' to reflect ;; `python-indent-offset', causing issues anywhere `tab-width' is respected. - (setq-hook! '(python-mode-hook python-ts-mode-hook) tab-width python-indent-offset) - - ;; HACK: `python-ts-mode' changes `auto-mode-alist' and - ;; `interpreter-mode-alist' every time the mode is activated, which runs the - ;; risk of overwriting user (or Doom) entries. - ;; REVIEW: Should be addressed upstream. - (defadvice! +python--undo-ts-side-effects-a (fn &rest args) - :around #'python-ts-mode - (let (auto-mode-alist interpreter-mode-alist) - (apply fn args)))) + (setq-hook! '(python-mode-hook python-ts-mode-hook) tab-width python-indent-offset)) (use-package! pyimport diff --git a/modules/lang/ruby/config.el b/modules/lang/ruby/config.el index 0721167aa..0ef6d3e66 100644 --- a/modules/lang/ruby/config.el +++ b/modules/lang/ruby/config.el @@ -41,8 +41,7 @@ :when (fboundp 'ruby-ts-mode) ; 29.1+ only :defer t :init - (set-tree-sitter! 'ruby-mode 'ruby-ts-mode - '((ruby :url "https://github.com/tree-sitter/tree-sitter-ruby"))) + (set-tree-sitter! 'ruby-mode 'ruby-ts-mode 'ruby) :config (set-electric! 'ruby-ts-mode :words '("else" "end" "elsif")) (set-repl-handler! 'ruby-ts-mode #'inf-ruby) diff --git a/modules/lang/yaml/config.el b/modules/lang/yaml/config.el index 8a5cbb90f..9f139313a 100644 --- a/modules/lang/yaml/config.el +++ b/modules/lang/yaml/config.el @@ -12,12 +12,7 @@ :when (modulep! +tree-sitter) :when (fboundp 'yaml-ts-mode) ; 29.1+ only :init - (set-tree-sitter! 'yaml-mode 'yaml-ts-mode - '((yaml :url "https://github.com/tree-sitter-grammars/tree-sitter-yaml" - :rev "v0.7.0"))) + (set-tree-sitter! 'yaml-mode 'yaml-ts-mode 'yaml) :config - ;; HACK: Rely on `major-mode-remap-defaults'. - (cl-callf2 rassq-delete-all 'yaml-ts-mode auto-mode-alist) - (when (modulep! +lsp) (add-hook 'yaml-ts-mode-local-vars-hook #'lsp! 'append))) diff --git a/modules/lang/zig/config.el b/modules/lang/zig/config.el index 52adc3bf2..7fe3d90e7 100644 --- a/modules/lang/zig/config.el +++ b/modules/lang/zig/config.el @@ -47,7 +47,4 @@ '((zig :url "https://github.com/tree-sitter/zig-tree-sitter" :rev "v0.25.0"))) :config - ;; HACK: Rely on `major-mode-remap-defaults' - (cl-callf2 rassq-delete-all 'zig-ts-mode auto-mode-alist) - (+zig-common-config 'zig-ts-mode)) diff --git a/modules/tools/docker/config.el b/modules/tools/docker/config.el index 3e523be48..6029a6c3c 100644 --- a/modules/tools/docker/config.el +++ b/modules/tools/docker/config.el @@ -13,9 +13,4 @@ :when (fboundp 'dockerfile-ts-mode) ; 29.1+ only :defer t :init - (set-tree-sitter! 'dockerfile-mode 'dockerfile-ts-mode - '((dockerfile :url "https://github.com/camdencheek/tree-sitter-dockerfile" - :rev "v0.2.0"))) - :config - ;; HACK: Rely on `major-mode-remap-defaults' instead - (cl-callf2 rassq-delete-all 'dockerfile-ts-mode auto-mode-alist)) + (set-tree-sitter! 'dockerfile-mode 'dockerfile-ts-mode 'dockerfile)) diff --git a/modules/tools/tree-sitter/autoload/tree-sitter.el b/modules/tools/tree-sitter/autoload/tree-sitter.el index b3dde5490..5df7c4bdf 100644 --- a/modules/tools/tree-sitter/autoload/tree-sitter.el +++ b/modules/tools/tree-sitter/autoload/tree-sitter.el @@ -15,10 +15,11 @@ MODE and TS-MODE are major mode symbols. If RECIPES is provided, fall back to MODE if RECIPES don't pass `treesit-ready-p' when activating TS-MODE. Use this for ts modes that error out instead of failing gracefully. -RECIPES are an alist of plists with the format (LANG &key URL REV SOURCE-DIR CC -CPP COMMIT), which will be transformed into entries for -`treesit-language-source-alist' (which descrie what each of these keys mean). -Note that COMMIT is only available in Emacs >=31." +RECIPES is a symbol (a grammar language name), list thereof, or alist of plists +with the format (LANG &key URL REV SOURCE-DIR CC CPP COMMIT). If an alist of +plists, it will be transformed into entries for `treesit-language-source-alist' +(which describe what each of these keys mean). Note that COMMIT is ignored +pre-Emacs 31." (declare (indent 2)) (cl-check-type mode symbol) (cl-check-type ts-mode symbol) @@ -41,6 +42,11 @@ Note that COMMIT is only available in Emacs >=31." (fboundp ts-mode) (or (eq treesit-enabled-modes t) (memq ts-mode treesit-enabled-modes)) + ;; Lazily load autoload so + ;; `treesit-language-source-alist' is initialized. + (let ((fn (symbol-function ts-mode))) + (or (not (autoloadp fn)) + (autoload-do-load fn))) ;; Only prompt once, and log other times. (cl-every (if ensured? (doom-rpartial #'treesit-ready-p 'message) @@ -54,16 +60,16 @@ Note that COMMIT is only available in Emacs >=31." m)))))))) (with-eval-after-load 'treesit (dolist (recipe recipes) - (cl-destructuring-bind (name &key url rev source-dir cc cpp commit) - (ensure-list recipe) - (setf (alist-get name treesit-language-source-alist) - (append (list url rev source-dir cc cpp) - ;; COMPAT: 31.1 introduced a COMMIT recipe argument. On - ;; <=30.x, extra arguments will trigger an arity error - ;; when installing grammars. - (if (eq (cdr (func-arity 'treesit--install-language-grammar-1)) - 'many) - (list commit)))))))) + (when (cdr (setq recipe (ensure-list recipe))) + (cl-destructuring-bind (name &key url rev source-dir cc cpp commit) recipe + (setf (alist-get name treesit-language-source-alist) + (append (list url rev source-dir cc cpp) + ;; COMPAT: 31.1 introduced a COMMIT recipe argument. On + ;; <=30.x, extra arguments will trigger an arity error + ;; when installing grammars. + (if (eq (cdr (func-arity 'treesit--install-language-grammar-1)) + 'many) + (list commit))))))))) ;; ;; HACK: Remove and refactor when `use-package' eager macro expansion is solved or `use-package!' is removed ;; ;;;###autoload @@ -81,6 +87,11 @@ Note that COMMIT is only available in Emacs >=31." ;; (evil-textobj-tree-sitter-goto-textobj group previous end query))) ;; sym)) +;;;###autoload +(defun +tree-sitter-ts-mode-inhibit-side-effects-a (fn &rest args) + "Suppress changes to `auto-mode-alist' and `interpreter-mode-alist'." + (let (auto-mode-alist interpreter-mode-alist) + (apply fn args))) ;;; TODO: Backwards compatibility diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index 4c2cd9133..b6c5c91e4 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -10,38 +10,42 @@ :preface (setq treesit-enabled-modes t) - ;; HACK: These *-ts-mode-maybe functions all treat `treesit-enabled-modes' - ;; strangely in the event the language's grammar is unavailable. Plus, they - ;; add yet-another-layer of complexity for users to be cognicent of. Get rid - ;; of them. - ;; REVIEW: Handle this during the 'doom sync' process instead. - (setq auto-mode-alist - (save-match-data - (cl-loop for (src . fn) in auto-mode-alist - unless (and (functionp fn) - (string-match "-ts-mode-maybe$" (symbol-name fn))) - collect (cons src fn)))) + ;; HACK: The *-ts-mode major modes are inconsistent about how they treat + ;; missing language grammars (some error out, some respect + ;; `treesit-auto-install-grammar', some fall back to `fundamental-mode'). + ;; I'd like to address this poor UX using `major-mode-remap-alist' entries + ;; created by `set-tree-sitter!' (which will fall back to the non-treesit + ;; modes), but most *-ts-mode's clobber `auto-mode-alist' and/or + ;; `interpreter-mode-alist' each time the major mode is activated, so those + ;; must be undone too so they don't overwrite user config. + ;; TODO: Handle this during the 'doom sync' process instead. + (save-match-data + (dolist (sym '(auto-mode-alist interpreter-mode-alist)) + (set + sym (cl-loop for (src . fn) in (symbol-value sym) + unless (and (functionp fn) + (string-match "-ts-mode\\(?:-maybe\\)?$" (symbol-name fn))) + collect (cons src fn))))) + + ;; HACK: These *-ts-modes change `auto-mode-alist' and/or + ;; `interpreter-mode-alist' every time they are activated, running the risk + ;; of overwriting user (or Doom) config. + ;; REVIEW: Should be addressed upstream. + (dolist (mode '(csharp-ts-mode + python-ts-mode)) + (advice-add mode :around #'+tree-sitter-ts-mode-inhibit-side-effects-a)) :config ;; HACK: The implementation of `treesit-enabled-modes's setter and - ;; `treesit-major-mode-remap-alist' are intrusively opinionated, so I - ;; disable it altogether as to not unexpectedly modify - ;; `major-mode-remap-alist' at runtime. What's more, there's no guarantee - ;; this will be populated correctly unless the user is on a particular - ;; commit of Emacs 31 or newer. Best we simply ignore it. - (dolist (m treesit-major-mode-remap-alist) - (setq major-mode-remap-alist (delete m major-mode-remap-alist))) + ;; `treesit-major-mode-remap-alist' is intrusively opinionated, so disable + ;; it ato avoid untimely (and overriding) modifications of + ;; `major-mode-remap-alist' at runtime. What's more, this was only + ;; introduced in 31, so ignoring them is more consistent for pre-31 users. + (when major-mode-remap-alist + (dolist (m treesit-major-mode-remap-alist) + (setq major-mode-remap-alist (delete m major-mode-remap-alist)))) (setq treesit-major-mode-remap-alist nil) - ;; HACK: treesit lacks any way to dictate where to install grammars. - (add-to-list 'treesit-extra-load-path (concat doom-profile-data-dir "tree-sitter")) - (defadvice! +tree-sitter--install-grammar-to-local-dir-a (fn &rest args) - "Write grammars to `doom-profile-data-dir'." - :around #'treesit-install-language-grammar - :around #'treesit--build-grammar - (let ((user-emacs-directory doom-profile-data-dir)) - (apply fn args))) - ;; HACK: Some *-ts-mode packages modify `major-mode-remap-defaults' ;; inconsistently. Playing whack-a-mole to undo those changes is more hassle ;; then simply ignoring them (by overriding `major-mode-remap-defaults' for @@ -56,6 +60,15 @@ major-mode-remap-defaults))) (funcall fn mode))) + ;; HACK: Keep $EMACSDIR clean by installing grammars to the active profile. + (add-to-list 'treesit-extra-load-path (concat doom-profile-data-dir "tree-sitter")) + (defadvice! +tree-sitter--install-grammar-to-local-dir-a (fn &rest args) + "Write grammars to `doom-profile-data-dir'." + :around #'treesit-install-language-grammar + :around #'treesit--build-grammar + (let ((user-emacs-directory doom-profile-data-dir)) + (apply fn args))) + ;; TODO: Move most of these out to modules (dolist (map '((awk "https://github.com/Beaglefoot/tree-sitter-awk" nil nil nil nil) (bibtex "https://github.com/latex-lsp/tree-sitter-bibtex" nil nil nil nil) From 086a0d30d09a6c316bc2e63ab556ec38c731bb49 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 27 Aug 2025 00:47:36 +0200 Subject: [PATCH 40/71] feat(rust): add treesit support --- modules/lang/rust/README.org | 1 + modules/lang/rust/config.el | 83 ++++++++++++++++++++++++------------ modules/lang/rust/doctor.el | 4 ++ 3 files changed, 60 insertions(+), 28 deletions(-) diff --git a/modules/lang/rust/README.org b/modules/lang/rust/README.org index 93179ad59..c7806b8e9 100644 --- a/modules/lang/rust/README.org +++ b/modules/lang/rust/README.org @@ -26,6 +26,7 @@ e.g. ~cargo~. editing. Requires [[doom-module::tools tree-sitter]]. ** Packages +- [[doom-package:rust-mode]] - [[doom-package:rustic]] ** Hacks diff --git a/modules/lang/rust/config.el b/modules/lang/rust/config.el index f14ff418a..283e5744e 100644 --- a/modules/lang/rust/config.el +++ b/modules/lang/rust/config.el @@ -8,15 +8,46 @@ ;; ;;; Packages -(use-package! rustic +;; HACK: `rust-mode' and `rustic' add entries to `auto-mode-alist', but package +;; load order makes which gets precedence unpredictable. By removing them +;; early, we rely on our own entries in `auto-mode-alist' and +;; `major-mode-remap-defaults' to ensure correct order. +(cl-callf2 rassq-delete-all 'rust-mode auto-mode-alist) +(cl-callf2 rassq-delete-all 'rustic-mode auto-mode-alist) + + +(use-package! rust-mode :mode ("\\.rs\\'" . rust-mode) - :mode ("\\.rs\\'" . rustic-mode) + :defer t :preface - ;; HACK: `rust-mode' and `rustic' add entries to `auto-mode-alist', but - ;; package load order makes which gets precedence unpredictable. By removing - ;; them early, we rely on the `:mode' directives above to re-insert them - ;; with the correct order. - (setq auto-mode-alist (assoc-delete-all "\\.rs\\'" auto-mode-alist)) + ;; Ensure rust-mode derives from rust-ts-mode, b/c rustic-mode derives from + ;; rust-mode. This way, rustic-mode is the only major mode we have to worry + ;; about. + (setq rust-mode-treesitter-derive (modulep! +tree-sitter)) + + :config + (setq rust-indent-method-chain t) + + ;; Load order is important for these two packages. + (let (auto-mode-alist) + (require 'rustic-mode nil t))) + + +(use-package! rust-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'rust-ts-mode) ; 29.1+ only + :defer t + :init + (set-tree-sitter! 'rust-mode 'rust-ts-mode 'rust) + + (add-to-list 'major-mode-remap-defaults '(rust-mode . rust-ts-mode) t)) + + +(use-package! rustic + :defer t + :preface + (unless (assq 'rust-mode major-mode-remap-defaults) + (add-to-list 'major-mode-remap-defaults '(rust-mode . rustic-mode))) ;; HACK `rustic' sets up some things too early. I'd rather disable it and let ;; our respective modules standardize how they're initialized. @@ -27,21 +58,20 @@ (remove-hook 'rustic-mode-hook #'flycheck-mode) (remove-hook 'rustic-mode-hook #'flymake-mode-off) (remove-hook 'flycheck-mode-hook #'rustic-flycheck-setup)) + :init ;; HACK Certainly, `rustic-babel' does this, but the package (and many other ;; rustic packages) must be loaded in order for them to take effect. To lazy - ;; load it all, we must do it early: + ;; load it all, it must be done earlier: (after! org-src (defalias 'org-babel-execute:rust #'org-babel-execute:rustic) (add-to-list 'org-src-lang-modes '("rust" . rustic))) + :config - (add-hook 'rustic-mode-hook #'rainbow-delimiters-mode) (set-docsets! 'rustic-mode "Rust") (set-popup-rule! "^\\*rustic-compilation" :vslot -1) (set-popup-rule! "^\\*cargo-run" :vslot -1) - (setq rustic-indent-method-chain t) - ;; Leave automatic reformatting to the :editor format module. (setq rustic-babel-format-src-block nil rustic-format-trigger nil) @@ -60,7 +90,7 @@ ;; response of Rust Analyzer, which is not stable enough for `lsp-mode' ;; maintainers (see emacs-lsp/lsp-mode#1740). (unless (modulep! :tools lsp +eglot) - (defadvice! +rust--dont-cache-results-from-ra-a (fn &rest args) + (defadvice! +rust--dont-cache-results-from-ra-a (&rest _) :after #'lsp-eldoc-function (when (derived-mode-p 'rust-mode 'rust-ts-mode) (setq lsp--hover-saved-bounds nil))) @@ -84,9 +114,6 @@ (s-join " ")))) (lsp--render-element (concat "```rust\n" sig cmt "\n```")))))) - (when (modulep! +tree-sitter) - (add-hook 'rustic-mode-local-vars-hook #'tree-sitter! 'append)) - ;; HACK If lsp/eglot isn't available, it attempts to install lsp-mode via ;; package.el. Doom manages its own dependencies through straight so disable ;; this behavior to avoid package-not-initialized errors. @@ -97,17 +124,17 @@ (map! :map rustic-mode-map :localleader (:prefix ("b" . "build") - :desc "cargo audit" "a" #'+rust/cargo-audit - :desc "cargo build" "b" #'rustic-cargo-build - :desc "cargo bench" "B" #'rustic-cargo-bench - :desc "cargo check" "c" #'rustic-cargo-check - :desc "cargo clippy" "C" #'rustic-cargo-clippy - :desc "cargo doc" "d" #'rustic-cargo-build-doc - :desc "cargo doc --open" "D" #'rustic-cargo-doc - :desc "cargo fmt" "f" #'rustic-cargo-fmt - :desc "cargo new" "n" #'rustic-cargo-new - :desc "cargo outdated" "o" #'rustic-cargo-outdated - :desc "cargo run" "r" #'rustic-cargo-run) + :desc "cargo audit" "a" #'+rust/cargo-audit + :desc "cargo build" "b" #'rustic-cargo-build + :desc "cargo bench" "B" #'rustic-cargo-bench + :desc "cargo check" "c" #'rustic-cargo-check + :desc "cargo clippy" "C" #'rustic-cargo-clippy + :desc "cargo doc" "d" #'rustic-cargo-build-doc + :desc "cargo doc --open" "D" #'rustic-cargo-doc + :desc "cargo fmt" "f" #'rustic-cargo-fmt + :desc "cargo new" "n" #'rustic-cargo-new + :desc "cargo outdated" "o" #'rustic-cargo-outdated + :desc "cargo run" "r" #'rustic-cargo-run) (:prefix ("t" . "cargo test") - :desc "all" "a" #'rustic-cargo-test - :desc "current test" "t" #'rustic-cargo-current-test))) + :desc "all" "a" #'rustic-cargo-test + :desc "current test" "t" #'rustic-cargo-current-test))) diff --git a/modules/lang/rust/doctor.el b/modules/lang/rust/doctor.el index a7e3ee467..e813e09d9 100644 --- a/modules/lang/rust/doctor.el +++ b/modules/lang/rust/doctor.el @@ -9,6 +9,10 @@ (modulep! :tools tree-sitter)) "This module requires (:tools tree-sitter)") +(assert! (or (not (modulep! +tree-sitter)) + (fboundp 'rust-ts-mode)) + "Can't find `rust-ts-mode'; Emacs 29.1+ is required") + (unless (executable-find "rustc") (warn! "Couldn't find rustc binary")) From 47fe11cd767e8e836b8b0b16fc73d7922a46909b Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 27 Aug 2025 17:09:27 +0200 Subject: [PATCH 41/71] feat(haskell): add treesit support --- modules/lang/haskell/config.el | 13 ++++++++++--- modules/lang/haskell/doctor.el | 4 ++++ modules/lang/haskell/packages.el | 2 ++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/modules/lang/haskell/config.el b/modules/lang/haskell/config.el index 9c78fbced..0bbc03eeb 100644 --- a/modules/lang/haskell/config.el +++ b/modules/lang/haskell/config.el @@ -28,9 +28,6 @@ #'haskell-collapse-mode ; support folding haskell code blocks #'interactive-haskell-mode) - (when (modulep! +tree-sitter) - (add-hook 'haskell-mode-local-vars-hook #'tree-sitter! 'append)) - (add-to-list 'completion-ignored-extensions ".hi") (map! :map haskell-mode-map @@ -47,6 +44,16 @@ "H" #'haskell-hide-toggle-all)) +;; TODO: Mirror other haskell-mode config to ts-mode +(use-package! haskell-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'haskell-ts-mode) + :defer t + :init + (set-tree-sitter! 'haskell-mode 'haskell-ts-mode + '((haskell :url "https://github.com/tree-sitter/tree-sitter-haskell")))) + + (use-package! lsp-haskell :when (modulep! +lsp) :defer t diff --git a/modules/lang/haskell/doctor.el b/modules/lang/haskell/doctor.el index 8874330f5..7ffc55058 100644 --- a/modules/lang/haskell/doctor.el +++ b/modules/lang/haskell/doctor.el @@ -5,6 +5,10 @@ (modulep! :tools lsp)) "This module requires (:tools lsp)") +(assert! (or (not (modulep! +tree-sitter)) + (modulep! :tools tree-sitter)) + "This module requires (:tools tree-sitter)") + (unless (executable-find "cabal") (warn! "Couldn't find cabal. haskell-mode may have issues.")) diff --git a/modules/lang/haskell/packages.el b/modules/lang/haskell/packages.el index 8ba6491bd..0feac9687 100644 --- a/modules/lang/haskell/packages.el +++ b/modules/lang/haskell/packages.el @@ -2,6 +2,8 @@ ;;; lang/haskell/packages.el (package! haskell-mode :pin "e9c356739310332afe59b10ffa2e6c3e76f124e3") +(when (modulep! +tree-sitter) + (package! haskell-ts-mode :pin "b47211699944997bfb03fd88b1157dd71727bad7")) (when (and (modulep! +lsp) (modulep! :tools lsp -eglot)) From c1ac8bc37a34bdb495e91ab30e7a0b633b43afb0 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 27 Aug 2025 17:11:42 +0200 Subject: [PATCH 42/71] refactor(ocaml): remove tree-sitter support No *-ts-mode exists for tuareg-mode. There *is* a ocaml-ts-mode, but it's too rudimentary. The ocaml module will fall back to font-lock rules so this is not a breaking changing. --- modules/lang/ocaml/README.org | 3 --- modules/lang/ocaml/config.el | 4 ---- modules/lang/ocaml/doctor.el | 4 ---- 3 files changed, 11 deletions(-) diff --git a/modules/lang/ocaml/README.org b/modules/lang/ocaml/README.org index c062f1aec..d6b824b35 100644 --- a/modules/lang/ocaml/README.org +++ b/modules/lang/ocaml/README.org @@ -23,9 +23,6 @@ This module adds [[https://ocaml.org/][OCaml]] support to Doom Emacs, powered by - +lsp :: Enable LSP support for ~tuareg-mode~. Requires [[doom-module::tools lsp]] and a langserver (supports [[https://github.com/freebroccolo/ocaml-language-server][ocaml-language-server]]). -- +tree-sitter :: - Leverages tree-sitter for better syntax highlighting and structural text - editing. Requires [[doom-module::tools tree-sitter]]. ** Packages - [[doom-package:dune]] diff --git a/modules/lang/ocaml/config.el b/modules/lang/ocaml/config.el index 4ca5805d5..a270252f0 100644 --- a/modules/lang/ocaml/config.el +++ b/modules/lang/ocaml/config.el @@ -130,10 +130,6 @@ (opam-switch-set-switch (tuareg-opam-current-compiler))) -(when (modulep! +tree-sitter) - (add-hook 'tuareg-mode-local-vars-hook #'tree-sitter!)) - - (use-package! dune :defer t :config diff --git a/modules/lang/ocaml/doctor.el b/modules/lang/ocaml/doctor.el index 07facc1d3..4879155b9 100644 --- a/modules/lang/ocaml/doctor.el +++ b/modules/lang/ocaml/doctor.el @@ -5,10 +5,6 @@ (modulep! :tools lsp)) "This module requires (:tools lsp)") -(assert! (or (not (modulep! +tree-sitter)) - (modulep! :tools tree-sitter)) - "This module requires (:tools tree-sitter)") - (unless (executable-find "ocamlmerlin") (warn! "Couldn't find ocamlmerlin. Lookup, completion and syntax checking won't work")) From bee45157c6817264af5f766e60cf5ac8a5d28ee0 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 27 Aug 2025 17:14:53 +0200 Subject: [PATCH 43/71] refactor(elm): remove tree-sitter support No *-ts-mode exists for elm-mode. The elm module will fall back to font-lock rules so this is not a breaking changing. --- modules/lang/elm/README.org | 3 --- modules/lang/elm/config.el | 3 --- modules/lang/elm/doctor.el | 3 --- 3 files changed, 9 deletions(-) diff --git a/modules/lang/elm/README.org b/modules/lang/elm/README.org index 8445c7c20..d2c2d06c6 100644 --- a/modules/lang/elm/README.org +++ b/modules/lang/elm/README.org @@ -13,9 +13,6 @@ This module adds [[https://elm-lang.org/][Elm]] support to Doom Emacs. - +lsp :: Enable LSP support for ~elm-mode~. Requires [[doom-module::tools lsp]] and a langserver (supports [[https://github.com/elm-tooling/elm-language-server][elm-language-server]]). -- +tree-sitter :: - Leverages tree-sitter for better syntax highlighting and structural text - editing. Requires [[doom-module::tools tree-sitter]]. ** Packages - [[doom-package:elm-mode]] diff --git a/modules/lang/elm/config.el b/modules/lang/elm/config.el index c8d371a21..44948cb77 100644 --- a/modules/lang/elm/config.el +++ b/modules/lang/elm/config.el @@ -5,9 +5,6 @@ (add-hook 'elm-mode-local-vars-hook #'lsp! 'append) (set-company-backend! 'elm-mode 'company-elm)) - (when (modulep! +tree-sitter) - (add-hook 'elm-mode-local-vars-hook #'tree-sitter! 'append)) - (set-repl-handler! 'elm-mode #'run-elm-interactive) (set-ligatures! 'elm-mode :null "null" diff --git a/modules/lang/elm/doctor.el b/modules/lang/elm/doctor.el index 37e3272b3..5e3379f00 100644 --- a/modules/lang/elm/doctor.el +++ b/modules/lang/elm/doctor.el @@ -1,5 +1,2 @@ ;;; lang/elm/doctor.el -*- lexical-binding: t; -*- -(assert! (or (not (modulep! +tree-sitter)) - (modulep! :tools tree-sitter)) - "This module requires (:tools tree-sitter)") From 3d2abf8b05f378ceff6b00f3249a57e85128b9ae Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 27 Aug 2025 17:19:08 +0200 Subject: [PATCH 44/71] feat(erlang): add treesit support --- modules/lang/erlang/config.el | 15 +++++++++++---- modules/lang/erlang/doctor.el | 4 ++++ modules/lang/erlang/packages.el | 3 +++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/modules/lang/erlang/config.el b/modules/lang/erlang/config.el index 32854a627..23914e243 100644 --- a/modules/lang/erlang/config.el +++ b/modules/lang/erlang/config.el @@ -5,9 +5,16 @@ :mode ("/rebar\\.config\\(?:\\.script\\)?\\'" . erlang-mode) :mode ("/\\(?:app\\|sys\\)\\.config\\'" . erlang-mode) :config - (set-formatter! 'erlfmt '("rebar3" "fmt" "-") :modes '(erlang-mode)) + (set-formatter! 'erlfmt '("rebar3" "fmt" "-") + :modes '(erlang-mode erlang-ts-mode)) (when (modulep! +lsp) - (add-hook 'erlang-mode-local-vars-hook #'lsp! 'append)) + (add-hook 'erlang-mode-local-vars-hook #'lsp! 'append))) - (when (modulep! +tree-sitter) - (add-hook 'erlang-mode-local-vars-hook #'tree-sitter! 'append))) + +(use-package! erlang-ts + :when (modulep! +tree-sitter) + :when (fboundp 'erlang-ts-mode) + :defer t + :init + (set-tree-sitter! 'erlang-mode 'erlang-ts-mode + '((erlang "https://github.com/WhatsApp/tree-sitter-erlang")))) diff --git a/modules/lang/erlang/doctor.el b/modules/lang/erlang/doctor.el index eca4a6039..006832da2 100644 --- a/modules/lang/erlang/doctor.el +++ b/modules/lang/erlang/doctor.el @@ -5,6 +5,10 @@ (modulep! :tools lsp)) "This module requires (:tools lsp)") +(assert! (or (not (modulep! +tree-sitter)) + (modulep! :tools tree-sitter)) + "This module requires (:tools tree-sitter)") + (when (modulep! :editor format) (unless (and (executable-find "rebar3") (zerop (car (doom-call-process "rebar3" "fmt" "-v")))) (warn! "Couldn't find erlfmt. Formatting will be disabled."))) diff --git a/modules/lang/erlang/packages.el b/modules/lang/erlang/packages.el index 88de226ae..6777483ef 100644 --- a/modules/lang/erlang/packages.el +++ b/modules/lang/erlang/packages.el @@ -2,3 +2,6 @@ ;;; lang/erlang/packages.el (package! erlang :pin "b9d3ec017da091168918a2901a1cef4cb062fd2a") + +(when (modulep! +tree-sitter) + (package! erlang-ts :pin "eb579dd55fbb2cf721290939e7b3a50be19c0305")) From bf8576797549279ee7bd763a157b361322e04ae9 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 27 Aug 2025 17:21:33 +0200 Subject: [PATCH 45/71] refactor(graphviz): remove tree-sitter support No *-ts-mode exists for graphviz-dot-mode. The graphviz module will fall back to font-lock rules so this is not a breaking changing. --- modules/lang/graphviz/config.el | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/lang/graphviz/config.el b/modules/lang/graphviz/config.el index 7e390b09e..daae33ac1 100644 --- a/modules/lang/graphviz/config.el +++ b/modules/lang/graphviz/config.el @@ -8,10 +8,6 @@ :config (set-company-backend! 'graphviz-dot-mode 'company-graphviz-dot-backend) (set-formatter! 'graphviz-dot #'+graphviz-formatter :modes '(graphviz-dot-mode)) - (set-tree-sitter-lang! 'graphviz-dot-mode 'dot) - - (when (modulep! +tree-sitter) - (add-hook 'graphiz-dot-mode-hook #'tree-sitter!)) (after! dtrt-indent (add-to-list 'dtrt-indent-hook-mapping-list '(graphviz-mode graphviz-dot-indent-width))) From 6ca155ea112bd065b6512194d8a6cf0dc58a758e Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 27 Aug 2025 17:23:44 +0200 Subject: [PATCH 46/71] refactor(ess): remove tree-sitter support No *-ts-mode exists for ess-r-mode (or any other ess mode, afaik). The ess module will fall back to font-lock rules so this is not a breaking changing. --- modules/lang/ess/README.org | 3 --- modules/lang/ess/config.el | 3 --- 2 files changed, 6 deletions(-) diff --git a/modules/lang/ess/README.org b/modules/lang/ess/README.org index a09374034..c03439e36 100644 --- a/modules/lang/ess/README.org +++ b/modules/lang/ess/README.org @@ -13,9 +13,6 @@ SAS, Julia and Stata. ** Module flags - +stan :: Enable support for ~stan-mode~, including code completion and syntax checking. -- +tree-sitter :: - Leverages tree-sitter for better syntax highlighting and structural text - editing. Currently only supports ~ess-r-mode~. Requires [[doom-module::tools tree-sitter]]. ** Packages - [[doom-package:ess]] diff --git a/modules/lang/ess/config.el b/modules/lang/ess/config.el index d7d97e69a..d58c5bee7 100644 --- a/modules/lang/ess/config.el +++ b/modules/lang/ess/config.el @@ -24,9 +24,6 @@ (when (modulep! +lsp) (add-hook 'ess-r-mode-local-vars-hook #'lsp! 'append)) - (when (modulep! +tree-sitter) - (add-hook 'ess-r-mode-local-vars-hook #'tree-sitter! 'append)) - (set-repl-handler! 'ess-r-mode #'run-ess-r) (set-repl-handler! 'ess-julia-mode #'run-ess-julia) (set-lookup-handlers! '(ess-r-mode ess-julia-mode) From 07e7c699cf968a6e5578a5770f4583365c5ad2ef Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 27 Aug 2025 17:26:25 +0200 Subject: [PATCH 47/71] feat(java): add treesit support --- modules/lang/java/config.el | 11 ++++++++--- modules/lang/java/doctor.el | 4 ++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/modules/lang/java/config.el b/modules/lang/java/config.el index 12eb46377..1dab9a892 100644 --- a/modules/lang/java/config.el +++ b/modules/lang/java/config.el @@ -30,13 +30,18 @@ If the depth is 2, the first two directories are removed: net.lissner.game.") (modulep! :tools lsp -eglot)) (load! "+lsp")) -(when (modulep! +tree-sitter) - (add-hook 'java-mode-local-vars-hook #'tree-sitter! 'append)) - ;; ;;; Common packages +(use-package! java-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'java-ts-mode) ; 29.1+ only + :defer t + :init + (set-tree-sitter! 'java-mode 'java-ts-mode '(java doxygen))) + + (use-package! android-mode :commands android-mode :init diff --git a/modules/lang/java/doctor.el b/modules/lang/java/doctor.el index 9e0a9a1aa..102ec263e 100644 --- a/modules/lang/java/doctor.el +++ b/modules/lang/java/doctor.el @@ -9,6 +9,10 @@ (modulep! :tools tree-sitter)) "This module requires (:tools tree-sitter)") +(assert! (or (not (modulep! +tree-sitter)) + (fboundp 'java-ts-mode)) + "Can't find `java-ts-mode'; Emacs 29.1+ is required") + (unless (executable-find "javac") (warn! "Couldn't find the javac executable, are you sure the JDK is installed?")) From 6b203d74c9fb6f1cc6df8d1c2e4fc973c7b930fc Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 27 Aug 2025 17:32:56 +0200 Subject: [PATCH 48/71] refactor(sh): remove tree-sitter support bash-ts-mode is inferior to shell-script-mode's syntax highlighting and no other *-ts-mode modes are available for other shells (though, there *are* powershell and nushell ts-modes; I'll investigate those later). --- modules/lang/sh/README.org | 5 +---- modules/lang/sh/config.el | 3 --- modules/lang/sh/doctor.el | 4 ---- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/modules/lang/sh/README.org b/modules/lang/sh/README.org index 130aed01c..fcaa225be 100644 --- a/modules/lang/sh/README.org +++ b/modules/lang/sh/README.org @@ -23,10 +23,7 @@ Fish script) to Doom Emacs. (supports bash-language-server). - +powershell :: Add syntax highlighting for Powershell script files (=.ps1= and =.psm1=). -- +tree-sitter :: - Leverages tree-sitter for better syntax highlighting and structural text - editing. Requires [[doom-module::tools tree-sitter]]. - + ** Packages - [[doom-package:company-shell]] if [[doom-module::completion company]] - [[doom-package:fish-mode]] if [[doom-module:+fish]] diff --git a/modules/lang/sh/config.el b/modules/lang/sh/config.el index 7bb128b6b..ae08047af 100755 --- a/modules/lang/sh/config.el +++ b/modules/lang/sh/config.el @@ -37,9 +37,6 @@ (when (modulep! +lsp) (add-hook 'sh-mode-local-vars-hook #'lsp! 'append)) - (when (modulep! +tree-sitter) - (add-hook 'sh-mode-local-vars-hook #'tree-sitter! 'append)) - (setq sh-indent-after-continuation 'always) ;; [pedantry intensifies] diff --git a/modules/lang/sh/doctor.el b/modules/lang/sh/doctor.el index a5a6ce2a5..60446af00 100644 --- a/modules/lang/sh/doctor.el +++ b/modules/lang/sh/doctor.el @@ -7,7 +7,3 @@ (when (modulep! :editor format) (unless (executable-find "shfmt") (warn! "Couldn't find shfmt. Code formatting will not work."))) - -(assert! (or (modulep! -tree-sitter) - (modulep! :tools tree-sitter)) - "This module requires (:tools tree-sitter)") From 5bf132a80fd20f1fe77a01e5b994e9cdf668e9b4 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 27 Aug 2025 17:38:40 +0200 Subject: [PATCH 49/71] feat(web): add treesit support (for html/css) --- modules/lang/web/+css.el | 9 +++++++-- modules/lang/web/+html.el | 19 +++++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/modules/lang/web/+css.el b/modules/lang/web/+css.el index 2211abc50..afb4400a7 100644 --- a/modules/lang/web/+css.el +++ b/modules/lang/web/+css.el @@ -73,5 +73,10 @@ If set to `nil', disable all the above behaviors.") less-css-mode-local-vars-hook) :append #'lsp!)) -(when (modulep! +tree-sitter) - (add-hook 'css-mode-local-vars-hook #'tree-sitter! 'append)) + +(use-package! css-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'css-ts-mode) ; 29.1+ only + :defer t + :init + (set-tree-sitter! 'css-mode 'css-ts-mode 'css)) diff --git a/modules/lang/web/+html.el b/modules/lang/web/+html.el index e9abf0227..00417a42d 100644 --- a/modules/lang/web/+html.el +++ b/modules/lang/web/+html.el @@ -167,7 +167,18 @@ nxml-mode-local-vars-hook) :append #'lsp!)) -(when (modulep! +tree-sitter) - (add-hook! '(html-mode-local-vars-hook - mhtml-mode-local-vars-hook) - :append #'tree-sitter!)) + +(use-package! html-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'html-ts-mode) ; 30.1+ only + :defer t + :init + (set-tree-sitter! 'html-mode 'html-ts-mode 'html)) + + +(use-package! mhtml-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'mhtml-ts-mode) ; 31+ only + :defer t + :init + (set-tree-sitter! 'mhtml-mode 'mhtml-ts-mode 'html)) From cfadd8f6a45a1380aa093500175767a905011aa5 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 28 Aug 2025 13:45:03 +0200 Subject: [PATCH 50/71] feat(sml): add treesit (and lsp) support --- modules/lang/sml/README.org | 10 ++++++++-- modules/lang/sml/config.el | 22 +++++++++++++++++++--- modules/lang/sml/doctor.el | 4 ++++ modules/lang/sml/packages.el | 2 ++ 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/modules/lang/sml/README.org b/modules/lang/sml/README.org index 745651e02..1b2b3be7e 100644 --- a/modules/lang/sml/README.org +++ b/modules/lang/sml/README.org @@ -4,17 +4,23 @@ #+since: 21.12.0 * Description :unfold: -THis module adds [[https://smlfamily.github.io/][SML (Standard ML) programming language]] support to Doom Emacs. +This module adds [[https://smlfamily.github.io/][SML (Standard ML) programming language]] support to Doom Emacs. ** Maintainers *This module needs a maintainer.* [[doom-contrib-maintainer:][Become a maintainer?]] ** Module flags -/This module has no flags./ +- +lsp :: + Enable LSP support for ~sml-mode~/~sml-ts-mode~. Requires [[doom-module::tools lsp]] + and a langserver (supports [[https://github.com/azdavis/millet][millet-ls]]). +- +tree-sitter :: + Leverages tree-sitter for better syntax highlighting and structural text + editing. Requires [[doom-module::tools tree-sitter]]. ** Packages - [[doom-package:company-mlton]] if [[doom-module::completion company]] - [[doom-package:sml-mode]] +- [[doom-package:sml-ts-mode]] if [[doom-module:+tree-sitter]] ** Hacks /No hacks documented for this module./ diff --git a/modules/lang/sml/config.el b/modules/lang/sml/config.el index 9755cd33e..81493bfcc 100644 --- a/modules/lang/sml/config.el +++ b/modules/lang/sml/config.el @@ -3,11 +3,14 @@ (use-package! sml-mode :mode "\\.s\\(?:ml\\|ig\\)\\'" :config - (set-repl-handler! 'sml-mode #'run-sml) - (set-formatter! 'smlformat '("smlformat") :modes '(sml-mode)) + (set-repl-handler! '(sml-mode sml-ts-mode) #'run-sml) + (set-formatter! 'smlformat '("smlformat") :modes '(sml-mode sml-ts-mode)) + + (when (modulep! +lsp) + (add-hook 'sml-mode-local-vars-hook #'lsp! 'append)) ;; don't auto-close apostrophes (type 'a = foo) and backticks (`Foo) - (sp-with-modes 'sml-mode + (sp-with-modes '(sml-mode sml-ts-mode) (sp-local-pair "'" nil :actions nil) (sp-local-pair "`" nil :actions nil)) @@ -23,6 +26,19 @@ :desc "Run region" "r" #'sml-prog-proc-send-region)) +;; TODO: Mirror sml-mode keybinds to ts-mode +(use-package! sml-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'treesit-available-p) + :defer t + :init + (set-tree-sitter! 'sml-mode 'sml-ts-mode + '((sml :url "https://github.com/MatthewFluet/tree-sitter-sml"))) + :config + (when (modulep! +lsp) + (add-hook 'sml-ts-mode-local-vars-hook #'lsp! 'append))) + + (use-package! company-mlton :when (modulep! :completion company) :hook (sml-mode . company-mlton-init) diff --git a/modules/lang/sml/doctor.el b/modules/lang/sml/doctor.el index de483c420..eb21317a5 100644 --- a/modules/lang/sml/doctor.el +++ b/modules/lang/sml/doctor.el @@ -1,5 +1,9 @@ ;;; lang/sml/doctor.el -*- lexical-binding: t; -*- +(assert! (or (not (modulep! +tree-sitter)) + (modulep! :tools tree-sitter)) + "This module requires (:tools tree-sitter)") + (when (modulep! :editor format) (unless (executable-find "smlformat") (warn! "Couldn't find smlformat. Formatting will be disabled."))) diff --git a/modules/lang/sml/packages.el b/modules/lang/sml/packages.el index 08879072e..3322c9f8a 100644 --- a/modules/lang/sml/packages.el +++ b/modules/lang/sml/packages.el @@ -6,3 +6,5 @@ (package! company-mlton :recipe (:host github :repo "MatthewFluet/company-mlton" :files ("*.el" "*.basis")) :pin "9b09d209b4767a2af24784fb5321390ed1d445bf")) +(when (modulep! +tree-sitter) + (package! sml-ts-mode :pin "d2dabcc9d8f91eeee7048641e4c80fabb3583194")) From 93c085fa13fd9a4249328e47e35ecfebb9c223da Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 28 Aug 2025 14:00:48 +0200 Subject: [PATCH 51/71] feat(qt): add treesit (and lsp) support --- modules/lang/qt/README.org | 8 +++++++- modules/lang/qt/autoload.el | 10 ++++++++++ modules/lang/qt/doctor.el | 9 +++++++++ modules/lang/qt/packages.el | 6 ++++++ 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 modules/lang/qt/doctor.el diff --git a/modules/lang/qt/README.org b/modules/lang/qt/README.org index 2470b3b5d..a549e0292 100644 --- a/modules/lang/qt/README.org +++ b/modules/lang/qt/README.org @@ -13,10 +13,16 @@ This module provides language functionality for [[https://qt.io][Qt]] specific f *This module needs a maintainer.* [[doom-contrib-maintainer:][Become a maintainer?]] ** Module flags -/This module has no flags./ +- +lsp :: + Enable LSP support for ~qml-mode~/~qml-ts-mode~. Requires [[doom-module::tools lsp]] + and a langserver (supports [[https://doc.qt.io/qt-6/qtqml-tooling-qmlls.html][qmlls]]). +- +tree-sitter :: + Leverages tree-sitter for better syntax highlighting and structural text + editing. Requires [[doom-module::tools tree-sitter]]. ** Packages - [[doom-package:qml-mode]] +- [[doom-package:qml-ts-mode]] if [[doom-module:+tree-sitter]] - [[doom-package:qt-pro-mode]] ** Hacks diff --git a/modules/lang/qt/autoload.el b/modules/lang/qt/autoload.el index ba5db146c..805be65b1 100644 --- a/modules/lang/qt/autoload.el +++ b/modules/lang/qt/autoload.el @@ -2,3 +2,13 @@ ;;;###autoload (add-to-list 'auto-mode-alist '("\\.pr[io]\\'" . qt-pro-mode)) + +;;;###autoload +(when (modulep! +tree-sitter) + (set-tree-sitter! 'qml-mode 'qml-ts-mode + '((qmljs :url "https://github.com/yuja/tree-sitter-qmljs")))) + +;;;###autoload +(when (modulep! +lsp) + (add-hook 'qml-mode-local-vars-hook #'lsp! 'append) + (add-hook 'qml-ts-mode-local-vars-hook #'lsp! 'append)) diff --git a/modules/lang/qt/doctor.el b/modules/lang/qt/doctor.el new file mode 100644 index 000000000..1fb1dd978 --- /dev/null +++ b/modules/lang/qt/doctor.el @@ -0,0 +1,9 @@ +;;; lang/qt/doctor.el -*- lexical-binding: t; -*- + +(assert! (or (not (modulep! +lsp)) + (modulep! :tools lsp)) + "This module requires (:tools lsp)") + +(assert! (or (not (modulep! +tree-sitter)) + (modulep! :tools tree-sitter)) + "This module requires (:tools tree-sitter)") diff --git a/modules/lang/qt/packages.el b/modules/lang/qt/packages.el index 22f01ef77..b60c95f0a 100644 --- a/modules/lang/qt/packages.el +++ b/modules/lang/qt/packages.el @@ -3,3 +3,9 @@ (package! qml-mode :pin "6c5f33ba88ae010bf201a80ee8095e20a724558c") (package! qt-pro-mode :pin "7a2da323de834294b413cbbb3c92f42f54913643") + +(when (modulep! +tree-sitter) + (package! qml-ts-mode + :recipe (:host github + :repo "xhcoding/qml-ts-mode") + :pin "b80c6663521b4d0083e416e6712ebc02d37b7aec")) From 64b4e565c3724c19025dea8c6200dd445c9c4875 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 28 Aug 2025 14:03:01 +0200 Subject: [PATCH 52/71] refactor(tree-sitter): remove redundant grammars Already registered by csharp and web module packages. Amend: 5bf132a80fd2 Amend: c403bb5e2f77 --- modules/tools/tree-sitter/config.el | 5 ----- 1 file changed, 5 deletions(-) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index b6c5c91e4..5a00fa24f 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -73,11 +73,7 @@ (dolist (map '((awk "https://github.com/Beaglefoot/tree-sitter-awk" nil nil nil nil) (bibtex "https://github.com/latex-lsp/tree-sitter-bibtex" nil nil nil nil) (blueprint "https://github.com/huanie/tree-sitter-blueprint" nil nil nil nil) - (c-sharp "https://github.com/tree-sitter/tree-sitter-c-sharp" nil nil nil nil) (commonlisp "https://github.com/tree-sitter-grammars/tree-sitter-commonlisp" nil nil nil nil) - (css "https://github.com/tree-sitter/tree-sitter-css" nil nil nil nil) - (html "https://github.com/tree-sitter/tree-sitter-html" nil nil nil nil) - (java "https://github.com/tree-sitter/tree-sitter-java" nil nil nil nil) (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src" nil nil) (latex "https://github.com/latex-lsp/tree-sitter-latex" nil nil nil nil) (make "https://github.com/tree-sitter-grammars/tree-sitter-make" nil nil nil nil) @@ -86,7 +82,6 @@ (perl "https://github.com/ganezdragon/tree-sitter-perl" nil nil nil nil) (proto "https://github.com/mitchellh/tree-sitter-proto" nil nil nil nil) (r "https://github.com/r-lib/tree-sitter-r" nil nil nil nil) - (rust "https://github.com/tree-sitter/tree-sitter-rust" nil nil nil nil) (sql "https://github.com/DerekStride/tree-sitter-sql" "gh-pages" nil nil nil) (surface "https://github.com/connorlay/tree-sitter-surface" nil nil nil nil) (toml "https://github.com/tree-sitter/tree-sitter-toml" nil nil nil nil) From f782b7979719c9c4e3280f120670c0abc49dcb32 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 28 Aug 2025 14:17:38 +0200 Subject: [PATCH 53/71] feat(graphql): add treesit support --- modules/lang/graphql/README.org | 4 +++ modules/lang/graphql/config.el | 43 ++++++++++++++++++++++---------- modules/lang/graphql/doctor.el | 5 ++++ modules/lang/graphql/packages.el | 2 ++ 4 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 modules/lang/graphql/doctor.el diff --git a/modules/lang/graphql/README.org b/modules/lang/graphql/README.org index e09e32f00..9e0821542 100644 --- a/modules/lang/graphql/README.org +++ b/modules/lang/graphql/README.org @@ -26,10 +26,14 @@ It includes: - +lsp :: Enable LSP support for ~graphql-mode~. Requires [[doom-module::tools lsp]] and a langserver ([[https://github.com/graphql/graphiql/tree/main/packages/graphql-language-service-cli#readme][graphql-language-service-cli]]). +- +tree-sitter :: + Leverages tree-sitter for better syntax highlighting and structural text + editing. Requires [[doom-module::tools tree-sitter]]. ** Packages - [[doom-package:company-graphql]] unless [[doom-module:+lsp]] - [[doom-package:graphql-mode]] +- [[doom-package:graphql-ts-mode]] if [[doom-module:+tree-sitter]] - [[doom-package:graphql-doc]] ** Hacks diff --git a/modules/lang/graphql/config.el b/modules/lang/graphql/config.el index f03597df1..3687b0aaf 100644 --- a/modules/lang/graphql/config.el +++ b/modules/lang/graphql/config.el @@ -1,22 +1,18 @@ ;;; lang/graphql/config.el -*- lexical-binding: t; -*- -(after! graphql-mode - (defface nerd-icons-rhodamine - '((t (:foreground "#E10098"))) - "Face for GraphQL icon." - :group 'nerd-icons-faces) +;; +;;; Packages + +(defun +graphql-common-config (mode) (if (modulep! +lsp) - (add-hook 'graphql-mode-local-vars-hook #'lsp! 'append) - (set-company-backend! 'graphql-mode 'company-graphql)) + (add-hook (intern (format "%s-local-vars-hook" mode)) #'lsp! 'append) + (set-company-backend! mode 'company-graphql)) - (add-hook 'graphql-mode-hook #'rainbow-delimiters-mode) - (set-docsets! 'graphql-mode :add "GraphQL Specification") - - (set-electric! 'graphql-mode + (set-docsets! mode :add "GraphQL Specification") + (set-electric! mode :chars '(?\} ?\)) :words '("or" "and")) - - (set-ligatures! 'graphql-mode + (set-ligatures! mode :null "null" :true "true" :false "false" :int "Int" :str "String" @@ -26,5 +22,26 @@ :not "not" :and "and" :or "or")) + +(after! graphql-mode + (defface nerd-icons-rhodamine + '((t (:foreground "#E10098"))) + "Face for GraphQL icon." + :group 'nerd-icons-faces) + (add-hook 'graphql-mode-hook #'rainbow-delimiters-mode) + (+graphql-common-config 'graphql-mode)) + + +(use-package! graphql-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'treesit-available-p) + :defer t + :init + (set-tree-sitter! 'graphql-mode 'graphql-ts-mode + '((graphql :url "https://github.com/bkegley/tree-sitter-graphql"))) + :config + (+graphql-common-config 'graphql-ts-mode)) + + (use-package! graphql-doc :after graphql-mode) diff --git a/modules/lang/graphql/doctor.el b/modules/lang/graphql/doctor.el new file mode 100644 index 000000000..94be43a97 --- /dev/null +++ b/modules/lang/graphql/doctor.el @@ -0,0 +1,5 @@ +;;; lang/graphql/doctor.el -*- lexical-binding: t; -*- + +(assert! (or (not (modulep! +tree-sitter)) + (modulep! :tools tree-sitter)) + "This module requires (:tools tree-sitter)") diff --git a/modules/lang/graphql/packages.el b/modules/lang/graphql/packages.el index 6f0b7c096..7b11285e2 100644 --- a/modules/lang/graphql/packages.el +++ b/modules/lang/graphql/packages.el @@ -7,3 +7,5 @@ (package! company-graphql :recipe (:host github :repo "thaenalpha/company-graphql") :pin "aed9f5109e877944a895d08fc08bad103f03096b")) +(when (modulep! +tree-sitter) + (package! graphql-ts-mode :pin "e933f235408ea195762700fd07c2d828e8f09aac")) From d20c5f1273b1c0b94a0079102e153e6852afc3b4 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 28 Aug 2025 14:29:34 +0200 Subject: [PATCH 54/71] docs(haskell): mention haskell-ts-mode package Amend: 47fe11cd767e --- modules/lang/haskell/README.org | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/lang/haskell/README.org b/modules/lang/haskell/README.org index 7fce1d721..553228a06 100644 --- a/modules/lang/haskell/README.org +++ b/modules/lang/haskell/README.org @@ -21,6 +21,7 @@ This module adds Haskell support to Doom Emacs. ** Packages - [[doom-package:haskell-mode]] +- [[doom-package:haskell-ts-mode]] if [[doom-module:+tree-sitter]] - [[doom-package:lsp-haskell]] if [[doom-module:+lsp]] ** Hacks From bd0bee92cc53d291fed34c0a1fb02767a4815d8c Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 29 Aug 2025 13:25:14 +0200 Subject: [PATCH 55/71] feat!(javascript): add treesit support BREAKING CHANGE: This commit removes a number of core packages and features from this module and only replaces a handful of them, so that we can lean more on LSP and tree-sitter. To be specific: - We used to rely on `rjsx-mode` (derived from js2-mode) for total JS/JSX support (though imperfect; Emacs was starved for options at the time). This has now been replaced with `js-ts-mode` (built-in after Emacs 29), falling back to `js-mode` (very rudimentary, but a decent fallback). - This also meant the removal of `js2-mode`, which `skewer-mode`, `js2-refactor`, and `xref-js2` depended on, so those were removed too, and have *somewhat* been replaced with LSP integration (offers jump-to-definition/references and *some* refactoring actions, but no replacement for skewer's functionality). - Typescript support no longer relies on the jury-rigged, web-mode-derived major mode (because TSX support in the upstream `typescript-mode` isn't great). We now use `typescript-ts-mode` (built-in into Emacs 29.1+), falling back to `typescript-mode`. - JSX/TSX support now *requires* tree-sitter (and Emacs 29.1+), where `tsx-ts-mode` is available and outshines all the alternatives (at the time of writing). Due to the absolute chaos that is webdev, this module sacrifices some of the graceful-degradation I've implemented for other modules and creates a hard requirement on tree-sitter and Emacs 29.1+ for JSX/TSX. It still tries to degrade gracefully for plain JS and TS, but the module's doctor and docs will actively recommend tree-sitter. Close: #5278 Fix: #6172 Fix: #7042 Close: #8447 Co-authored-by: ribaricplusplus --- modules/lang/javascript/README.org | 118 ++-------- modules/lang/javascript/config.el | 348 ++++++---------------------- modules/lang/javascript/doctor.el | 4 + modules/lang/javascript/packages.el | 18 +- modules/tools/tree-sitter/config.el | 3 - 5 files changed, 96 insertions(+), 395 deletions(-) diff --git a/modules/lang/javascript/README.org b/modules/lang/javascript/README.org index 419d37c2f..c51c78b9a 100644 --- a/modules/lang/javascript/README.org +++ b/modules/lang/javascript/README.org @@ -6,13 +6,14 @@ * Description :unfold: This module adds [[https://www.javascript.com/][JavaScript]] and [[https://www.typescriptlang.org/][TypeScript]] support to Doom Emacs. -- Code completion ([[doom-package:tide]]) -- REPL support ([[doom-package:nodejs-repl]]) -- Refactoring commands ([[doom-package:js2-refactor]]) -- Syntax checking ([[doom-package:flycheck]]) -- Browser code injection with [[doom-package:skewer-mode]] -- Coffeescript & JSX support -- Jump-to-definitions and references support ([[doom-package:xref]]) +- JSX/TSX support (requires [[doom-module:+tree-sitter]] and Emacs 29.1+) +- LSP Integration + - Code completion (with [[doom-module::completion corfu]] (recommended) or + [[doom-module::completion company]]) + - Syntax checking (with [[doom-module::checkers syntax]]) + - Jump-to-definitions and references support +- Code formatting (with [[doom-module::editor format]] and [[https://prettier.io/docs/en/install.html][prettier]]) +- REPL support (with [[doom-package:nodejs-repl]] and/or [[doom-module::tools eval]]) ** Maintainers - [[doom-user:][@elken]] @@ -23,22 +24,17 @@ This module adds [[https://www.javascript.com/][JavaScript]] and [[https://www.t ** Module flags - +lsp :: - Enable LSP support for ~js2-mode~, ~rjsx-mode~, JS in ~web-mode~, and - ~typescript-mode~. Requires [[doom-module::tools lsp]] and a langserver (supports ts-ls and - deno-ls). + Enable LSP support for ~js-mode~, ~js-ts-mode~, ~typesript-mode~, and + ~typescript-ts-mode. Requires [[doom-module::tools lsp]] and a langserver + (supports ts-ls and deno-ls). - +tree-sitter :: Leverages tree-sitter for better syntax highlighting and structural text - editing. Requires [[doom-module::tools tree-sitter]]. + editing. Requires [[doom-module::tools tree-sitter]]. Requires Emacs 29.1+. + Required for JSX/TSX support. ** Packages -- [[doom-package:js2-refactor]] - [[doom-package:nodejs-repl]] -- [[doom-package:npm-mode]] -- [[doom-package:rjsx-mode]] -- [[doom-package:skewer-mode]] (DEPRECATED) -- [[doom-package:tide]] -- [[doom-package:typescript-mode]] -- [[doom-package:xref-js2]] if [[doom-module::tools lookup]] +- [[doom-package:typescript-mode]] unless [[doom-module:+tree-sitter]] ** TODO Hacks #+begin_quote @@ -59,97 +55,13 @@ This module requires [[https://nodejs.org/en/][NodeJS]] and one of [[https://www - openSUSE: ~$ zypper install nodejs npm~ ** Formatter - Formatting is handled using the [[doom-module::editor format]] module via [[https://prettier.io/docs/en/install.html][prettier]]. * TODO Usage #+begin_quote - 󱌣 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]] + 󱌣 This module has no usage documentation yet. [[doom-contrib-module:][Write some?]] #+end_quote -~rjsx-mode~ is used for all javascript buffers. - -** Commands -*** rjsx-mode -| command | key / ex command | description | -|----------------------------------+------------------+------------------------------------------------------------| -| ~+javascript/open-repl~ | ~:repl~ | Open the NodeJS REPL (or send the current selection to it) | -| ~+javascript/skewer-this-buffer~ | [[kbd:][ S]] | Attaches a browser to the current buffer | - -*** Tide -| command | key / ex command | description | -|-------------------------+---------------------+------------------------| -| ~tide-restart-server~ | [[kbd:][ R]] | Restart tide server | -| ~tide-reformat~ | [[kbd:][ f]] | Reformat region | -| ~tide-rename-symbol~ | [[kbd:][ r r s]] | Rename symbol at point | -| ~tide-organize-imports~ | [[kbd:][ r o i]] | Organize imports | - -*** Refactoring (js2-refactor-mode) -| command | key / ex command | description | -|---------------------------------------------------+---------------------+--------------------------------------------------------------------------------------------------------------------| -| ~js2r-expand-node-at-point~ | [[kbd:][ r e e]] | Expand bracketed list according to node type at point | -| ~js2r-contract-node-at-point~ | [[kbd:][ r c c]] | Contract bracketed list according to node type at point | -| ~js2r-extract-function~ | [[kbd:][ r e f]] | Extracts the marked expressions out into a new named function. | -| ~js2r-extract-method~ | [[kbd:][ r e m]] | Extracts the marked expressions out into a new named method in an object literal. | -| ~js2r-toggle-function-expression-and-declaration~ | [[kbd:][ r t f]] | Toggle between function name() {} and var name = function (); | -| ~js2r-toggle-arrow-function-and-expression~ | [[kbd:][ r t a]] | Toggle between function expression to arrow function. | -| ~js2r-toggle-function-async~ | [[kbd:][ r t s]] | Toggle between an async and a regular function. | -| ~js2r-introduce-parameter~ | [[kbd:][ r i p]] | Changes the marked expression to a parameter in a local function. | -| ~js2r-localize-parameter~ | [[kbd:][ r l p]] | Changes a parameter to a local var in a local function. | -| ~js2r-wrap-buffer-in-iife~ | [[kbd:][ r w i]] | Wraps the entire buffer in an immediately invoked function expression | -| ~js2r-inject-global-in-iife~ | [[kbd:][ r i g]] | Creates a shortcut for a marked global by injecting it in the wrapping immediately invoked function expression | -| ~js2r-add-to-globals-annotation~ | [[kbd:][ r a g]] | Creates a /*global */ annotation if it is missing, and adds the var at point to it. | -| ~js2r-extract-var~ | [[kbd:][ r e v]] | Takes a marked expression and replaces it with a var. | -| ~js2r-extract-let~ | [[kbd:][ r e l]] | Similar to extract-var but uses a let-statement. | -| ~js2r-extract-const~ | [[kbd:][ r e c]] | Similar to extract-var but uses a const-statement. | -| ~js2r-inline-var~ | [[kbd:][ r i v]] | Replaces all instances of a variable with its initial value. | -| ~js2r-rename-var~ | [[kbd:][ r r v]] | Renames the variable on point and all occurrences in its lexical scope. | -| ~js2r-var-to-this~ | [[kbd:][ r v t]] | Changes local var a to be this.a instead. | -| ~js2r-arguments-to-object~ | [[kbd:][ r a o]] | Replaces arguments to a function call with an object literal of named arguments. | -| ~js2r-ternary-to-if~ | [[kbd:][ r 3 i]] | Converts ternary operator to if-statement. | -| ~js2r-split-var-declaration~ | [[kbd:][ r s v]] | Splits a var with multiple vars declared, into several var statements. | -| ~js2r-split-string~ | [[kbd:][ r s s]] | Splits a string. | -| ~js2r-string-to-template~ | [[kbd:][ r s t]] | Converts a string into a template string. | -| ~js2r-unwrap~ | [[kbd:][ r u w]] | Replaces the parent statement with the selected region. | -| ~js2r-log-this~ | [[kbd:][ r l t]] | Adds a console.log() statement for what is at point (or region). With a prefix argument, use JSON pretty-printing. | -| ~js2r-debug-this~ | [[kbd:][ r d t]] | Adds a debug() statement for what is at point (or region). | -| ~js2r-forward-slurp~ | [[kbd:][ r s l]] | Moves the next statement into current function, if-statement, for-loop or while-loop. | -| ~js2r-forward-barf~ | [[kbd:][ r b a]] | Moves the last child out of current function, if-statement, for-loop or while-loop. | -| ~js2r-kill~ | [[kbd:][ r k]] | Kills to the end of the line, but does not cross semantic boundaries. | - -*** skewer-mode -**** general -| command | key / ex command | description | -|-------------------------------+-------------------+---------------------------------------| -| ~skewer-eval-last-expression~ | [[kbd:][ s E]] | Evaluate last expression | -| ~skewer-eval-defun~ | [[kbd:][ s e]] | Evaluate function definition at point | -| ~skewer-load-buffer~ | [[kbd:][ s f]] | Load buffer into REPL | - -**** css -| command | key / ex command | description | -|---------------------------------------+-------------------+-------------------------------| -| ~skewer-css-eval-current-declaration~ | [[kbd:][ s e]] | Evaluate declaration at point | -| ~skewer-css-eval-current-rule~ | [[kbd:][ s r]] | Evaluate rule at point | -| ~skewer-css-eval-buffer~ | [[kbd:][ s b]] | Evaluate buffer | -| ~skewer-css-clear-all~ | [[kbd:][ s c]] | Clear all rules | - -**** html -| command | key / ex command | description | -|------------------------+-------------------+-----------------------| -| ~skewer-html-eval-tag~ | [[kbd:][ s e]] | Evaluate tag at point | - -*** npm-mode -| command | key / ex command | description | -|---------------------------------+-------------------+------------------------------------------------------------------| -| ~npm-mode-npm-init~ | [[kbd:][ n n]] | Initialize npm project | -| ~npm-mode-npm-install~ | [[kbd:][ n i]] | Install npm package | -| ~npm-mode-npm-install-save~ | [[kbd:][ n s]] | Install npm package and save to package.json | -| ~npm-mode-npm-install-save-dev~ | [[kbd:][ n d]] | Install npm package and save to package.json as a dev dependency | -| ~npm-mode-npm-uninstall~ | [[kbd:][ n u]] | Uninstall npm package | -| ~npm-mode-npm-list~ | [[kbd:][ n l]] | List npm packages | -| ~npm-mode-npm-run~ | [[kbd:][ n r]] | Run npm task | -| ~npm-mode-visit-project-file~ | [[kbd:][ n v]] | Find file in npm project | - * TODO Configuration #+begin_quote 󱌣 This module has no configuration documentation yet. [[doom-contrib-module:][Write some?]] diff --git a/modules/lang/javascript/config.el b/modules/lang/javascript/config.el index 2e9cbe5f7..4496d98e0 100644 --- a/modules/lang/javascript/config.el +++ b/modules/lang/javascript/config.el @@ -8,305 +8,101 @@ ;; ;;; Major modes -(dolist (feature '(rjsx-mode - typescript-mode - web-mode - (nodejs-repl-mode . nodejs-repl))) - (let ((pkg (or (cdr-safe feature) feature)) - (mode (or (car-safe feature) feature))) - (with-eval-after-load pkg - (set-docsets! mode "JavaScript" - "AngularJS" "Backbone" "BackboneJS" "Bootstrap" "D3JS" "EmberJS" "Express" - "ExtJS" "JQuery" "JQuery_Mobile" "JQuery_UI" "KnockoutJS" "Lo-Dash" - "MarionetteJS" "MomentJS" "NodeJS" "PrototypeJS" "React" "RequireJS" - "SailsJS" "UnderscoreJS" "VueJS" "ZeptoJS") - (set-ligatures! mode - ;; Functional - :def "function" - :lambda "() =>" - :composition "compose" - ;; Types - :null "null" - :true "true" :false "false" - ;; Flow - :not "!" - :and "&&" :or "||" - :for "for" - :return "return" - ;; Other - :yield "import")))) +(defun +javascript-common-config (mode) + (unless (eq mode 'nodejs-repl-mode) + (set-repl-handler! mode #'+javascript/open-repl) + (set-electric! mode :chars '(?\} ?\) ?. ?:)) + (set-ligatures! mode + ;; Functional + :def "function" + :lambda "() =>" + :composition "compose" + ;; Types + :null "null" + :true "true" :false "false" + ;; Flow + :not "!" + :and "&&" :or "||" + :for "for" + :return "return" + ;; Other + :yield "import") + + (when (modulep! +lsp) + (add-hook (intern (format "%s-local-vars-hook" mode)) #'lsp! 'append))) + + (pcase mode + ((or 'js-mode 'js-ts-mode 'nodejs-repl-mode) + (set-docsets! mode "JavaScript" + "AngularJS" "Backbone" "BackboneJS" "Bootstrap" "D3JS" "EmberJS" "Express" + "ExtJS" "JQuery" "JQuery_Mobile" "JQuery_UI" "KnockoutJS" "Lo-Dash" + "MarionetteJS" "MomentJS" "NodeJS" "PrototypeJS" "React" "RequireJS" + "SailsJS" "UnderscoreJS" "VueJS" "ZeptoJS")) + ((or 'typescript-mode 'typescript-ts-mode) + (set-docsets! mode :add "TypeScript" "AngularTS") + (set-electric! mode :chars '(?\} ?\)) :words '("||" "&&"))))) -(use-package! rjsx-mode +(use-package! js-mode :mode "\\.[mc]?js\\'" :mode "\\.es6\\'" :mode "\\.pac\\'" - :interpreter "node" - :hook (rjsx-mode . rainbow-delimiters-mode) - :init - ;; Parse node stack traces in the compilation buffer - (after! compilation - (add-to-list 'compilation-error-regexp-alist 'node) - (add-to-list 'compilation-error-regexp-alist-alist - '(node "^[[:blank:]]*at \\(.*(\\|\\)\\(.+?\\):\\([[:digit:]]+\\):\\([[:digit:]]+\\)" - 2 3 4))) :config - (set-repl-handler! 'rjsx-mode #'+javascript/open-repl) - (set-electric! 'rjsx-mode :chars '(?\} ?\) ?. ?:)) + (setq js-chain-indent t) + (+javascript-common-config 'js-mode)) - (setq js-chain-indent t - ;; These have become standard in the JS community - js2-basic-offset 2 - ;; Don't mishighlight shebang lines - js2-skip-preprocessor-directives t - ;; let flycheck handle this - js2-mode-show-parse-errors nil - js2-mode-show-strict-warnings nil - ;; Flycheck provides these features, so disable them: conflicting with - ;; the eslint settings. - js2-strict-missing-semi-warning nil - ;; maximum fontification - js2-highlight-level 3 - js2-idle-timer-delay 0.15) - (setq-hook! 'rjsx-mode-hook - ;; Indent switch-case another step - js-switch-indent-offset js2-basic-offset) - - (use-package! xref-js2 - :when (modulep! :tools lookup) - :init - (setq xref-js2-search-program 'rg) - (set-lookup-handlers! 'rjsx-mode - :xref-backend #'xref-js2-xref-backend)) - - ;; HACK `rjsx-electric-gt' relies on js2's parser to tell it when the cursor - ;; is in a self-closing tag, so that it can insert a matching ending tag - ;; at point. The parser doesn't run immediately however, so a fast typist - ;; can outrun it, causing tags to stay unclosed, so force it to parse: - (defadvice! +javascript-reparse-a (n) - ;; if n != 1, rjsx-electric-gt calls rjsx-maybe-reparse itself - :before #'rjsx-electric-gt - (if (= n 1) (rjsx-maybe-reparse)))) +(use-package! js-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'js-ts-mode) ; 29.1+ only + :defer t + :init + (set-tree-sitter! 'js-mode 'js-ts-mode 'javascript) + (+javascript-common-config 'js-ts-mode)) (use-package! typescript-mode - :hook (typescript-mode . rainbow-delimiters-mode) - :hook (typescript-tsx-mode . rainbow-delimiters-mode) - :init - (when (modulep! :lang web) - (autoload 'typescript-tsx-mode "typescript-mode" nil t)) - - ;; REVIEW We associate TSX files with `typescript-tsx-mode' derived from - ;; `web-mode' because `typescript-mode' does not officially support - ;; JSX/TSX. See emacs-typescript/typescript.el#4 - (add-to-list 'auto-mode-alist - (cons "\\.tsx\\'" - (if (modulep! :lang web) - #'typescript-tsx-mode - #'typescript-mode))) - - (when (modulep! :checkers syntax -flymake) - (after! flycheck - (flycheck-add-mode 'javascript-eslint 'web-mode) - (flycheck-add-mode 'javascript-eslint 'typescript-mode) - (flycheck-add-mode 'javascript-eslint 'typescript-tsx-mode) - (flycheck-add-mode 'typescript-tslint 'typescript-tsx-mode) - (unless (modulep! +lsp) - (after! tide - (flycheck-add-next-checker 'typescript-tide '(warning . javascript-eslint) 'append) - (flycheck-add-mode 'typescript-tide 'typescript-tsx-mode))) - (add-hook! 'typescript-tsx-mode-hook - (defun +javascript-disable-tide-checkers-h () - (pushnew! flycheck-disabled-checkers - 'javascript-jshint - 'tsx-tide - 'jsx-tide))))) + :unless (modulep! +tree-sitter) + :mode "\\.ts\\'" :config - (when (fboundp 'web-mode) - (define-derived-mode typescript-tsx-mode web-mode "TypeScript-TSX") - (when (modulep! +lsp) - (after! lsp-mode - (add-to-list 'lsp--formatting-indent-alist '(typescript-tsx-mode . typescript-indent-level)))) - (when (modulep! +tree-sitter) - (after! evil-textobj-tree-sitter - (pushnew! evil-textobj-tree-sitter-major-mode-language-alist '(typescript-tsx-mode . "tsx"))) - (after! tree-sitter - (pushnew! tree-sitter-major-mode-language-alist '(typescript-tsx-mode . tsx))) - ;; HACK: the tsx grammer doesn't work with the hightlighting provided by - ;; font-lock-keywords. See emacs-tree-sitter/tree-sitter-langs#23 - (setq-hook! 'typescript-tsx-mode-hook - tree-sitter-hl-use-font-lock-keywords nil))) + (+javascript-common-config 'typescript-mode)) - (set-docsets! '(typescript-mode typescript-tsx-mode) - :add "TypeScript" "AngularTS") - (set-electric! '(typescript-mode typescript-tsx-mode) - :chars '(?\} ?\)) - :words '("||" "&&")) - ;; HACK Fixes comment continuation on newline - (autoload 'js2-line-break "js2-mode" nil t) - (setq-hook! 'typescript-mode-hook - comment-line-break-function #'js2-line-break - ;; Most projects use either eslint, prettier, .editorconfig, or tsf in order - ;; to specify indent level and formatting. In the event that no - ;; project-level config is specified (very rarely these days), the community - ;; default is 2, not 4. However, respect what is in tsfmt.json if it is - ;; present in the project - typescript-indent-level - (or (and (bound-and-true-p tide-mode) - (plist-get (tide-tsfmt-options) :indentSize)) - typescript-indent-level) +(use-package! typescript-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'typescript-ts-mode) ; 29.1+ only + :mode "\\.ts\\'" + :init + (set-tree-sitter! 'typescript-mode 'typescript-ts-mode 'typescript) + :config + (+javascript-common-config 'typescript-ts-mode)) - ;; Fix #5556: expand .x to className="x" instead of class="x", if - ;; `emmet-mode' is used. - emmet-expand-jsx-className? t)) + +(use-package! tsx-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'tsx-ts-mode) ; 29.1+ only + :mode "\\.[tj]sx\\'" + :defer t + :config + (+javascript-common-config 'tsx-ts-mode)) ;; -;;; Tools +;;; Extensions -(when (modulep! +tree-sitter) - (add-hook! '(js2-mode-local-vars-hook - typescript-mode-local-vars-hook - typescript-tsx-mode-local-vars-hook - rjsx-mode-local-vars-hook) - :append #'tree-sitter!)) - -(add-hook! '(typescript-mode-local-vars-hook - typescript-tsx-mode-local-vars-hook - web-mode-local-vars-hook - rjsx-mode-local-vars-hook) - (defun +javascript-init-lsp-or-tide-maybe-h () - "Start `lsp' or `tide' in the current buffer. - -LSP will be used if the +lsp flag is enabled for :lang javascript AND if the -current buffer represents a file in a project. - -If LSP fails to start (e.g. no available server or project), then we fall back -to tide." - (let ((buffer-file-name (buffer-file-name (buffer-base-buffer)))) - (when (derived-mode-p 'js-mode 'typescript-mode 'typescript-tsx-mode) - (if (null buffer-file-name) - ;; necessary because `tide-setup' and `lsp' will error if not a - ;; file-visiting buffer - (add-hook 'after-save-hook #'+javascript-init-lsp-or-tide-maybe-h - nil 'local) - (or (if (modulep! +lsp) (lsp!)) - ;; fall back to tide - (if (executable-find "node") - (and (require 'tide nil t) - (progn (tide-setup) tide-mode)) - (ignore - (doom-log "Couldn't start tide because 'node' is missing")))) - (remove-hook 'after-save-hook #'+javascript-init-lsp-or-tide-maybe-h - 'local)))))) +;; Parse node stack traces in the compilation buffer +(after! compilation + (add-to-list 'compilation-error-regexp-alist 'node) + (add-to-list 'compilation-error-regexp-alist-alist + '(node "^[[:blank:]]*at \\(.*(\\|\\)\\(.+?\\):\\([[:digit:]]+\\):\\([[:digit:]]+\\)" + 2 3 4))) -(use-package! tide - :hook (tide-mode . tide-hl-identifier-mode) - :config - (set-company-backend! 'tide-mode 'company-tide) - ;; navigation - (set-lookup-handlers! 'tide-mode :async t - :xref-backend #'xref-tide-xref-backend - :documentation #'tide-documentation-at-point) - (set-popup-rule! "^\\*tide-documentation" :quit t) - - (setq tide-completion-detailed t - tide-always-show-documentation t - ;; Fix #1792: by default, tide ignores payloads larger than 100kb. This - ;; is too small for larger projects that produce long completion lists, - ;; so we up it to 512kb. - tide-server-max-response-length 524288 - ;; We'll handle it - tide-completion-setup-company-backend nil) - - ;; Resolve to `doom-project-root' if `tide-project-root' fails - (advice-add #'tide-project-root :override #'+javascript-tide-project-root-a) - - ;; Cleanup tsserver when no tide buffers are left - (add-hook! 'tide-mode-hook - (add-hook 'kill-buffer-hook #'+javascript-cleanup-tide-processes-h - nil 'local)) - - ;; Eldoc is activated too soon and disables itself, thinking there is no eldoc - ;; support in the current buffer, so we must re-enable it later once eldoc - ;; support exists. It is set *after* tide-mode is enabled, so enabling it on - ;; `tide-mode-hook' is too early, so... - (advice-add #'tide-setup :after #'eldoc-mode) - - (map! :localleader - :map tide-mode-map - "R" #'tide-restart-server - "f" #'tide-format - "rrs" #'tide-rename-symbol - "roi" #'tide-organize-imports)) - - -(use-package! js2-refactor - :hook ((js2-mode rjsx-mode) . js2-refactor-mode) +(use-package! nodejs-repl + :defer t :init - (map! :after js2-mode - :map js2-mode-map - :localleader - (:prefix ("r" . "refactor") - (:prefix ("a" . "add/arguments")) - (:prefix ("b" . "barf")) - (:prefix ("c" . "contract")) - (:prefix ("d" . "debug")) - (:prefix ("e" . "expand/extract")) - (:prefix ("i" . "inject/inline/introduce")) - (:prefix ("l" . "localize/log")) - (:prefix ("o" . "organize")) - (:prefix ("r" . "rename")) - (:prefix ("s" . "slurp/split/string")) - (:prefix ("t" . "toggle")) - (:prefix ("u" . "unwrap")) - (:prefix ("v" . "var")) - (:prefix ("w" . "wrap")) - (:prefix ("3" . "ternary")))) :config - (when (modulep! :editor evil +everywhere) - (add-hook 'js2-refactor-mode-hook #'evil-normalize-keymaps) - (let ((js2-refactor-mode-map (evil-get-auxiliary-keymap js2-refactor-mode-map 'normal t t))) - (js2r-add-keybindings-with-prefix (format "%s r" doom-localleader-key))))) - - -;;;###package skewer-mode -(map! :localleader - (:after js2-mode - :map js2-mode-map - "S" #'+javascript/skewer-this-buffer - :prefix ("s" . "skewer")) - :prefix "s" - (:after skewer-mode - :map skewer-mode-map - "E" #'skewer-eval-last-expression - "e" #'skewer-eval-defun - "f" #'skewer-load-buffer) - - (:after skewer-css - :map skewer-css-mode-map - "e" #'skewer-css-eval-current-declaration - "r" #'skewer-css-eval-current-rule - "b" #'skewer-css-eval-buffer - "c" #'skewer-css-clear-all) - - (:after skewer-html - :map skewer-html-mode-map - "e" #'skewer-html-eval-tag)) - - -(use-package! npm-mode - :hook ((js-mode typescript-mode) . npm-mode) - :config - (map! :localleader - (:map npm-mode-keymap - "n" npm-mode-command-keymap) - (:after js2-mode - :map js2-mode-map - :prefix ("n" . "npm")))) + (+javascript-common-config 'nodejs-repl-mode)) ;; diff --git a/modules/lang/javascript/doctor.el b/modules/lang/javascript/doctor.el index be3415c2d..3c774e795 100644 --- a/modules/lang/javascript/doctor.el +++ b/modules/lang/javascript/doctor.el @@ -8,3 +8,7 @@ (assert! (or (not (modulep! +tree-sitter)) (modulep! :tools tree-sitter)) "This module requires (:tools tree-sitter)") + +(unless (modulep! +tree-sitter) + (warn! "Typescript support is degraded without +tree-sitter (and Emacs 29+)") + (warn! "No JSX/TSX support without +tree-sitter (and Emacs 29+)")) diff --git a/modules/lang/javascript/packages.el b/modules/lang/javascript/packages.el index 02c79e850..5a61a437a 100644 --- a/modules/lang/javascript/packages.el +++ b/modules/lang/javascript/packages.el @@ -2,18 +2,10 @@ ;;; lang/javascript/packages.el ;; Major modes -(package! rjsx-mode :pin "b697fe4d92cc84fa99a7bcb476f815935ea0d919") -(package! typescript-mode :pin "481df3ad2cdf569d8e6697679669ff6206fbd2f9") +(unless (or (modulep! +tree-sitter) + (fboundp 'treesit-available-p) + (treesit-available-p)) + (package! typescript-mode :pin "481df3ad2cdf569d8e6697679669ff6206fbd2f9")) -;; Tools -(package! js2-refactor :pin "e1177c728ae52a5e67157fb18ee1409d8e95386a") -(package! npm-mode :pin "3ee7c0bad5b7a041d4739ef3aaa06a3dc764e5eb") - -;; Eval +;; Extensions (package! nodejs-repl :pin "130d49b073a50b7aad472ae8cd05848a9840e480") -(package! skewer-mode :pin "e5bed351939c92a1f788f78398583c2f83f1bb3c") - -;; Programming environment -(package! tide :pin "6a35fe355f1442da34b976bf2decf008d6e4f991") -(when (modulep! :tools lookup) - (package! xref-js2 :pin "e215af9eedac69b40942fff9d5514704f9f4d43e")) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index 5a00fa24f..bec186284 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -74,7 +74,6 @@ (bibtex "https://github.com/latex-lsp/tree-sitter-bibtex" nil nil nil nil) (blueprint "https://github.com/huanie/tree-sitter-blueprint" nil nil nil nil) (commonlisp "https://github.com/tree-sitter-grammars/tree-sitter-commonlisp" nil nil nil nil) - (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src" nil nil) (latex "https://github.com/latex-lsp/tree-sitter-latex" nil nil nil nil) (make "https://github.com/tree-sitter-grammars/tree-sitter-make" nil nil nil nil) (nu "https://github.com/nushell/tree-sitter-nu" nil nil nil nil) @@ -85,8 +84,6 @@ (sql "https://github.com/DerekStride/tree-sitter-sql" "gh-pages" nil nil nil) (surface "https://github.com/connorlay/tree-sitter-surface" nil nil nil nil) (toml "https://github.com/tree-sitter/tree-sitter-toml" nil nil nil nil) - (tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src" nil nil) - (typescript "https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src" nil nil) (typst "https://github.com/uben0/tree-sitter-typst" "master" "src" nil nil) (verilog "https://github.com/gmlarumbe/tree-sitter-verilog" nil nil nil nil) (vhdl "https://github.com/alemuller/tree-sitter-vhdl" nil nil nil nil) From cd5dd5279e8d3ff207cde922cf8775a52eebd29e Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 29 Aug 2025 14:25:35 +0200 Subject: [PATCH 56/71] fix(tree-sitter): major mode remapping on first-load Also refactors +tree-sitter--major-mode-remaps-alist to be lighter. --- .../tools/tree-sitter/autoload/tree-sitter.el | 42 +++------------- modules/tools/tree-sitter/config.el | 48 +++++++++++++------ 2 files changed, 40 insertions(+), 50 deletions(-) diff --git a/modules/tools/tree-sitter/autoload/tree-sitter.el b/modules/tools/tree-sitter/autoload/tree-sitter.el index 5df7c4bdf..69dfeaabe 100644 --- a/modules/tools/tree-sitter/autoload/tree-sitter.el +++ b/modules/tools/tree-sitter/autoload/tree-sitter.el @@ -23,45 +23,15 @@ pre-Emacs 31." (declare (indent 2)) (cl-check-type mode symbol) (cl-check-type ts-mode symbol) - (setq recipes (ensure-list recipes)) + (setq recipes (mapcar #'ensure-list (ensure-list recipes))) (dolist (m (ensure-list mode)) (add-to-list '+tree-sitter--major-mode-remaps-alist - (cons - m (let (ensured?) - (lambda () - (funcall - ;; Because standard major-mode remapping doesn't offer graceful - ;; failure in some cases, I implement it myself: - (cond ((null recipes) m) - ((not (fboundp ts-mode)) - (message "Couldn't find %S, using %S instead" ts-mode m) - m) - ((and (fboundp 'treesit-available-p) - (treesit-available-p) - (fboundp ts-mode) - (or (eq treesit-enabled-modes t) - (memq ts-mode treesit-enabled-modes)) - ;; Lazily load autoload so - ;; `treesit-language-source-alist' is initialized. - (let ((fn (symbol-function ts-mode))) - (or (not (autoloadp fn)) - (autoload-do-load fn))) - ;; Only prompt once, and log other times. - (cl-every (if ensured? - (doom-rpartial #'treesit-ready-p 'message) - #'treesit-ensure-installed) - (cl-loop for r in recipes - if (listp r) - collect (car r) - else collect (list r)))) - ts-mode) - ((setq ensured? t) - m)))))))) - (with-eval-after-load 'treesit - (dolist (recipe recipes) - (when (cdr (setq recipe (ensure-list recipe))) - (cl-destructuring-bind (name &key url rev source-dir cc cpp commit) recipe + (list m ts-mode (mapcar #'car recipes) nil))) + (when (setq recipes (cl-remove-if-not #'cdr recipes)) + (with-eval-after-load 'treesit + (dolist (recipe recipes) + (cl-destructuring-bind (name &key url rev source-dir cc cpp commit) (ensure-list recipe) (setf (alist-get name treesit-language-source-alist) (append (list url rev source-dir cc cpp) ;; COMPAT: 31.1 introduced a COMMIT recipe argument. On diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index bec186284..3770b15a5 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -35,6 +35,40 @@ python-ts-mode)) (advice-add mode :around #'+tree-sitter-ts-mode-inhibit-side-effects-a)) + ;; HACK: Some *-ts-mode packages modify `major-mode-remap-defaults' + ;; inconsistently. Playing whack-a-mole to undo those changes is more hassle + ;; then simply ignoring them (by overriding `major-mode-remap-defaults' for + ;; any modes remapped with `set-tree-sitter!'). The user shouldn't touch + ;; `major-mode-remap-defaults' anyway; `major-mode-remap-alist' will always + ;; have precedence. + (defadvice! +tree-sitter--maybe-remap-major-mode-a (fn mode) + :around #'major-mode-remap + (let ((major-mode-remap-defaults + ;; Because standard major-mode remapping doesn't offer graceful + ;; failure in some cases, I implement it myself: + (cons (when-let* ((spec (assq mode +tree-sitter--major-mode-remaps-alist)) + (ts-mode (nth 1 spec)) + (langs (nth 2 spec))) + (if (not (fboundp ts-mode)) + (ignore (message "Couldn't find %S, falling back to %S" ts-mode mode)) + (prog1 (and (or (eq treesit-enabled-modes t) + (memq ts-mode treesit-enabled-modes)) + ;; Lazily load autoload so + ;; `treesit-language-source-alist' is + ;; initialized. + (let ((fn (symbol-function ts-mode))) + (or (not (autoloadp fn)) + (autoload-do-load fn ts-mode))) + ;; Only prompt once, and log other times. + (cl-every (if (get ts-mode 'ensured?) + (doom-rpartial #'treesit-ready-p 'message) + #'treesit-ensure-installed) + langs) + `((,mode . ,ts-mode))) + (put ts-mode 'ensured? t)))) + major-mode-remap-defaults))) + (funcall fn mode))) + :config ;; HACK: The implementation of `treesit-enabled-modes's setter and ;; `treesit-major-mode-remap-alist' is intrusively opinionated, so disable @@ -46,20 +80,6 @@ (setq major-mode-remap-alist (delete m major-mode-remap-alist)))) (setq treesit-major-mode-remap-alist nil) - ;; HACK: Some *-ts-mode packages modify `major-mode-remap-defaults' - ;; inconsistently. Playing whack-a-mole to undo those changes is more hassle - ;; then simply ignoring them (by overriding `major-mode-remap-defaults' for - ;; any modes remapped with `set-tree-sitter!'). The user shouldn't touch - ;; `major-mode-remap-defaults' anyway; `major-mode-remap-alist' will always - ;; have precedence. - (defadvice! +tree-sitter--ignore-default-major-mode-remaps-a (fn mode) - :around #'major-mode-remap - (let ((major-mode-remap-defaults - (if-let* ((m (assq mode +tree-sitter--major-mode-remaps-alist))) - +tree-sitter--major-mode-remaps-alist - major-mode-remap-defaults))) - (funcall fn mode))) - ;; HACK: Keep $EMACSDIR clean by installing grammars to the active profile. (add-to-list 'treesit-extra-load-path (concat doom-profile-data-dir "tree-sitter")) (defadvice! +tree-sitter--install-grammar-to-local-dir-a (fn &rest args) From 702d97666500e5b094b47861f203488fe3d43f4e Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 29 Aug 2025 14:37:10 +0200 Subject: [PATCH 57/71] docs(tree-sitter): document module hacks --- modules/tools/tree-sitter/README.org | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/modules/tools/tree-sitter/README.org b/modules/tools/tree-sitter/README.org index 3303ad1b2..46a518353 100644 --- a/modules/tools/tree-sitter/README.org +++ b/modules/tools/tree-sitter/README.org @@ -27,14 +27,26 @@ It includes: /This module has no flags./ ** Packages -- if [[doom-module:+compat]] - - [[doom-package:evil-textobj-tree-sitter]] if [[doom-module::editor evil +everywhere]] - - [[doom-package:tree-sitter]] - - [[doom-package:tree-sitter-indent]] - - [[doom-package:tree-sitter-langs]] +/This module doesn't install any packages./ ** Hacks -/No hacks documented for this module./ +- ~treesit-auto-install-grammar~, ~treesit-ensure-installed~, ~treesit-enabled-modes~, + and ~treesit-major-mode-remap-alist~ have been backported from Emacs 30/31. +- ~treesit~ has been advised to install grammars to the current Doom profile's + data folder, rather than in ~$EMACSDIR/treesit/~ (to keep ~$EMACSDIR~ clean and so + each profile can have their own grammars; in case of version conflicts). +- Because *-ts-modes are inconsistent in how they handle missing language + grammars (some error out, some respect ~treesit-auto-install-grammar~ as of 30+, + some fall back to the non-ts-mode), ~major-mode-remap~ is advised to provide + consistent and graceful failure these cases (falling back to the non-ts-mode + in all cases, with a logged warning). +- Some *-ts-modes modify ~auto-mode-alist~ and/or ~interpreter-mode-alist~ with + hardcoded entries whenever they are activated, potentially overriding user (or + Doom module) configuration. They have been advised to suppress this behavior. +- Autoloaded ~*-ts-mode~/~*-ts-mode-maybe~ entries in ~auto-mode-alist~ and + ~interpreter-mode-alist~ are proactively removed so we can consistently rely on + ~major-mode-remap-{alist,defaults}~ instead (which is more predictable and + harder for users/modules to carelessly override) ** TODO Changelog # This section will be machine generated. Don't edit it by hand. From 31f5b60f5ea0a621e57be9e6769100673bf0b9a3 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 29 Aug 2025 17:56:55 +0200 Subject: [PATCH 58/71] fix(php): dynamic mode map interpolation error Amend: 9073b248783e Close: #8448 Co-authored-by: ribaricplusplus --- modules/lang/php/config.el | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/lang/php/config.el b/modules/lang/php/config.el index e96d23683..40902debc 100644 --- a/modules/lang/php/config.el +++ b/modules/lang/php/config.el @@ -42,9 +42,8 @@ :return "return" :yield "use") - (let ((mode-hook (intern (format "%s-hook" mode))) - (mode-vars-hook (intern (format "%s-local-vars-hook" mode))) - (mode-map (symbol-value (intern (format "%s-map" mode))))) + (let ((mode-vars-hook (intern (format "%s-local-vars-hook" mode))) + (mode-map (intern (format "%s-map" mode)))) (sp-with-modes (ensure-list mode) (sp-local-pair "" :post-handlers '(("| " "SPC" "=") ("||\n[i]" "RET") ("[d2]" "p"))) (sp-local-pair "" :post-handlers '(("| " "SPC") ("||\n[i]" "RET")))) From 3044812ac11cc133783d92c36b6662e0c7078b0c Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 29 Aug 2025 18:23:18 +0200 Subject: [PATCH 59/71] fix(clojure): remove vestiges of tree-sitter Amend: 2adbdf136061 --- modules/lang/clojure/config.el | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/modules/lang/clojure/config.el b/modules/lang/clojure/config.el index dd3206aec..e8f8892ec 100644 --- a/modules/lang/clojure/config.el +++ b/modules/lang/clojure/config.el @@ -32,18 +32,7 @@ clojurec-mode clojurescript-mode clojurex-mode)) - (add-to-list 'lsp-language-id-configuration (cons m "clojure"))))) - - (when (modulep! +tree-sitter) - (add-hook! '(clojure-mode-local-vars-hook - clojurec-mode-local-vars-hook - clojurescript-mode-local-vars-hook) - :append - #'tree-sitter!) - ;; TODO: PR this upstream - (after! tree-sitter-langs - (add-to-list 'tree-sitter-major-mode-language-alist '(clojurec-mode . clojure)) - (add-to-list 'tree-sitter-major-mode-language-alist '(clojurescript-mode . clojure))))) + (add-to-list 'lsp-language-id-configuration (cons m "clojure")))))) (use-package! clojure-ts-mode From 7dcedc16b5c2c561f89b6a6e2fd8847bc7f6b64c Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 30 Aug 2025 03:01:44 +0200 Subject: [PATCH 60/71] refactor(tree-sitter): major mode remapping This approach simplifies the hacks and uses fewer moving parts to be less error prone (or prone to potentially overwriting user/module configuration). --- .../tools/tree-sitter/autoload/tree-sitter.el | 8 +-- modules/tools/tree-sitter/config.el | 68 ++++++++----------- 2 files changed, 29 insertions(+), 47 deletions(-) diff --git a/modules/tools/tree-sitter/autoload/tree-sitter.el b/modules/tools/tree-sitter/autoload/tree-sitter.el index 69dfeaabe..f9953bbbd 100644 --- a/modules/tools/tree-sitter/autoload/tree-sitter.el +++ b/modules/tools/tree-sitter/autoload/tree-sitter.el @@ -1,8 +1,5 @@ ;;; tools/tree-sitter/autoload/tree-sitter.el -*- lexical-binding: t; -*- -;;;###autoload -(defvar +tree-sitter--major-mode-remaps-alist nil) - ;;;###autodef (fset 'tree-sitter! #'ignore) (defun tree-sitter! () (message "Old tree-sitter.el support is deprecated!")) @@ -25,9 +22,8 @@ pre-Emacs 31." (cl-check-type ts-mode symbol) (setq recipes (mapcar #'ensure-list (ensure-list recipes))) (dolist (m (ensure-list mode)) - (add-to-list - '+tree-sitter--major-mode-remaps-alist - (list m ts-mode (mapcar #'car recipes) nil))) + (setf (alist-get m major-mode-remap-defaults) ts-mode) + (put ts-mode '+tree-sitter (cons m (mapcar #'car recipes)))) (when (setq recipes (cl-remove-if-not #'cdr recipes)) (with-eval-after-load 'treesit (dolist (recipe recipes) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index 3770b15a5..486f9db06 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -35,51 +35,37 @@ python-ts-mode)) (advice-add mode :around #'+tree-sitter-ts-mode-inhibit-side-effects-a)) - ;; HACK: Some *-ts-mode packages modify `major-mode-remap-defaults' - ;; inconsistently. Playing whack-a-mole to undo those changes is more hassle - ;; then simply ignoring them (by overriding `major-mode-remap-defaults' for - ;; any modes remapped with `set-tree-sitter!'). The user shouldn't touch - ;; `major-mode-remap-defaults' anyway; `major-mode-remap-alist' will always - ;; have precedence. + ;; HACK: Intercept all ts-mode major mode remappings so grammars can be + ;; dynamically checked and `treesit-auto-install-grammar' can be + ;; consistently respected (which isn't currently the case with the majority + ;; of ts-modes, even the built-in ones). (defadvice! +tree-sitter--maybe-remap-major-mode-a (fn mode) :around #'major-mode-remap - (let ((major-mode-remap-defaults - ;; Because standard major-mode remapping doesn't offer graceful - ;; failure in some cases, I implement it myself: - (cons (when-let* ((spec (assq mode +tree-sitter--major-mode-remaps-alist)) - (ts-mode (nth 1 spec)) - (langs (nth 2 spec))) - (if (not (fboundp ts-mode)) - (ignore (message "Couldn't find %S, falling back to %S" ts-mode mode)) - (prog1 (and (or (eq treesit-enabled-modes t) - (memq ts-mode treesit-enabled-modes)) - ;; Lazily load autoload so - ;; `treesit-language-source-alist' is - ;; initialized. - (let ((fn (symbol-function ts-mode))) - (or (not (autoloadp fn)) - (autoload-do-load fn ts-mode))) - ;; Only prompt once, and log other times. - (cl-every (if (get ts-mode 'ensured?) - (doom-rpartial #'treesit-ready-p 'message) - #'treesit-ensure-installed) - langs) - `((,mode . ,ts-mode))) - (put ts-mode 'ensured? t)))) - major-mode-remap-defaults))) - (funcall fn mode))) + (let ((mode (funcall fn mode))) + (if-let* ((ts (get mode '+tree-sitter)) + (fallback-mode (car ts))) + (cond ((not (fboundp mode)) + (message "Couldn't find %S, falling back to %S" mode fallback-mode) + fallback-mode) + ((and (or (eq treesit-enabled-modes t) + (memq fallback-mode treesit-enabled-modes)) + ;; Lazily load autoloaded `treesit-language-source-alist' + ;; entries. + (let ((fn (symbol-function mode))) + (or (not (autoloadp fn)) + (autoload-do-load fn mode))) + ;; Only prompt once, and log other times. + (or (null (cdr ts)) + (cl-every (if (get mode '+tree-sitter-ensured) + (doom-rpartial #'treesit-ready-p 'message) + #'treesit-ensure-installed) + (cdr ts)))) + (put mode '+tree-sitter-ensured t) + mode) + (fallback-mode)) + mode))) :config - ;; HACK: The implementation of `treesit-enabled-modes's setter and - ;; `treesit-major-mode-remap-alist' is intrusively opinionated, so disable - ;; it ato avoid untimely (and overriding) modifications of - ;; `major-mode-remap-alist' at runtime. What's more, this was only - ;; introduced in 31, so ignoring them is more consistent for pre-31 users. - (when major-mode-remap-alist - (dolist (m treesit-major-mode-remap-alist) - (setq major-mode-remap-alist (delete m major-mode-remap-alist)))) - (setq treesit-major-mode-remap-alist nil) - ;; HACK: Keep $EMACSDIR clean by installing grammars to the active profile. (add-to-list 'treesit-extra-load-path (concat doom-profile-data-dir "tree-sitter")) (defadvice! +tree-sitter--install-grammar-to-local-dir-a (fn &rest args) From 2870697e1ae3717a970b40eb1da9aab9012b3f6f Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 30 Aug 2025 09:44:14 +0200 Subject: [PATCH 61/71] fix(go,nix,zig): dynamic keymap interpolation errors Amend: 7c6e1950e8d4 Amend: 5b37bfee23fd Amend: 9acc5f48b6e2 --- modules/lang/go/config.el | 2 +- modules/lang/nix/config.el | 2 +- modules/lang/zig/config.el | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/lang/go/config.el b/modules/lang/go/config.el index d526f2fc8..0d5c468f1 100644 --- a/modules/lang/go/config.el +++ b/modules/lang/go/config.el @@ -12,7 +12,7 @@ (when (modulep! +lsp) (add-hook (intern (format "%s-local-vars-hook" mode)) #'lsp! 'append)) - (map! :map ,(symbol-value (intern (format "%s-map" mode))) + (map! :map ,(intern (format "%s-map" mode)) :localleader "a" #'go-tag-add "d" #'go-tag-remove diff --git a/modules/lang/nix/config.el b/modules/lang/nix/config.el index ced4ef98a..035e5f418 100644 --- a/modules/lang/nix/config.el +++ b/modules/lang/nix/config.el @@ -25,7 +25,7 @@ (add-hook (intern (format "%s-local-vars-hook" mode)) #'lsp! 'append)) (map! :localleader - :map ,(symbol-value (intern (format "%s-map" mode))) + :map ,(intern (format "%s-map" mode)) "f" #'nix-update-fetch "p" #'nix-format-buffer "r" #'nix-repl-show diff --git a/modules/lang/zig/config.el b/modules/lang/zig/config.el index 7fe3d90e7..c68f864cd 100644 --- a/modules/lang/zig/config.el +++ b/modules/lang/zig/config.el @@ -12,7 +12,7 @@ (when (modulep! +lsp) (add-hook (intern (format "%s-local-vars-hook" mode)) #'lsp! 'append)) (map! :localleader - :map ,(symbol-value (intern (format "%s-map" mode))) + :map ,(intern (format "%s-map" mode)) "b" #'zig-compile "f" #'zig-format-buffer "r" #'zig-run From ab4dace692cd31b8528dcd9c7ad0338c2bc91a48 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 30 Aug 2025 09:58:12 +0200 Subject: [PATCH 62/71] refactor(:lang): remove redudant mode-alist lines Amend: 3b587415224e --- modules/lang/json/config.el | 3 --- modules/lang/lua/config.el | 6 +----- modules/lang/markdown/config.el | 4 +--- modules/lang/scala/config.el | 3 --- 4 files changed, 2 insertions(+), 14 deletions(-) diff --git a/modules/lang/json/config.el b/modules/lang/json/config.el index a2d385c56..88d6889b4 100644 --- a/modules/lang/json/config.el +++ b/modules/lang/json/config.el @@ -27,9 +27,6 @@ :init (set-tree-sitter! 'json-mode 'json-ts-mode 'json) :config - ;; HACK: Rely on `major-mode-remap-defaults'. - (cl-callf2 assq-delete-all 'json-ts-mode auto-mode-alist) - (when (modulep! +lsp) (add-hook 'json-ts-mode-local-vars-hook #'lsp! 'append))) diff --git a/modules/lang/lua/config.el b/modules/lang/lua/config.el index e57d8a150..bd5e4d3fc 100644 --- a/modules/lang/lua/config.el +++ b/modules/lang/lua/config.el @@ -40,11 +40,7 @@ (when (modulep! +lsp) (add-hook 'lua-ts-mode-local-vars-hook #'lsp! 'append) (when (modulep! :tools lsp +eglot) - (set-eglot-client! 'lua-ts-mode (+lua-generate-lsp-server-command)))) - - ;; HACK: Get rid of redundancies, rely on `major-mode-remap-defaults' - (cl-callf2 delete '("\\.lua\\'" . lua-ts-mode) auto-mode-alist) - (cl-callf2 delete '("\\ Date: Sat, 30 Aug 2025 10:05:01 +0200 Subject: [PATCH 63/71] refactor(lua): DRY tree-sitter config --- modules/lang/lua/config.el | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/modules/lang/lua/config.el b/modules/lang/lua/config.el index bd5e4d3fc..f082eceb3 100644 --- a/modules/lang/lua/config.el +++ b/modules/lang/lua/config.el @@ -7,22 +7,23 @@ ;; ;;; Major modes +(defun +lua-common-config (mode) + (set-lookup-handlers! mode :documentation 'lua-search-documentation) + (set-electric! mode :words '("else" "end")) + (set-repl-handler! mode #'+lua/open-repl) + (set-company-backend! mode '(company-lua company-yasnippet)) + (when (modulep! +lsp) + (add-hook (intern (format "%s-local-vars-hook" mode)) #'lsp! 'append) + (when (modulep! :tools lsp +eglot) + (set-eglot-client! mode (+lua-generate-lsp-server-command))))) + + (use-package! lua-mode :interpreter "\\ Date: Sat, 30 Aug 2025 10:17:13 +0200 Subject: [PATCH 64/71] fix(haskell): haskell-ts-mode: repl & eglot integration Amend: 47fe11cd767e --- modules/lang/haskell/config.el | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/lang/haskell/config.el b/modules/lang/haskell/config.el index 0bbc03eeb..3707ac6a9 100644 --- a/modules/lang/haskell/config.el +++ b/modules/lang/haskell/config.el @@ -44,14 +44,16 @@ "H" #'haskell-hide-toggle-all)) -;; TODO: Mirror other haskell-mode config to ts-mode (use-package! haskell-ts-mode :when (modulep! +tree-sitter) :when (fboundp 'haskell-ts-mode) :defer t :init (set-tree-sitter! 'haskell-mode 'haskell-ts-mode - '((haskell :url "https://github.com/tree-sitter/tree-sitter-haskell")))) + '((haskell :url "https://github.com/tree-sitter/tree-sitter-haskell"))) + :config + (set-repl-handler! 'haskell-ts-mode #'run-haskell :persist t) + (set-eglot-client! 'haskell-ts-mode '("haskell-language-server-wrapper" "--lsp"))) (use-package! lsp-haskell From d77d39ab46a4343479db16751a949a9cc36a1f63 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 30 Aug 2025 10:20:37 +0200 Subject: [PATCH 65/71] refactor(scala): remove redundant config Amend: c5dd2847ffaf --- modules/lang/scala/config.el | 8 +------- modules/lang/scala/doctor.el | 4 ---- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/modules/lang/scala/config.el b/modules/lang/scala/config.el index 099cca00e..6197fe243 100644 --- a/modules/lang/scala/config.el +++ b/modules/lang/scala/config.el @@ -65,12 +65,6 @@ :config (when (modulep! +lsp) - (setq-hook! 'scala-ts-mode-hook lsp-enable-indentation nil) - (add-hook 'scala-ts-mode-local-vars-hook #'lsp! 'append)) + (setq-hook! 'scala-ts-mode-hook lsp-enable-indentation nil)) (+scala-common-config 'scala-ts-mode)) - - -(use-package! sbt-mode - :after scala-mode - :config (set-repl-handler! '(scala-mode scala-ts-mode) #'+scala/open-repl :persist t)) diff --git a/modules/lang/scala/doctor.el b/modules/lang/scala/doctor.el index 4ba6b07d2..fc72e2f18 100644 --- a/modules/lang/scala/doctor.el +++ b/modules/lang/scala/doctor.el @@ -8,10 +8,6 @@ (modulep! :tools tree-sitter)) "This module requires (:tools tree-sitter)") -(assert! (or (not (modulep! +tree-sitter)) - (version< emacs-version "29.1")) - "Emacs 29.1+ is required for tree-sitter support") - (if (and (modulep! +lsp) (not (executable-find "metals"))) (warn! "metals isn't installed")) From d9fd5cb8f30cb2f7f1f9238b993361fa8717ee5f Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 31 Aug 2025 14:34:45 +0200 Subject: [PATCH 66/71] fix(tree-sitter): treesit-enabled-modes: sort arity in <30 `sort`s signature changed in Emacs 30 from: (sort SEQ PREDICATE) To (sort SEQ &key KEY LESSP REVERSE IN-PLACE) Amend: 6009c2b8382b --- modules/tools/tree-sitter/autoload/compat-30.el | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/tools/tree-sitter/autoload/compat-30.el b/modules/tools/tree-sitter/autoload/compat-30.el index d37f936b6..2d610aaed 100644 --- a/modules/tools/tree-sitter/autoload/compat-30.el +++ b/modules/tools/tree-sitter/autoload/compat-30.el @@ -55,8 +55,11 @@ or t to enable all ts-modes." (const :tag "Enable all available ts-modes" t) (set :tag "List of enabled ts-modes" ,@(when (treesit-available-p) - (sort (mapcar (lambda (m) `(function-item ,m)) - (seq-uniq (mapcar #'cdr treesit-major-mode-remap-alist))))))) + (let ((items (mapcar (lambda (m) `(function-item ,m)) + (seq-uniq (mapcar #'cdr treesit-major-mode-remap-alist))))) + (if (= (car (func-arity 'sort)) 1) + (sort items) + (sort items #'value<)))))) :initialize #'custom-initialize-default :set (lambda (sym val) (set-default sym val) From d545fccf47b64faf8b19f6fdab3fbb7c23a377cf Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 31 Aug 2025 12:47:50 +0200 Subject: [PATCH 67/71] fix(:lang): missing grammar recipes I removed the grammar recipes in 3b58741 to avoid redundancy with the upstream recipes, but didn't realize that those upstream recipes weren't added until Emacs 31, so users on 30 and older would get errors when trying to install any missing grammars. This also establishes a hard dependency between :lang (php +tree-sitter) and :lang ({javascript,web} +tree-sitter). Amend: 3b587415224e --- modules/lang/cc/config.el | 10 ++++++---- modules/lang/csharp/config.el | 6 +++++- modules/lang/elixir/config.el | 9 ++++++--- modules/lang/go/config.el | 8 +++++++- modules/lang/janet/config.el | 4 ++-- modules/lang/java/config.el | 9 ++++++--- modules/lang/javascript/config.el | 19 +++++++++++++------ modules/lang/json/config.el | 7 ++++--- modules/lang/julia/config.el | 3 ++- modules/lang/lua/config.el | 5 +++-- modules/lang/markdown/config.el | 3 +-- modules/lang/php/config.el | 11 +++++++++-- modules/lang/php/doctor.el | 16 +++++++++------- modules/lang/python/config.el | 4 +++- modules/lang/ruby/config.el | 7 ++++--- modules/lang/rust/config.el | 10 +++++++--- modules/lang/web/+css.el | 8 +++++--- modules/lang/web/+html.el | 11 ++++++----- modules/lang/yaml/config.el | 8 +++++--- modules/tools/docker/config.el | 5 +++-- modules/tools/tree-sitter/config.el | 2 +- 21 files changed, 107 insertions(+), 58 deletions(-) diff --git a/modules/lang/cc/config.el b/modules/lang/cc/config.el index 0af20dedf..2400ba17d 100644 --- a/modules/lang/cc/config.el +++ b/modules/lang/cc/config.el @@ -30,9 +30,10 @@ This is ignored by ccls.") :hook (c-mode-common . rainbow-delimiters-mode) :init (when (modulep! +tree-sitter) - (set-tree-sitter! 'c-mode 'c-ts-mode 'c) - (set-tree-sitter! 'c++-mode 'c++-ts-mode 'cpp)) - + (set-tree-sitter! 'c-mode 'c-ts-mode + '((c :url "https://github.com/tree-sitter/tree-sitter-c"))) + (set-tree-sitter! 'c++-mode 'c++-ts-mode + '((cpp :url "https://github.com/tree-sitter/tree-sitter-cpp")))) :config (set-docsets! '(c-mode c-ts-mode) "C") (set-docsets! '(c++-mode c++-ts-mode) "C++" "Boost") @@ -114,7 +115,8 @@ This is ignored by ccls.") :init (when (and (modulep! +tree-sitter) (boundp 'cmake-ts-mode)) ; 29+ only - (set-tree-sitter! 'cmake-mode 'cmake-ts-mode 'cmake)) + (set-tree-sitter! 'cmake-mode 'cmake-ts-mode + '((cmake :url "https://github.com/uyha/tree-sitter-cmake")))) :config (set-docsets! '(cmake-mode cmake-ts-mode) "CMake") (set-popup-rule! "^\\*CMake Help\\*" :size 0.4 :ttl t) diff --git a/modules/lang/csharp/config.el b/modules/lang/csharp/config.el index 70a4a9884..1b0dccd3f 100644 --- a/modules/lang/csharp/config.el +++ b/modules/lang/csharp/config.el @@ -2,9 +2,13 @@ (use-package! csharp-mode :hook (csharp-mode . rainbow-delimiters-mode) + :defer t :init (when (modulep! +tree-sitter) - (set-tree-sitter! 'csharp-mode 'csharp-ts-mode 'c-sharp)) + (set-tree-sitter! 'csharp-mode 'csharp-ts-mode + '((c-sharp :url "https://github.com/tree-sitter/tree-sitter-c-sharp" + :rev "v0.23.1" + :commit "362a8a41b265056592a0c3771664a21d23a71392")))) :config (set-formatter! 'csharpier '("csharpier" "format" "--write-stdout") :modes '(csharp-mode csharp-ts-mode)) diff --git a/modules/lang/elixir/config.el b/modules/lang/elixir/config.el index 81bd247dd..18aff5df5 100644 --- a/modules/lang/elixir/config.el +++ b/modules/lang/elixir/config.el @@ -54,12 +54,15 @@ highlight-numbers-modelist))) -(use-package! elixir-ts-mode +(use-package! elixir-ts-mode ; 30.1+ only :when (modulep! +tree-sitter) - :when (fboundp 'elixir-ts-mode) ; 30.1+ only :defer t :init - (set-tree-sitter! 'elixir-mode 'elixir-ts-mode '(elixir heex)) + (set-tree-sitter! 'elixir-mode 'elixir-ts-mode + '((elixir :url "https://github.com/elixir-lang/tree-sitter-elixir" + :commit "02a6f7fd4be28dd94ee4dd2ca19cb777053ea74e") + (heex :url "https://github.com/phoenixframework/tree-sitter-heex" + :commit "f6b83f305a755cd49cf5f6a66b2b789be93dc7b9"))) :config (+elixir-common-config 'elixir-ts-mode)) diff --git a/modules/lang/go/config.el b/modules/lang/go/config.el index 0d5c468f1..387c1ee97 100644 --- a/modules/lang/go/config.el +++ b/modules/lang/go/config.el @@ -53,7 +53,13 @@ :when (fboundp 'go-ts-mode) ; 31.1+ only :defer t :init - (set-tree-sitter! 'go-mode 'go-ts-mode '(go gomod gowork)) + (set-tree-sitter! 'go-mode 'go-ts-mode + '((go :url "https://github.com/tree-sitter/tree-sitter-go" + :commit "12fe553fdaaa7449f764bc876fd777704d4fb752") + (gomod :url "https://github.com/camdencheek/tree-sitter-go-mod" + :commit "3b01edce2b9ea6766ca19328d1850e456fde3103") + (gowork :url "https://github.com/omertuc/tree-sitter-go-work" + :commit "949a8a470559543857a62102c84700d291fc984c"))) :config (+go-common-config 'go-ts-mode)) diff --git a/modules/lang/janet/config.el b/modules/lang/janet/config.el index fa49da13a..f1564a68e 100644 --- a/modules/lang/janet/config.el +++ b/modules/lang/janet/config.el @@ -29,5 +29,5 @@ :defer t :init (set-tree-sitter! 'janet-mode 'janet-ts-mode - `(janet-simple :url "https://github.com/sogaiu/tree-sitter-janet-simple" - :cc ,(if (featurep :system 'windows) "gcc.exe")))) + `((janet-simple :url "https://github.com/sogaiu/tree-sitter-janet-simple" + :cc ,(if (featurep :system 'windows) "gcc.exe"))))) diff --git a/modules/lang/java/config.el b/modules/lang/java/config.el index 1dab9a892..e6a983a89 100644 --- a/modules/lang/java/config.el +++ b/modules/lang/java/config.el @@ -34,12 +34,15 @@ If the depth is 2, the first two directories are removed: net.lissner.game.") ;; ;;; Common packages -(use-package! java-ts-mode +(use-package! java-ts-mode ; 29.1+ only :when (modulep! +tree-sitter) - :when (fboundp 'java-ts-mode) ; 29.1+ only :defer t :init - (set-tree-sitter! 'java-mode 'java-ts-mode '(java doxygen))) + (set-tree-sitter! 'java-mode 'java-ts-mode + '((java :url "https://github.com/tree-sitter/tree-sitter-java" + :commit "94703d5a6bed02b98e438d7cad1136c01a60ba2c") + (doxygen :url "https://github.com/tree-sitter-grammars/tree-sitter-doxygen" + :commit "1e28054cb5be80d5febac082706225e42eff14e6")))) (use-package! android-mode diff --git a/modules/lang/javascript/config.el b/modules/lang/javascript/config.el index 4496d98e0..835bb0c10 100644 --- a/modules/lang/javascript/config.el +++ b/modules/lang/javascript/config.el @@ -52,12 +52,17 @@ (+javascript-common-config 'js-mode)) -(use-package! js-ts-mode +(use-package! js-ts-mode ; 29.1+ only :when (modulep! +tree-sitter) - :when (fboundp 'js-ts-mode) ; 29.1+ only :defer t :init - (set-tree-sitter! 'js-mode 'js-ts-mode 'javascript) + (set-tree-sitter! 'js-mode 'js-ts-mode + '((javascript :url "https://github.com/tree-sitter/tree-sitter-javascript" + :rev "v0.23.0" + :commit "108b2d4d17a04356a340aea809e4dd5b801eb40d") + (jsdoc :url "https://github.com/tree-sitter/tree-sitter-jsdoc" + :rev "v0.23.0" + :commit "b253abf68a73217b7a52c0ec254f4b6a7bb86665"))) (+javascript-common-config 'js-ts-mode)) @@ -68,12 +73,14 @@ (+javascript-common-config 'typescript-mode)) -(use-package! typescript-ts-mode +(use-package! typescript-ts-mode ; 29.1+ only :when (modulep! +tree-sitter) - :when (fboundp 'typescript-ts-mode) ; 29.1+ only :mode "\\.ts\\'" :init - (set-tree-sitter! 'typescript-mode 'typescript-ts-mode 'typescript) + (set-tree-sitter! 'typescript-mode 'typescript-ts-mode + '((typescript :url "https://github.com/tree-sitter/tree-sitter-typescript" + :commit "8e13e1db35b941fc57f2bd2dd4628180448c17d5" + :source-dir "typescript/src"))) :config (+javascript-common-config 'typescript-ts-mode)) diff --git a/modules/lang/json/config.el b/modules/lang/json/config.el index 88d6889b4..c4b56b82d 100644 --- a/modules/lang/json/config.el +++ b/modules/lang/json/config.el @@ -20,12 +20,13 @@ "f" #'json-mode-beautify)) -(use-package! json-ts-mode +(use-package! json-ts-mode ; 29.1+ only :when (modulep! +tree-sitter) - :when (fboundp 'json-ts-mode) ; 29.1+ only :defer t :init - (set-tree-sitter! 'json-mode 'json-ts-mode 'json) + (set-tree-sitter! 'json-mode 'json-ts-mode + '((json :url "https://github.com/tree-sitter/tree-sitter-json" + :commit "4d770d31f732d50d3ec373865822fbe659e47c75"))) :config (when (modulep! +lsp) (add-hook 'json-ts-mode-local-vars-hook #'lsp! 'append))) diff --git a/modules/lang/julia/config.el b/modules/lang/julia/config.el index 43ae499b3..99850f6f1 100644 --- a/modules/lang/julia/config.el +++ b/modules/lang/julia/config.el @@ -48,7 +48,8 @@ :when (modulep! +tree-sitter) :defer t :init - (set-tree-sitter! 'julia-mode 'julia-ts-mode 'julia) + (set-tree-sitter! 'julia-mode 'julia-ts-mode + '((julia :url "https://github.com/tree-sitter/tree-sitter-julia"))) :config (when (modulep! +lsp) (add-hook 'julia-ts-mode-local-vars-hook #'lsp! 'append))) diff --git a/modules/lang/lua/config.el b/modules/lang/lua/config.el index f082eceb3..f176fddbc 100644 --- a/modules/lang/lua/config.el +++ b/modules/lang/lua/config.el @@ -28,10 +28,11 @@ (use-package! lua-ts-mode :when (modulep! +tree-sitter) - :when (fboundp 'lua-ts-mode) ; 30.1+ only :defer t :init - (set-tree-sitter! 'lua-mode 'lua-ts-mode 'lua) + (set-tree-sitter! 'lua-mode 'lua-ts-mode + '((lua :url "https://github.com/tree-sitter-grammars/tree-sitter-lua" + :commit "db16e76558122e834ee214c8dc755b4a3edc82a9"))) :config (+lua-common-config 'lua-ts-mode)) diff --git a/modules/lang/markdown/config.el b/modules/lang/markdown/config.el index f1e5dde26..782182c33 100644 --- a/modules/lang/markdown/config.el +++ b/modules/lang/markdown/config.el @@ -126,9 +126,8 @@ capture, the end position, and the output buffer.") :desc "GFM checkbox" "x" #'markdown-toggle-gfm-checkbox))) -(use-package! markdown-ts-mode +(use-package! markdown-ts-mode ; 31+ only :when (modulep! +tree-sitter) - :when (fboundp 'markdown-ts-mode) :defer t :init (set-tree-sitter! 'markdown-mode 'markdown-ts-mode '(markdown markdown-inline))) diff --git a/modules/lang/php/config.el b/modules/lang/php/config.el index 40902debc..e15c0bfbb 100644 --- a/modules/lang/php/config.el +++ b/modules/lang/php/config.el @@ -79,10 +79,17 @@ (use-package! php-ts-mode :when (modulep! +tree-sitter) - :when (fboundp 'php-ts-mode) ; 30.1+ only :defer t :init - (set-tree-sitter! 'php-mode 'php-ts-mode '(php phpdoc)) + (set-tree-sitter! 'php-mode 'php-ts-mode + '((php :url "https://github.com/tree-sitter/tree-sitter-php" + :rev "v0.23.11" + :commit "f7cf7348737d8cff1b13407a0bfedce02ee7b046" + :source-dir "php/src") + (phpdoc :url "https://github.com/claytonrcarter/tree-sitter-phpdoc" + :commit "03bb10330704b0b371b044e937d5cc7cd40b4999") + html css ; requires :lang (web +tree-sitter) + javascript jsdoc)) ; requires :lang (javascript +tree-sitter) :config (+php-common-config 'php-ts-mode)) diff --git a/modules/lang/php/doctor.el b/modules/lang/php/doctor.el index 426927e54..e72e73fcc 100644 --- a/modules/lang/php/doctor.el +++ b/modules/lang/php/doctor.el @@ -5,13 +5,15 @@ (modulep! :tools lsp)) "This module requires (:tools lsp)") -(assert! (or (not (modulep! +tree-sitter)) - (modulep! :tools tree-sitter)) - "This module requires (:tools tree-sitter)") - -(assert! (or (not (modulep! +tree-sitter)) - (fboundp 'php-ts-mode)) - "Can't find `php-ts-mode'; Emacs 30.1+ is required") +(when (modulep! +tree-sitter) + (assert! (modulep! :tools tree-sitter) + "This module requires (:tools tree-sitter)") + (assert! (fboundp 'php-ts-mode) + "Can't find `php-ts-mode'; Emacs 30.1+ is required") + (unless (modulep! :lang javascript +tree-sitter) + (error! "(:lang (javascript +tree-sitter)) required, but not enabled")) + (unless (modulep! :lang web +tree-sitter) + (error! "(:lang (web +tree-sitter)) required, but not enabled"))) (unless (executable-find "php") (warn! "Couldn't find php in your PATH")) diff --git a/modules/lang/python/config.el b/modules/lang/python/config.el index 44360d038..09956a8c8 100644 --- a/modules/lang/python/config.el +++ b/modules/lang/python/config.el @@ -20,7 +20,9 @@ python-indent-guess-indent-offset-verbose nil) (when (modulep! +tree-sitter) - (set-tree-sitter! 'python-mode 'python-ts-mode 'python)) + (set-tree-sitter! 'python-mode 'python-ts-mode + '((python :url "https://github.com/tree-sitter/tree-sitter-python" + :commit "bffb65a8cfe4e46290331dfef0dbf0ef3679de11")))) :config ;; HACK: `python-base-mode' (and `python-ts-mode') don't exist on pre-29 diff --git a/modules/lang/ruby/config.el b/modules/lang/ruby/config.el index 0ef6d3e66..f68d5d95e 100644 --- a/modules/lang/ruby/config.el +++ b/modules/lang/ruby/config.el @@ -36,12 +36,13 @@ "{" #'ruby-toggle-block)) -(use-package! ruby-ts-mode +(use-package! ruby-ts-mode ; 29.1+ only :when (modulep! +tree-sitter) - :when (fboundp 'ruby-ts-mode) ; 29.1+ only :defer t :init - (set-tree-sitter! 'ruby-mode 'ruby-ts-mode 'ruby) + (set-tree-sitter! 'ruby-mode 'ruby-ts-mode + '((ruby :url "https://github.com/tree-sitter/tree-sitter-ruby" + :commit "71bd32fb7607035768799732addba884a37a6210"))) :config (set-electric! 'ruby-ts-mode :words '("else" "end" "elsif")) (set-repl-handler! 'ruby-ts-mode #'inf-ruby) diff --git a/modules/lang/rust/config.el b/modules/lang/rust/config.el index 283e5744e..36f1774b6 100644 --- a/modules/lang/rust/config.el +++ b/modules/lang/rust/config.el @@ -33,12 +33,16 @@ (require 'rustic-mode nil t))) -(use-package! rust-ts-mode +(use-package! rust-ts-mode ; 29.1+ only :when (modulep! +tree-sitter) - :when (fboundp 'rust-ts-mode) ; 29.1+ only :defer t :init - (set-tree-sitter! 'rust-mode 'rust-ts-mode 'rust) + (set-tree-sitter! 'rust-mode 'rust-ts-mode + `((rust :url "https://github.com/tree-sitter/tree-sitter-rust" + :commit ,(if (and (treesit-available-p) + (< (treesit-library-abi-version) 15)) + "1f63b33efee17e833e0ea29266dd3d713e27e321" + "18b0515fca567f5a10aee9978c6d2640e878671a")))) (add-to-list 'major-mode-remap-defaults '(rust-mode . rust-ts-mode) t)) diff --git a/modules/lang/web/+css.el b/modules/lang/web/+css.el index afb4400a7..bb96cd966 100644 --- a/modules/lang/web/+css.el +++ b/modules/lang/web/+css.el @@ -74,9 +74,11 @@ If set to `nil', disable all the above behaviors.") :append #'lsp!)) -(use-package! css-ts-mode +(use-package! css-ts-mode ; 29.1+ only :when (modulep! +tree-sitter) - :when (fboundp 'css-ts-mode) ; 29.1+ only :defer t :init - (set-tree-sitter! 'css-mode 'css-ts-mode 'css)) + (set-tree-sitter! 'css-mode 'css-ts-mode + '((css :url "https://github.com/tree-sitter/tree-sitter-css" + :rev "v0.23.0" + :commit "6a442a3cf461b0ce275339e5afa178693484c927")))) diff --git a/modules/lang/web/+html.el b/modules/lang/web/+html.el index 00417a42d..69f63a42a 100644 --- a/modules/lang/web/+html.el +++ b/modules/lang/web/+html.el @@ -168,17 +168,18 @@ :append #'lsp!)) -(use-package! html-ts-mode +(use-package! html-ts-mode ; 30.1+ only :when (modulep! +tree-sitter) - :when (fboundp 'html-ts-mode) ; 30.1+ only :defer t :init - (set-tree-sitter! 'html-mode 'html-ts-mode 'html)) + (set-tree-sitter! 'html-mode 'html-ts-mode + '((html :url "https://github.com/tree-sitter/tree-sitter-html" + :rev "v0.23.0" + :commit "6a442a3cf461b0ce275339e5afa178693484c927")))) -(use-package! mhtml-ts-mode +(use-package! mhtml-ts-mode ; 31+ only :when (modulep! +tree-sitter) - :when (fboundp 'mhtml-ts-mode) ; 31+ only :defer t :init (set-tree-sitter! 'mhtml-mode 'mhtml-ts-mode 'html)) diff --git a/modules/lang/yaml/config.el b/modules/lang/yaml/config.el index 9f139313a..f6e795a68 100644 --- a/modules/lang/yaml/config.el +++ b/modules/lang/yaml/config.el @@ -8,11 +8,13 @@ (setq-hook! 'yaml-mode-hook tab-width yaml-indent-offset)) -(use-package! yaml-ts-mode +(use-package! yaml-ts-mode ; 29.1+ only :when (modulep! +tree-sitter) - :when (fboundp 'yaml-ts-mode) ; 29.1+ only + :defer t :init - (set-tree-sitter! 'yaml-mode 'yaml-ts-mode 'yaml) + (set-tree-sitter! 'yaml-mode 'yaml-ts-mode + '((yaml :url "https://github.com/tree-sitter-grammars/tree-sitter-yaml" + :commit "b733d3f5f5005890f324333dd57e1f0badec5c87"))) :config (when (modulep! +lsp) (add-hook 'yaml-ts-mode-local-vars-hook #'lsp! 'append))) diff --git a/modules/tools/docker/config.el b/modules/tools/docker/config.el index 6029a6c3c..b6f67b847 100644 --- a/modules/tools/docker/config.el +++ b/modules/tools/docker/config.el @@ -10,7 +10,8 @@ (use-package! dockerfile-ts-mode :when (modulep! +tree-sitter) - :when (fboundp 'dockerfile-ts-mode) ; 29.1+ only :defer t :init - (set-tree-sitter! 'dockerfile-mode 'dockerfile-ts-mode 'dockerfile)) + (set-tree-sitter! 'dockerfile-mode 'dockerfile-ts-mode + '((dockerfile :url "https://github.com/camdencheek/tree-sitter-dockerfile" + :commit "087daa20438a6cc01fa5e6fe6906d77c869d19fe")))) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index 486f9db06..09845c365 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -45,7 +45,7 @@ (if-let* ((ts (get mode '+tree-sitter)) (fallback-mode (car ts))) (cond ((not (fboundp mode)) - (message "Couldn't find %S, falling back to %S" mode fallback-mode) + (message "Couldn't find `%S', falling back to `%S'" mode fallback-mode) fallback-mode) ((and (or (eq treesit-enabled-modes t) (memq fallback-mode treesit-enabled-modes)) From 98f03062b6fb43988bd2b4125e5a1dd72e37590a Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 31 Aug 2025 10:59:43 +0200 Subject: [PATCH 68/71] fix(lib): major-mode-remap backport for Emacs <30 users `major-mode-remap`, `major-mode-remap-alist`, and `major-mode-remap-defaults` were not backported correctly for Emacs 29, 28, and 27 users. Amend: da08aa2d7d9c --- lisp/doom-compat.el | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/lisp/doom-compat.el b/lisp/doom-compat.el index f367a0727..1584811f7 100644 --- a/lisp/doom-compat.el +++ b/lisp/doom-compat.el @@ -109,23 +109,6 @@ and return the value found in PLACE instead." (unless (fboundp 'pos-bol) (defalias 'pos-bol #'line-beginning-position)) (unless (fboundp 'pos-eol) (defalias 'pos-eol #'line-end-position)) -;; Introduced in 29.1 -(unless (boundp 'major-mode-remap-alist) - (defvar major-mode-remap-alist nil) - (defvar-local set-auto-mode--last nil) - (define-advice set-auto-mode-0 (:override (mode &optional keep-mode-if-same) backport-major-mode-remap) - (unless (and keep-mode-if-same - (or (eq (indirect-function mode) - (indirect-function major-mode)) - (and set-auto-mode--last - (eq mode (car set-auto-mode--last)) - (eq major-mode (cdr set-auto-mode--last))))) - (when mode - (funcall (major-mode-remap mode)) - (unless (eq mode major-mode) - (setq set-auto-mode--last (cons mode major-mode))) - mode)))) - ;; Introduced in 29.1 (unless (boundp 'enable-theme-functions) (defcustom enable-theme-functions nil @@ -153,12 +136,26 @@ The functions in the hook are called with one parameter -- the ;;; From Emacs >= 30 ;; Introduced in 30.1 (unless (fboundp 'major-mode-remap) + (defvar major-mode-remap-alist nil) ; introduced in 29.1 (defvar major-mode-remap-defaults nil) (defun major-mode-remap (mode) "Return the function to use to enable MODE." (or (cdr (or (assq mode major-mode-remap-alist) (assq mode major-mode-remap-defaults))) - mode))) + mode)) + (defvar-local set-auto-mode--last nil) + (define-advice set-auto-mode-0 (:override (mode &optional keep-mode-if-same) backport-major-mode-remap) + (unless (and keep-mode-if-same + (or (eq (indirect-function mode) + (indirect-function major-mode)) + (and set-auto-mode--last + (eq mode (car set-auto-mode--last)) + (eq major-mode (cdr set-auto-mode--last))))) + (when mode + (funcall (major-mode-remap mode)) + (unless (eq mode major-mode) + (setq set-auto-mode--last (cons mode major-mode))) + mode)))) ;; Introduced in 30.1 (unless (boundp 'safe-local-variable-directories) From 86b6ba81acb551ba9bce8cb865d75db07ca99af6 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 31 Aug 2025 14:25:41 +0200 Subject: [PATCH 69/71] fix(go): go-{mod,work}-ts-mode --- modules/lang/go/config.el | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/modules/lang/go/config.el b/modules/lang/go/config.el index 387c1ee97..e6dde2ef4 100644 --- a/modules/lang/go/config.el +++ b/modules/lang/go/config.el @@ -48,18 +48,21 @@ (+go-common-config 'go-mode)) -(use-package! go-ts-mode +(use-package! go-ts-mode ; 29.1+ only :when (modulep! +tree-sitter) - :when (fboundp 'go-ts-mode) ; 31.1+ only - :defer t + :mode ("/go\\.mod\\'" . go-mod-ts-mode-maybe) :init (set-tree-sitter! 'go-mode 'go-ts-mode '((go :url "https://github.com/tree-sitter/tree-sitter-go" - :commit "12fe553fdaaa7449f764bc876fd777704d4fb752") - (gomod :url "https://github.com/camdencheek/tree-sitter-go-mod" - :commit "3b01edce2b9ea6766ca19328d1850e456fde3103") - (gowork :url "https://github.com/omertuc/tree-sitter-go-work" - :commit "949a8a470559543857a62102c84700d291fc984c"))) + :commit "12fe553fdaaa7449f764bc876fd777704d4fb752"))) + (set-tree-sitter! nil 'go-mod-ts-mode + '((gomod :url "https://github.com/camdencheek/tree-sitter-go-mod" + :commit "3b01edce2b9ea6766ca19328d1850e456fde3103"))) + (when (fboundp 'go-work-ts-mode) ; 30.1+ only + (add-to-list 'auto-mode-alist '("/go\\.work\\'" . go-work-ts-mode-maybe)) + (set-tree-sitter! nil 'go-work-ts-mode + '((gowork :url "https://github.com/omertuc/tree-sitter-go-work" + :commit "949a8a470559543857a62102c84700d291fc984c")))) :config (+go-common-config 'go-ts-mode)) From 94a1fe64a8d3fffee4160e397d320e3850c95b6d Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 31 Aug 2025 12:30:49 +0200 Subject: [PATCH 70/71] fix(tree-sitter): suppress "Can't find grammar" warnings In Emacs <=30, top-level `treesit-ready-p` calls in various *-ts-mode packages (like lua-ts-mode or ruby-ts-mode) are commonplace, and they throw up a warning popup if the grammar isn't available at load time. This is intrusive. Instead, this forces it to log to *Messages* instead before falling back to the normal major mode. Fortunately, these top-level `treesit-ready-p` calls have been removed in most *-ts-mode packages in 31+, but this still impacts users on <=30 or using third party *-ts-modes that haven't adapted. However, this doesn't suppress the warning when opening a *-ts-mode.el file (thanks to the byte-compiler). --- modules/tools/tree-sitter/config.el | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/tools/tree-sitter/config.el b/modules/tools/tree-sitter/config.el index 09845c365..d45aa88c9 100644 --- a/modules/tools/tree-sitter/config.el +++ b/modules/tools/tree-sitter/config.el @@ -51,7 +51,12 @@ (memq fallback-mode treesit-enabled-modes)) ;; Lazily load autoloaded `treesit-language-source-alist' ;; entries. - (let ((fn (symbol-function mode))) + (let ((fn (symbol-function mode)) + ;; Silence "can't find grammar" warning popups from + ;; `treesit-ready-p' calls in Emacs <=30.1. We'll + ;; log it to *Messages* instead. + (warning-suppress-types + (cons '(treesit) warning-suppress-types))) (or (not (autoloadp fn)) (autoload-do-load fn mode))) ;; Only prompt once, and log other times. From 571766e6bafe37f7d8b38911a2740cd658ea85fb Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 31 Aug 2025 14:47:03 +0200 Subject: [PATCH 71/71] fix(qt): eglot support Also refactor module out of autoload.el into config.el (now that it's non-trivial). Ref: doomemacs/community#24 --- modules/lang/qt/autoload.el | 14 -------------- modules/lang/qt/config.el | 27 +++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 14 deletions(-) delete mode 100644 modules/lang/qt/autoload.el create mode 100644 modules/lang/qt/config.el diff --git a/modules/lang/qt/autoload.el b/modules/lang/qt/autoload.el deleted file mode 100644 index 805be65b1..000000000 --- a/modules/lang/qt/autoload.el +++ /dev/null @@ -1,14 +0,0 @@ -;;; lang/qt/autoload.el -*- lexical-binding: t; -*- - -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.pr[io]\\'" . qt-pro-mode)) - -;;;###autoload -(when (modulep! +tree-sitter) - (set-tree-sitter! 'qml-mode 'qml-ts-mode - '((qmljs :url "https://github.com/yuja/tree-sitter-qmljs")))) - -;;;###autoload -(when (modulep! +lsp) - (add-hook 'qml-mode-local-vars-hook #'lsp! 'append) - (add-hook 'qml-ts-mode-local-vars-hook #'lsp! 'append)) diff --git a/modules/lang/qt/config.el b/modules/lang/qt/config.el new file mode 100644 index 000000000..afcd94357 --- /dev/null +++ b/modules/lang/qt/config.el @@ -0,0 +1,27 @@ +;;; lang/qt/config.el -*- lexical-binding: t; -*- + +(defun +qt-common-config (mode) + (when (modulep! +lsp) + (set-eglot-client! mode '("qmlls")) + (add-hook (intern (format "%s-local-vars-hook" mode)) #'lsp! 'append))) + + +(use-package! qml-mode + :defer t + :config + (+qt-common-config 'qml-mode)) + + +(use-package! qml-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'treesit-available-p) + :defer t + :init + (set-tree-sitter! 'qml-mode 'qml-ts-mode + '((qmljs :url "https://github.com/yuja/tree-sitter-qmljs"))) + :config + (+qt-common-config 'qml-ts-mode)) + + +(use-package! qt-pro-mode + :mode "\\.pr[io]\\'")