commit 2f1052d9b0de551dc3a463ed54e21c63517497ab (HEAD, refs/remotes/origin/master) Author: Pip Cet Date: Mon Dec 30 21:55:38 2024 +0000 ; * src/doc.c (store_function_docstring): Fix typo. diff --git a/src/doc.c b/src/doc.c index fdb61be2097..9620e4a2173 100644 --- a/src/doc.c +++ b/src/doc.c @@ -497,7 +497,7 @@ store_function_docstring (Lisp_Object obj, EMACS_INT offset) } else { - AUTO_STRING (format, "Ignoring DOC string on non-compiled" + AUTO_STRING (format, "Ignoring DOC string on non-compiled " "non-subr: %S"); CALLN (Fmessage, format, obj); } commit 687ff86e802c9883f292f58a890178d08311a821 Author: Juri Linkov Date: Mon Dec 30 20:07:40 2024 +0200 Improve treesit-forward-sexp-list, treesit-down-list, treesit-up-list * lisp/treesit.el (treesit-forward-sexp-list): Rewrite to support the value of ARG more than 1. In this case every step moves forward either over the next treesit-based list or over the syntax-based symbol. (treesit-down-list, treesit-up-list): Rewrite to support the fallback to the syntax-based navigation while inside the treesit-based list. Also use a loop for ARG more than 1 (bug#73404). diff --git a/lisp/treesit.el b/lisp/treesit.el index fd78d561a4a..ad95e53e667 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -2481,47 +2481,40 @@ outside of the boundaries of the current list. ARG is described in the docstring of `forward-sexp-function'." (interactive "^p") - (let* ((arg (or arg 1)) - (pred 'sexp-list) - (default-pos - (condition-case _ - (save-excursion - (forward-sexp-default-function arg) - (point)) - (scan-error nil))) - (default-pos (unless (eq (point) default-pos) default-pos)) - (sibling-pos - (when default-pos - (save-excursion - (and (if (> arg 0) - (treesit-end-of-thing pred (abs arg) 'restricted) - (treesit-beginning-of-thing pred (abs arg) 'restricted)) - (point))))) - (sibling (when sibling-pos - (if (> arg 0) - (treesit-thing-prev sibling-pos pred) - (treesit-thing-next sibling-pos pred)))) - (sibling (when (and sibling - (if (> arg 0) - (<= (point) (treesit-node-start sibling)) - (>= (point) (treesit-node-end sibling)))) - sibling)) - (current-thing (when default-pos - (treesit-thing-at (point) pred t)))) - - ;; 'forward-sexp-default-function' should not go out of the current thing, - ;; neither go inside the next thing or go over the next thing - (or (when (and default-pos - (or (null current-thing) - (if (> arg 0) - (< default-pos (treesit-node-end current-thing)) - (> default-pos (treesit-node-start current-thing)))) - (or (null sibling) - (if (> arg 0) - (<= default-pos (treesit-node-start sibling)) - (>= default-pos (treesit-node-end sibling))))) - (goto-char default-pos)) - (treesit-forward-list arg)))) + (let* ((pred (or treesit-sexp-type-regexp 'sexp-list)) + (arg (or arg 1)) + (cnt arg) + (inc (if (> arg 0) 1 -1))) + (while (/= cnt 0) + (let* ((default-pos + (condition-case _ + (save-excursion + (forward-sexp-default-function inc) + (point)) + (scan-error nil))) + (sibling (if (> arg 0) + (treesit-thing-next (point) pred) + (treesit-thing-prev (point) pred))) + (current (when default-pos + (treesit-thing-at (point) pred t)))) + ;; Use 'forward-sexp-default-function' only if it doesn't go + ;; over the sibling and doesn't go out of the current group. + (or (when (and default-pos + (or (null sibling) + (if (> arg 0) + (<= default-pos (treesit-node-start sibling)) + (>= default-pos (treesit-node-end sibling)))) + (or (null current) + (if (> arg 0) + (< default-pos (treesit-node-end current)) + (> default-pos (treesit-node-start current))))) + (goto-char default-pos)) + (when sibling + (goto-char (if (> arg 0) + (treesit-node-end sibling) + (treesit-node-start sibling)))) + (treesit--scan-error pred arg))) + (setq cnt (- cnt inc))))) (defun treesit-forward-list (&optional arg) "Move forward across a list. @@ -2557,21 +2550,34 @@ ARG is described in the docstring of `down-list'." (interactive "^p") (let* ((pred 'sexp-list) (arg (or arg 1)) + (cnt arg) (inc (if (> arg 0) 1 -1))) - (while (/= arg 0) - (let* ((node (if (> arg 0) - (treesit-thing-next (point) pred) - (treesit-thing-prev (point) pred))) - (child (when node - (treesit-node-child node (if (> arg 0) 0 -1)))) - (pos (when child - (if (> arg 0) - (treesit-node-end child) - (treesit-node-start child))))) - (if pos (goto-char pos) (treesit--scan-error pred arg))) - (setq arg (- arg inc))))) - -(defun treesit-up-list (&optional arg _escape-strings _no-syntax-crossing) + (while (/= cnt 0) + (let* ((default-pos + (condition-case _ + (save-excursion + (down-list-default-function inc) + (point)) + (scan-error nil))) + (sibling (if (> arg 0) + (treesit-thing-next (point) pred) + (treesit-thing-prev (point) pred))) + (child (when sibling + (treesit-node-child sibling (if (> arg 0) 0 -1))))) + (or (when (and default-pos + (or (null child) + (if (> arg 0) + (<= default-pos (treesit-node-start child)) + (>= default-pos (treesit-node-end child))))) + (goto-char default-pos)) + (when child + (goto-char (if (> arg 0) + (treesit-node-end child) + (treesit-node-start child)))) + (treesit--scan-error pred arg))) + (setq cnt (- cnt inc))))) + +(defun treesit-up-list (&optional arg escape-strings no-syntax-crossing) "Move forward out of one level of parentheses. What constitutes a level of parentheses is determined by `sexp-list' in `treesit-thing-settings' that usually defines @@ -2584,19 +2590,35 @@ ARG is described in the docstring of `up-list'." (interactive "^p") (let* ((pred 'sexp-list) (arg (or arg 1)) + (cnt arg) (inc (if (> arg 0) 1 -1))) - (while (/= arg 0) - (let ((node (treesit-thing-at (point) pred))) - (while (and node (eq (point) (if (> arg 0) - (treesit-node-end node) - (treesit-node-start node)))) - (setq node (treesit-parent-until node pred))) - (if node - (goto-char (if (> arg 0) - (treesit-node-end node) - (treesit-node-start node))) - (user-error "At top level"))) - (setq arg (- arg inc))))) + (while (/= cnt 0) + (let* ((default-pos + (condition-case _ + (save-excursion + (let ((forward-sexp-function nil)) + (up-list-default-function + inc escape-strings no-syntax-crossing)) + (point)) + (scan-error nil) + (user-error nil))) + (parent (treesit-thing-at (point) pred))) + (while (and parent (eq (point) (if (> arg 0) + (treesit-node-end parent) + (treesit-node-start parent)))) + (setq parent (treesit-parent-until parent pred))) + (or (when (and default-pos + (or (null parent) + (if (> arg 0) + (<= default-pos (treesit-node-end parent)) + (>= default-pos (treesit-node-start parent))))) + (goto-char default-pos)) + (when parent + (goto-char (if (> arg 0) + (treesit-node-end parent) + (treesit-node-start parent)))) + (user-error "At top level"))) + (setq cnt (- cnt inc))))) (defun treesit-transpose-sexps (&optional arg) "Tree-sitter `transpose-sexps' function. commit 4068948a74586056cf03a22cae2448d7b4e4a7bd Author: Juri Linkov Date: Mon Dec 30 19:54:39 2024 +0200 * lisp/treesit.el (treesit-show-paren-data--categorize): Fix it. Copy the implementation of treesit-parent-until here, and call its treesit-node-match-p with the argument IGNORE-MISSING set to t that causes it to fail silently instead of raising an error when the predicate 'sexp-list' is not defined in an embedded language. (treesit-major-mode-setup): Set show-paren-data-function to treesit-show-paren-data only when 'sexp-list' thing is defined that is used by treesit-show-paren-data--categorize (bug#75198). diff --git a/lisp/treesit.el b/lisp/treesit.el index 4fe4f7276f6..fd78d561a4a 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -3393,7 +3393,9 @@ For BOUND, MOVE, BACKWARD, LOOKING-AT, see the descriptions in (defun treesit-show-paren-data--categorize (pos &optional end-p) (let* ((pred 'sexp-list) - (parent (treesit-parent-until (treesit-node-at (if end-p (1- pos) pos)) pred)) + (parent (treesit-node-at (if end-p (1- pos) pos))) + (_ (while (and parent (not (treesit-node-match-p parent pred t))) + (setq parent (treesit-node-parent parent)))) (first (when parent (treesit-node-child parent 0))) (first-start (when first (treesit-node-start first))) (first-end (when first (treesit-node-end first))) @@ -3417,13 +3419,13 @@ For BOUND, MOVE, BACKWARD, LOOKING-AT, see the descriptions in (unless (bobp) (treesit-show-paren-data--categorize (point) t)) (when show-paren-when-point-in-periphery (let* ((ind-pos (save-excursion (back-to-indentation) (point))) - (eol-pos - (save-excursion - (end-of-line) (skip-chars-backward " \t" ind-pos) (point)))) + (eol-pos + (save-excursion + (end-of-line) (skip-chars-backward " \t" ind-pos) (point)))) (cond ((<= (point) ind-pos) (or (treesit-show-paren-data--categorize ind-pos) - (unless (bobp) + (unless (bobp) (treesit-show-paren-data--categorize (1- eol-pos))))) ((>= (point) eol-pos) (unless (bobp) @@ -3567,7 +3569,8 @@ before calling this function." (setq-local forward-sexp-function #'treesit-forward-sexp-list) (setq-local forward-list-function #'treesit-forward-list) (setq-local down-list-function #'treesit-down-list) - (setq-local up-list-function #'treesit-up-list)) + (setq-local up-list-function #'treesit-up-list) + (setq-local show-paren-data-function 'treesit-show-paren-data)) (when (treesit-thing-defined-p 'sentence nil) (setq-local forward-sentence-function #'treesit-forward-sentence)) @@ -3589,8 +3592,6 @@ before calling this function." (setq-local outline-search-function #'treesit-outline-search outline-level #'treesit-outline-level)) - (setq-local show-paren-data-function 'treesit-show-paren-data) - ;; Remove existing local parsers. (dolist (ov (overlays-in (point-min) (point-max))) (when-let* ((parser (overlay-get ov 'treesit-parser))) commit 7671d50b149edd9e19c29f5fa8ee71c01e2f583d Author: Michael Albinus Date: Mon Dec 30 12:42:00 2024 +0100 ; Minor Tramp changes * lisp/net/tramp.el (tramp-handle-make-process): * lisp/net/tramp-adb.el (tramp-adb-handle-make-process): * lisp/net/tramp-androidsu.el (tramp-androidsu-handle-make-process): * lisp/net/tramp-sh.el (tramp-sh-handle-make-process): * lisp/net/tramp-smb.el (tramp-smb-handle-start-file-process): Don't use connection property "remote-command", it's superfluous. * lisp/net/tramp-archive.el (tramp-archive-local-file-name): Add `tramp-archive-method' to `tramp-methods' temporarily. diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index 7fbb2332e89..27570645b60 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -846,8 +846,6 @@ will be used." (when filter (set-process-filter p filter)) (process-put p 'remote-command orig-command) - (tramp-set-connection-property - p "remote-command" orig-command) ;; Set query flag and process marker for this ;; process. We ignore errors, because the ;; process could have finished already. diff --git a/lisp/net/tramp-androidsu.el b/lisp/net/tramp-androidsu.el index 9b45b416ff9..2dde7094c27 100644 --- a/lisp/net/tramp-androidsu.el +++ b/lisp/net/tramp-androidsu.el @@ -375,7 +375,6 @@ FUNCTION." ;; so we reset it. (set-process-query-on-exit-flag p (null noquery)) (process-put p 'remote-command orig-command) - (tramp-set-connection-property p "remote-command" orig-command) (when (bufferp stderr) (tramp-taint-remote-process-buffer stderr)) p))) diff --git a/lisp/net/tramp-archive.el b/lisp/net/tramp-archive.el index f77dcec3663..f3996900aee 100644 --- a/lisp/net/tramp-archive.el +++ b/lisp/net/tramp-archive.el @@ -585,7 +585,8 @@ offered." ;; This is used in GNU ELPA package tramp-locproc.el. (defun tramp-archive-local-file-name (filename) "Return local mount name of FILENAME." - (tramp-gvfs-local-file-name (tramp-archive-gvfs-file-name filename))) + (let ((tramp-methods (cons `(,tramp-archive-method) tramp-methods))) + (tramp-gvfs-local-file-name (tramp-archive-gvfs-file-name filename)))) ;; File name primitives. diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 7b82195ed68..32f39070971 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -3150,8 +3150,6 @@ will be used." (when filter (set-process-filter p filter)) (process-put p 'remote-command orig-command) - (tramp-set-connection-property - p "remote-command" orig-command) ;; Set query flag and process marker for this ;; process. We ignore errors, because the ;; process could have finished already. diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index 8d090a6969f..87702d90665 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -1476,9 +1476,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (tramp-send-string v command))) (setq p (tramp-get-connection-process v)) (when program - (process-put p 'remote-command (cons program args)) - (tramp-set-connection-property - p "remote-command" (cons program args))) + (process-put p 'remote-command (cons program args))) ;; Return value. p))) diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 03e12471176..ea44a61be19 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -5294,7 +5294,6 @@ should be set connection-local.") ;; so we reset it. (set-process-query-on-exit-flag p (null noquery)) (process-put p 'remote-command orig-command) - (tramp-set-connection-property p "remote-command" orig-command) (when (bufferp stderr) (tramp-taint-remote-process-buffer stderr)) commit ec3f9434c7d615dc37ba444a2200f13c84984299 Author: Yuan Fu Date: Mon Dec 30 00:21:55 2024 -0800 Make typescript-ts-mode work with latest grammar * lisp/progmodes/typescript-ts-mode.el: (tsx-ts-mode--font-lock-compatibility-bb1f97b): Return dummy query when neither query works. In latest grammar, neither will work, because typescript grammar doesn't include jsx grammar anymore. diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el index df41c179e30..06635378dfd 100644 --- a/lisp/progmodes/typescript-ts-mode.el +++ b/lisp/progmodes/typescript-ts-mode.el @@ -22,6 +22,15 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Tree-sitter language versions +;; +;; typescript-ts-mode is known to work with the following languages and version: +;; - tree-sitter-typescript: v0.23.2-2-g8e13e1d +;; +;; We try our best to make builtin modes work with latest grammar +;; versions, so a more recent grammar version has a good chance to work. +;; Send us a bug report if it doesn't. + ;;; Commentary: ;; @@ -192,32 +201,47 @@ Argument LANGUAGE is either `typescript' or `tsx'." ;; Warning: treesitter-query-capture says both node types are valid, ;; but then raises an error if the wrong node type is used. So it is ;; important to check with the new node type (member_expression) + ;; + ;; Later typescript grammar removed support for jsx, so the later + ;; grammar versions this function just return nil. (typescript-ts-mode--check-dialect language) - (condition-case nil - (progn (treesit-query-capture language '((jsx_opening_element (member_expression) @capture))) - '((jsx_opening_element - [(member_expression (identifier)) (identifier)] - @typescript-ts-jsx-tag-face) - - (jsx_closing_element - [(member_expression (identifier)) (identifier)] - @typescript-ts-jsx-tag-face) - - (jsx_self_closing_element - [(member_expression (identifier)) (identifier)] - @typescript-ts-jsx-tag-face))) - (treesit-query-error - '((jsx_opening_element - [(nested_identifier (identifier)) (identifier)] - @typescript-ts-jsx-tag-face) - - (jsx_closing_element - [(nested_identifier (identifier)) (identifier)] - @typescript-ts-jsx-tag-face) - - (jsx_self_closing_element - [(nested_identifier (identifier)) (identifier)] - @typescript-ts-jsx-tag-face))))) + (let ((queries-a '((jsx_opening_element + [(member_expression (identifier)) (identifier)] + @typescript-ts-jsx-tag-face) + + (jsx_closing_element + [(member_expression (identifier)) (identifier)] + @typescript-ts-jsx-tag-face) + + (jsx_self_closing_element + [(member_expression (identifier)) (identifier)] + @typescript-ts-jsx-tag-face) + + (jsx_attribute (property_identifier) + @typescript-ts-jsx-attribute-face))) + (queries-b '((jsx_opening_element + [(nested_identifier (identifier)) (identifier)] + @typescript-ts-jsx-tag-face) + + (jsx_closing_element + [(nested_identifier (identifier)) (identifier)] + @typescript-ts-jsx-tag-face) + + (jsx_self_closing_element + [(nested_identifier (identifier)) (identifier)] + @typescript-ts-jsx-tag-face) + + (jsx_attribute (property_identifier) + @typescript-ts-jsx-attribute-face)))) + (or (ignore-errors + (treesit-query-compile language queries-a t) + queries-a) + (ignore-errors + (treesit-query-compile language queries-b t) + queries-b) + ;; Return a dummy query that doens't do anything, if neither + ;; query works. + '("," @_ignore)))) (defun tsx-ts-mode--font-lock-compatibility-function-expression (language) "Handle tree-sitter grammar breaking change for `function' expression. @@ -386,8 +410,7 @@ Argument LANGUAGE is either `typescript' or `tsx'." :language language :feature 'jsx - (append (tsx-ts-mode--font-lock-compatibility-bb1f97b language) - `((jsx_attribute (property_identifier) @typescript-ts-jsx-attribute-face))) + (tsx-ts-mode--font-lock-compatibility-bb1f97b language) :language language :feature 'number commit 732a1108b0b553028ada334172635f039012a7f7 Author: Yuan Fu Date: Mon Dec 30 00:21:46 2024 -0800 Add verified grammar version comment for tree-sitter modes * lisp/progmodes/c-ts-mode.el: * lisp/progmodes/cmake-ts-mode.el: * lisp/progmodes/dockerfile-ts-mode.el: * lisp/progmodes/elixir-ts-mode.el: * lisp/progmodes/go-ts-mode.el: * lisp/progmodes/heex-ts-mode.el: * lisp/progmodes/java-ts-mode.el: * lisp/progmodes/js.el: * lisp/progmodes/json-ts-mode.el: * lisp/progmodes/lua-ts-mode.el: * lisp/progmodes/php-ts-mode.el: * lisp/progmodes/ruby-ts-mode.el: * lisp/progmodes/rust-ts-mode.el: * lisp/textmodes/css-mode.el: * lisp/textmodes/html-ts-mode.el: Add comments. diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 5537439004e..65b5e7ab23d 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -25,7 +25,7 @@ ;;; Tree-sitter language versions ;; ;; c-ts-mode is known to work with the following languages and version: -;; - tree-sitter-c: v0.23.4 +;; - tree-sitter-c: v0.23.4-1-g3aa2995 ;; ;; c++-ts-mode is known to work with the following languages and version: ;; - tree-sitter-cpp: v0.23.4-1-gf41b4f6 diff --git a/lisp/progmodes/cmake-ts-mode.el b/lisp/progmodes/cmake-ts-mode.el index 1871ea39a47..6b28c9a05d4 100644 --- a/lisp/progmodes/cmake-ts-mode.el +++ b/lisp/progmodes/cmake-ts-mode.el @@ -25,7 +25,7 @@ ;;; Tree-sitter language versions ;; ;; cmake-ts-mode is known to work with the following languages and version: -;; - tree-sitter-cmake: e409ae33f00e04cde30f2bcffb979caf1a33562a +;; - tree-sitter-cmake: v0.5.0-5-ge409ae3 ;; ;; We try our best to make builtin modes work with latest grammar ;; versions, so a more recent grammar version has a good chance to work. diff --git a/lisp/progmodes/dockerfile-ts-mode.el b/lisp/progmodes/dockerfile-ts-mode.el index a234af65a3d..c0151a1148d 100644 --- a/lisp/progmodes/dockerfile-ts-mode.el +++ b/lisp/progmodes/dockerfile-ts-mode.el @@ -22,6 +22,15 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Tree-sitter language versions +;; +;; dockerfile-ts-mode is known to work with the following languages and version: +;; - tree-sitter-dockerfile: v0.2.0-1-g087daa2 +;; +;; We try our best to make builtin modes work with latest grammar +;; versions, so a more recent grammar version has a good chance to work. +;; Send us a bug report if it doesn't. + ;;; Commentary: ;; diff --git a/lisp/progmodes/elixir-ts-mode.el b/lisp/progmodes/elixir-ts-mode.el index d0a692a214b..4e4a836602f 100644 --- a/lisp/progmodes/elixir-ts-mode.el +++ b/lisp/progmodes/elixir-ts-mode.el @@ -21,6 +21,16 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Tree-sitter language versions +;; +;; elixir-ts-mode is known to work with the following languages and version: +;; - tree-sitter-heex: v0.7.0 +;; - tree-sitter-elixir: v0.3.3 +;; +;; We try our best to make builtin modes work with latest grammar +;; versions, so a more recent grammar version has a good chance to work. +;; Send us a bug report if it doesn't. + ;;; Commentary: ;; ;; This package provides `elixir-ts-mode' which is a major mode for editing diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el index f3adeb9b2f3..b30190f4a3d 100644 --- a/lisp/progmodes/go-ts-mode.el +++ b/lisp/progmodes/go-ts-mode.el @@ -22,6 +22,15 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Tree-sitter language versions +;; +;; go-ts-mode is known to work with the following languages and version: +;; - tree-sitter-go: v0.23.4-1-g12fe553 +;; +;; We try our best to make builtin modes work with latest grammar +;; versions, so a more recent grammar version has a good chance to work. +;; Send us a bug report if it doesn't. + ;;; Commentary: ;; diff --git a/lisp/progmodes/heex-ts-mode.el b/lisp/progmodes/heex-ts-mode.el index 7430e4f3adb..ac7707b0913 100644 --- a/lisp/progmodes/heex-ts-mode.el +++ b/lisp/progmodes/heex-ts-mode.el @@ -21,6 +21,15 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Tree-sitter language versions +;; +;; heex-ts-mode is known to work with the following languages and version: +;; - tree-sitter-heex: v0.7.0 +;; +;; We try our best to make builtin modes work with latest grammar +;; versions, so a more recent grammar version has a good chance to work. +;; Send us a bug report if it doesn't. + ;;; Commentary: ;; ;; This package provides `heex-ts-mode' which is a major mode for editing diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el index 459e57ebfb4..8627366ddac 100644 --- a/lisp/progmodes/java-ts-mode.el +++ b/lisp/progmodes/java-ts-mode.el @@ -22,6 +22,15 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Tree-sitter language versions +;; +;; java-ts-mode is known to work with the following languages and version: +;; - tree-sitter-java: v0.23.5 +;; +;; We try our best to make builtin modes work with latest grammar +;; versions, so a more recent grammar version has a good chance to work. +;; Send us a bug report if it doesn't. + ;;; Commentary: ;; ;; If the tree-sitter doxygen grammar is available, then the comment diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el index 1b6565f66c2..aa585d46967 100644 --- a/lisp/progmodes/js.el +++ b/lisp/progmodes/js.el @@ -24,6 +24,16 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Tree-sitter language versions +;; +;; js-ts-mode is known to work with the following languages and version: +;; - tree-sitter-jsdoc: v0.23.2 +;; - tree-sitter-javascript: v0.23.1-2-g108b2d4 +;; +;; We try our best to make builtin modes work with latest grammar +;; versions, so a more recent grammar version has a good chance to work. +;; Send us a bug report if it doesn't. + ;;; Commentary: ;; This is based on Karl Landstrom's barebones javascript-mode. This diff --git a/lisp/progmodes/json-ts-mode.el b/lisp/progmodes/json-ts-mode.el index 70b18ce7d95..cdecb329b5d 100644 --- a/lisp/progmodes/json-ts-mode.el +++ b/lisp/progmodes/json-ts-mode.el @@ -22,6 +22,15 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Tree-sitter language versions +;; +;; json-ts-mode is known to work with the following languages and version: +;; - tree-sitter-json: v0.24.8-1-g4d770d3 +;; +;; We try our best to make builtin modes work with latest grammar +;; versions, so a more recent grammar version has a good chance to work. +;; Send us a bug report if it doesn't. + ;;; Commentary: ;; diff --git a/lisp/progmodes/lua-ts-mode.el b/lisp/progmodes/lua-ts-mode.el index 857be185fcf..a0c492c335c 100644 --- a/lisp/progmodes/lua-ts-mode.el +++ b/lisp/progmodes/lua-ts-mode.el @@ -21,6 +21,15 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Tree-sitter language versions +;; +;; lua-ts-mode is known to work with the following languages and version: +;; - tree-sitter-lua: v0.2.0-2-g34e60e7 +;; +;; We try our best to make builtin modes work with latest grammar +;; versions, so a more recent grammar version has a good chance to work. +;; Send us a bug report if it doesn't. + ;;; Commentary: ;; This package provides `lua-ts-mode' which is a major mode for Lua diff --git a/lisp/progmodes/php-ts-mode.el b/lisp/progmodes/php-ts-mode.el index 5d360a6818b..128cefd3946 100644 --- a/lisp/progmodes/php-ts-mode.el +++ b/lisp/progmodes/php-ts-mode.el @@ -22,6 +22,20 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Tree-sitter language versions +;; +;; php-ts-mode is known to work with the following languages and version: +;; - tree-sitter-phpdoc: fe3202e468bc17332bec8969f2b50ff1f1da3a46 +;; - tree-sitter-css: v0.23.1-1-g6a442a3 +;; - tree-sitter-jsdoc: v0.23.2 +;; - tree-sitter-javascript: v0.23.1-2-g108b2d4 +;; - tree-sitter-html: v0.23.2-1-gd9219ad +;; - tree-sitter-php: v0.23.11 +;; +;; We try our best to make builtin modes work with latest grammar +;; versions, so a more recent grammar version has a good chance to work. +;; Send us a bug report if it doesn't. + ;;; Commentary: ;; ;; This package provides `php-ts-mode' which is a major mode diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el index 0ee72df6c9d..17e6a422720 100644 --- a/lisp/progmodes/ruby-ts-mode.el +++ b/lisp/progmodes/ruby-ts-mode.el @@ -22,6 +22,15 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Tree-sitter language versions +;; +;; ruby-ts-mode is known to work with the following languages and version: +;; - tree-sitter-ruby: v0.23.1 +;; +;; We try our best to make builtin modes work with latest grammar +;; versions, so a more recent grammar version has a good chance to work. +;; Send us a bug report if it doesn't. + ;;; Commentary: ;; This file defines ruby-ts-mode which is a major mode for editing diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el index ee749e963cd..0d0f76644fe 100644 --- a/lisp/progmodes/rust-ts-mode.el +++ b/lisp/progmodes/rust-ts-mode.el @@ -22,6 +22,15 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Tree-sitter language versions +;; +;; rust-ts-mode is known to work with the following languages and version: +;; - tree-sitter-rust: v0.23.2-1-g1f63b33 +;; +;; We try our best to make builtin modes work with latest grammar +;; versions, so a more recent grammar version has a good chance to work. +;; Send us a bug report if it doesn't. + ;;; Commentary: ;; diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el index c8da28187ee..d67cdf23222 100644 --- a/lisp/textmodes/css-mode.el +++ b/lisp/textmodes/css-mode.el @@ -21,6 +21,15 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Tree-sitter language versions +;; +;; css-ts-mode is known to work with the following languages and version: +;; - tree-sitter-css: v0.23.1-1-g6a442a3 +;; +;; We try our best to make builtin modes work with latest grammar +;; versions, so a more recent grammar version has a good chance to work. +;; Send us a bug report if it doesn't. + ;;; Commentary: ;; Yet another CSS mode. diff --git a/lisp/textmodes/html-ts-mode.el b/lisp/textmodes/html-ts-mode.el index 875ab267fd8..4790a4fd547 100644 --- a/lisp/textmodes/html-ts-mode.el +++ b/lisp/textmodes/html-ts-mode.el @@ -22,6 +22,15 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Tree-sitter language versions +;; +;; html-ts-mode is known to work with the following languages and version: +;; - tree-sitter-html: v0.23.2-1-gd9219ad +;; +;; We try our best to make builtin modes work with latest grammar +;; versions, so a more recent grammar version has a good chance to work. +;; Send us a bug report if it doesn't. + ;;; Commentary: ;; commit 0b1986ba5243b150bf6891f51827a4dae28447b0 Author: Yuan Fu Date: Mon Dec 30 00:14:37 2024 -0800 Generate compatibility report for multiple Emacs versions * admin/tree-sitter/compat-template.html: Update template. * admin/tree-sitter/treesit-admin.el: (treesit-admin--builtin-language-sources): Add sources. (treesit-admin--builtin-modes): New variable. (treesit-admin--verify-major-mode-queries): Don't need to pass LANGS argument anymore. (treesit-admin-verify-major-mode-queries): Move, and use treesit-admin--builtin-modes. (treesit-admin--mode-languages): Set some variables so it gets all the languages. (treesit-admin--find-latest-compatible-revision): Also return commit timestamp. (treesit-admin--generate-compatibility-report): New parameter EMACS-EXECUTABLES. Support generating report for multiple Emacs versions. * lisp/treesit.el (treesit--language-git-timestamp): New function. diff --git a/admin/tree-sitter/compat-template.html b/admin/tree-sitter/compat-template.html index f310d1b9ee5..23b5b55d7b3 100644 --- a/admin/tree-sitter/compat-template.html +++ b/admin/tree-sitter/compat-template.html @@ -9,6 +9,7 @@ width: min(90vw, 40rem); margin: auto; margin-top: 2rem; + margin-bottom: 2rem; font-family: ui-serif; } thead { @@ -19,6 +20,8 @@ } table td { padding: 0.5rem 1rem; + width: 10rem; + word-break: break-all; } .head { background: lightgreen; @@ -26,20 +29,11 @@ -

Tree-sitter grammar compatibility for Emacs ___REPLACE_EMACS_VERSION___

-

This is an auto-generated report of the latest compatible versions of tree-sitter grammars for each major mode. A green background on the version indicates that the major mode is compatible with the latest commit in the upstream grammar repo.

+

Emacs tree-sitter grammar compatibility

+

This is an auto-generated report of the last compatible version for each grammar in each Emacs version. A green background on the version indicates that the Emacs version is compatible with the latest commit in the upstream grammar repo.

This report is generated on ___REPLACE_TIME___.

- - - - - - - - ___REPLACE_TABLE___ -
Major modeLanguageLatest compatible version
diff --git a/admin/tree-sitter/treesit-admin.el b/admin/tree-sitter/treesit-admin.el index c2b95888652..d0e2a4ffe45 100644 --- a/admin/tree-sitter/treesit-admin.el +++ b/admin/tree-sitter/treesit-admin.el @@ -77,16 +77,41 @@ (cmake "https://github.com/uyha/tree-sitter-cmake") (dockerfile "https://github.com/camdencheek/tree-sitter-dockerfile") (go "https://github.com/tree-sitter/tree-sitter-go") - (ruby "https://github.com/tree-sitter/tree-sitter-ruby")) + (ruby "https://github.com/tree-sitter/tree-sitter-ruby") + (javascript "https://github.com/tree-sitter/tree-sitter-javascript") + (typescript "https://github.com/tree-sitter/tree-sitter-typescript" + nil "typescript/src") + (tsx "https://github.com/tree-sitter/tree-sitter-typescript" + nil "tsx/src") + (json "https://github.com/tree-sitter/tree-sitter-json") + (rust "https://github.com/tree-sitter/tree-sitter-rust") + (php "https://github.com/tree-sitter/tree-sitter-php" + nil "php/src") + (css "https://github.com/tree-sitter/tree-sitter-css") + (phpdoc "https://github.com/claytonrcarter/tree-sitter-phpdoc") + (doxygen "https://github.com/tree-sitter-grammars/tree-sitter-doxygen") + (lua "https://github.com/tree-sitter-grammars/tree-sitter-lua") + (python "https://github.com/tree-sitter/tree-sitter-python") + (html "https://github.com/tree-sitter/tree-sitter-html") + (elixir "https://github.com/elixir-lang/tree-sitter-elixir") + (heex "https://github.com/phoenixframework/tree-sitter-heex") + (java "https://github.com/tree-sitter/tree-sitter-java") + (jsdoc "https://github.com/tree-sitter/tree-sitter-jsdoc")) "A list of sources for the builtin modes. The source information are in the format of `treesit-language-source-alist'. This is for development only.") -(defun treesit-admin--verify-major-mode-queries (modes langs source-alist grammar-dir) +(defvar treesit-admin--builtin-modes + '( c-ts-mode c++-ts-mode cmake-ts-mode dockerfile-ts-mode + go-ts-mode ruby-ts-mode js-ts-mode typescript-ts-mode tsx-ts-mode + json-ts-mode rust-ts-mode php-ts-mode css-ts-mode lua-ts-mode + html-ts-mode elixir-ts-mode heex-ts-mode java-ts-mode) + "Builtin tree-sitter modes that we check.") + +(defun treesit-admin--verify-major-mode-queries (modes source-alist grammar-dir) "Verify font-lock queries in MODES. -LANGS is a list of languages, it should cover all the languages used by -major modes in MODES. SOURCE-ALIST should have the same shape as +SOURCE-ALIST should have the same shape as `treesit-language-source-alist'. GRAMMAR-DIR is a temporary direction in which grammars are installed. @@ -101,7 +126,9 @@ queries that has problems with latest grammar." (invalid-feature-list nil) (valid-modes nil) (mode-language-alist nil) - (file-modes-alist nil)) + (file-modes-alist nil) + (langs (cl-remove-duplicates + (mapcan #'treesit-admin--mode-languages modes)))) (dolist (lang langs) (let* ((recipe (assoc lang source-alist)) (ver (apply #'treesit--install-language-grammar-1 @@ -191,17 +218,6 @@ queries that has problems with latest grammar." (nth 2 entry))))) (special-mode)))) -;;; Compatibility report - -(defvar treesit-admin-file-name (or load-file-name (buffer-file-name)) - "Filename of the source file treesit-admin.el.") - -(defvar treesit-admin--compat-template-file-name - (expand-file-name "compat-template.html" - (file-name-directory - (or load-file-name (buffer-file-name)))) - "Filename of the HTML template for the compatibility report.") - (defun treesit-admin-verify-major-mode-queries () "Varify font-lock queries in builtin major modes. @@ -211,11 +227,21 @@ that version of grammar. At the end of the process, show a list of queries that has problems with latest grammar." (interactive) (treesit-admin--verify-major-mode-queries - '(cmake-ts-mode dockerfile-ts-mode go-ts-mode ruby-ts-mode) - '(cmake dockerfile go ruby) + treesit-admin--builtin-modes treesit-admin--builtin-language-sources "/tmp/tree-sitter-grammars")) +;;; Compatibility report + +(defvar treesit-admin-file-name (or load-file-name (buffer-file-name)) + "Filename of the source file treesit-admin.el.") + +(defvar treesit-admin--compat-template-file-name + (expand-file-name "compat-template.html" + (file-name-directory + (or load-file-name (buffer-file-name)))) + "Filename of the HTML template for the compatibility report.") + (defun treesit-admin--validate-mode-lang (mode lang) "Validate queries for LANG in MODE. @@ -244,7 +270,11 @@ Return non-nil if all queries are valid, nil otherwise." (let ((settings (with-temp-buffer (ignore-errors - (funcall mode) + ;; TODO: A more generic way to find all queries. + (let ((c-ts-mode-enable-doxygen t) + (c-ts-mode-enable-doxygen t) + (java-ts-mode-enabel-doxygen t)) + (funcall mode)) (font-lock-mode -1) treesit-font-lock-settings))) (all-queries-valid t)) @@ -266,10 +296,11 @@ instead. Return a plist of the form - (:version VERSION :head-version HEAD-VERSION). + (:version VERSION :head-version HEAD-VERSION :timstamp TIMESTAMP). HEAD-VERSION is the version of the HEAD, VERSION is the latest -compatible version." +compatible version. TIMESTAMP is the commit date of VERSION in UNIX +epoch format." (let ((treesit-extra-load-path (list grammar-dir)) (treesit--install-language-grammar-full-clone t) (treesit--install-language-grammar-blobless t) @@ -278,7 +309,9 @@ compatible version." (emacs-executable (or emacs-executable (expand-file-name invocation-name invocation-directory))) - head-version version exit-code) + head-version version exit-code timestamp) + (when (not recipe) + (signal 'treesit-error `("Cannot find recipe" ,language))) (pcase-let ((`(,url ,revision ,source-dir ,cc ,c++ ,commit) recipe)) (with-temp-buffer @@ -294,6 +327,7 @@ compatible version." (treesit--build-grammar workdir grammar-dir language source-dir cc c++)) (setq version (treesit--language-git-revision workdir)) + (setq timestamp (treesit--language-git-timestamp workdir)) (message "Validateing version %s" version) (setq exit-code (call-process @@ -307,7 +341,7 @@ compatible version." ',mode ',language) (kill-emacs 0) (kill-emacs -1))))))))) - (list :version version :head-version head-version))) + (list :version version :head-version head-version :timestamp timestamp))) (defun treesit-admin--last-compatible-grammar-for-modes (modes source-alist grammar-dir &optional emacs-executable) @@ -336,47 +370,83 @@ VERSION and HEAD-VERSION in the plist are the same as in modes)) (defun treesit-admin--generate-compatibility-report - (modes out-file &optional emacs-executable) - "Generate a language compatibility report for MODES. - -If EMACS-EXECUTABLE is non-nil, use it for validating queries. Write -the report to OUT-FILE." - (interactive) - (with-temp-buffer - (let ((table (treesit-admin--last-compatible-grammar-for-modes - modes - treesit-admin--builtin-language-sources - "/tmp/treesit-grammar"))) - (dolist (entry table) - (let ((mode (car entry))) - (dolist (entry (cdr entry)) - (let* ((lang (car entry)) - (version (plist-get (cdr entry) :version)) - (head-version (plist-get (cdr entry) :head-version)) - (classname - (if (equal version head-version) "head" ""))) - (insert (format "%s%s%s\n" - mode lang classname version))))))) - (let ((time (current-time-string nil t)) - (table-text (buffer-string)) - (emacs-version - (if emacs-executable - (with-temp-buffer - (call-process emacs-executable nil t nil - "-Q" "--batch" - "--eval" "(princ emacs-version)") - (buffer-string)) - emacs-version))) - (erase-buffer) - (insert-file-contents treesit-admin--compat-template-file-name) - (goto-char (point-min)) - (search-forward "___REPLACE_EMACS_VERSION___") - (replace-match emacs-version t) - (search-forward "___REPLACE_TIME___") - (replace-match (format "%s UTC" time) t) - (search-forward "___REPLACE_TABLE___") - (replace-match table-text t) - (write-region (point-min) (point-max) out-file)))) + (emacs-executables modes out-file) + "Generate a table for language compatibiity for MODES. + +Note that this only works for Emacs 31 and later, because before Emacs +31 we can't validate a compiled query (because there's a bug preventing +us from eager compiling a compiled query that's already lazily +compiled). + +EMACS-EXECUTABLES is a list of Emacs executbles to check for." + (let ((tables + (mapcar + (lambda (emacs) + (cons (with-temp-buffer + (call-process emacs nil t nil + "-Q" "--batch" + "--eval" "(princ emacs-version)") + (buffer-string)) + (treesit-admin--last-compatible-grammar-for-modes + modes + treesit-admin--builtin-language-sources + "/tmp/treesit-grammar" + emacs))) + emacs-executables)) + (database (make-hash-table :test #'equal)) + languages) + (dolist (table tables) + (dolist (mode-entry (cdr table)) + (dolist (language-entry (cdr mode-entry)) + (let* ((lang (car language-entry)) + (plist (cdr language-entry)) + ;; KEY = (LANG . EMACS-VERSION) + (key (cons lang (car table))) + (existing-plist (gethash key database))) + (push lang languages) + ;; If there are two major modes that uses LANG, and they + ;; have different compatible versions, use the older + ;; version. + (when (or (not existing-plist) + (< (plist-get plist :timestamp) + (plist-get existing-plist :timestamp))) + (puthash key plist database)))))) + (setq languages (cl-sort (cl-remove-duplicates languages) + (lambda (a b) + (string< (symbol-name a) (symbol-name b))))) + ;; Compose HTML table. + (with-temp-buffer + (insert "Language") + (dolist (emacs-version (mapcar #'car tables)) + (insert (format "%s" emacs-version))) + (insert "\n") + (dolist (lang languages) + (insert "") + (insert (format "%s" lang)) + (dolist (emacs-version (mapcar #'car tables)) + (let* ((key (cons lang emacs-version)) + (plist (gethash key database)) + (version (plist-get plist :version)) + (head-version (plist-get plist :head-version)) + (classname + (if (equal version head-version) "head" ""))) + (if (not plist) + (insert "") + (insert (format "%s" + classname version))))) + (insert "\n")) + + ;; Compose table with template and write to out file. + (let ((time (current-time-string nil t)) + (table-text (buffer-string))) + (erase-buffer) + (insert-file-contents treesit-admin--compat-template-file-name) + (goto-char (point-min)) + (search-forward "___REPLACE_TIME___") + (replace-match (format "%s UTC" time) t) + (search-forward "___REPLACE_TABLE___") + (replace-match table-text t) + (write-region (point-min) (point-max) out-file))))) (provide 'treesit-admin) diff --git a/lisp/treesit.el b/lisp/treesit.el index 5e153bc6f78..4fe4f7276f6 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -4239,6 +4239,16 @@ nil." (string-trim (buffer-string))) (t nil)))) +(defun treesit--language-git-timestamp (repo-dir) + "Return the commit date in REPO-DIR in UNIX epoch. + +Return nil if failed to run command." + (with-temp-buffer + (if (eq 0 (call-process + "git" nil t nil "-C" repo-dir "log" "-1" "--format=%ct")) + (string-to-number (string-trim (buffer-string))) + nil))) + (defun treesit--call-process-signal (&rest args) "Run `call-process' with ARGS. If it returns anything but 0, signal an error. Use the buffer commit d9cfe1fe92ffda7e52dcb434e34bfdd1258f2688 Author: Yuan Fu Date: Sun Dec 29 00:31:37 2024 -0800 Add treesit-admin-generate-compatibility-report This function can generate a HTML report on latest compatible grammar versions for each major mode. * admin/tree-sitter/compat-template.html: Update. * admin/tree-sitter/treesit-admin.el: (treesit-admin--validate-mode-lang): Change so that emacs 30 can also run it. (treesit-admin--find-latest-compatible-revision): Support running checks with a different Emacs executable. (treesit-admin--generate-compatibility-report): New function. diff --git a/admin/tree-sitter/compat-template.html b/admin/tree-sitter/compat-template.html index 487d4aacaef..f310d1b9ee5 100644 --- a/admin/tree-sitter/compat-template.html +++ b/admin/tree-sitter/compat-template.html @@ -3,21 +3,42 @@ - Emacs tree-sitter language grammar version compatibility + Emacs tree-sitter grammar version compatibility report +

Tree-sitter grammar compatibility for Emacs ___REPLACE_EMACS_VERSION___

+

This is an auto-generated report of the latest compatible versions of tree-sitter grammars for each major mode. A green background on the version indicates that the major mode is compatible with the latest commit in the upstream grammar repo.

+

This report is generated on ___REPLACE_TIME___.

- + + + + + - REPLACE +___REPLACE_TABLE___
LanguageVersion
Major modeLanguageLatest compatible version
diff --git a/admin/tree-sitter/treesit-admin.el b/admin/tree-sitter/treesit-admin.el index 0787f6c9742..c2b95888652 100644 --- a/admin/tree-sitter/treesit-admin.el +++ b/admin/tree-sitter/treesit-admin.el @@ -228,7 +228,8 @@ Return non-nil if all queries are valid, nil otherwise." treesit-font-lock-settings))) (all-queries-valid t)) (dolist (setting settings) - (let* ((query (treesit-font-lock-setting-query setting)) + ;; `treesit-font-lock-setting-query' isn't available in Emacs 30. + (let* ((query (car setting)) (language (treesit-query-language query))) ;; Validate query. (when (and (eq lang language) @@ -253,13 +254,20 @@ Return non-nil if all queries are valid, nil otherwise." settings))))) (defun treesit-admin--find-latest-compatible-revision - (mode language source-alist grammar-dir) + (mode language source-alist grammar-dir &optional emacs-executable) "Find the latest revision for LANGUAGE that's compatible with MODE. MODE, LANGUAGE, SOURCE-ALIST, GRAMMAR-DIR are the same as in `treesit-admin--verify-major-mode-queries'. -Return a plist (:version VERSION :head-version HEAD-VERSION). +By default, use the Emacs executable that spawned the current Emacs +session to validate grammars, but if EMACS-EXECUTABLE is non-nil, use it +instead. + +Return a plist of the form + + (:version VERSION :head-version HEAD-VERSION). + HEAD-VERSION is the version of the HEAD, VERSION is the latest compatible version." (let ((treesit-extra-load-path (list grammar-dir)) @@ -268,7 +276,8 @@ compatible version." (recipe (alist-get language source-alist)) (workdir (make-temp-file "treesit-validate-workdir" t)) (emacs-executable - (expand-file-name invocation-name invocation-directory)) + (or emacs-executable + (expand-file-name invocation-name invocation-directory))) head-version version exit-code) (pcase-let ((`(,url ,revision ,source-dir ,cc ,c++ ,commit) recipe)) @@ -301,11 +310,12 @@ compatible version." (list :version version :head-version head-version))) (defun treesit-admin--last-compatible-grammar-for-modes - (modes source-alist grammar-dir) - "Generate an HTML page listing latest compatible grammar versions. + (modes source-alist grammar-dir &optional emacs-executable) + "Generate an alist listing latest compatible grammar versions. MODES, SOURCE-ALIST, GRAMMAR-DIR are the same as -`treesit-admin--verify-major-mode-queries'. +`treesit-admin--verify-major-mode-queries'. If EMACS-EXECUTABLE is +non-nil, use it for validating queries. Return an alist of an alist of a plist: @@ -320,14 +330,53 @@ VERSION and HEAD-VERSION in the plist are the same as in (lambda (language) (cons language (treesit-admin--find-latest-compatible-revision - mode language source-alist grammar-dir))) + mode language source-alist grammar-dir + emacs-executable))) (treesit-admin--mode-languages mode)))) modes)) -(defun treesit-admin-generate-compatibility-report () - "Generate a language compatibility report." +(defun treesit-admin--generate-compatibility-report + (modes out-file &optional emacs-executable) + "Generate a language compatibility report for MODES. + +If EMACS-EXECUTABLE is non-nil, use it for validating queries. Write +the report to OUT-FILE." (interactive) - ) + (with-temp-buffer + (let ((table (treesit-admin--last-compatible-grammar-for-modes + modes + treesit-admin--builtin-language-sources + "/tmp/treesit-grammar"))) + (dolist (entry table) + (let ((mode (car entry))) + (dolist (entry (cdr entry)) + (let* ((lang (car entry)) + (version (plist-get (cdr entry) :version)) + (head-version (plist-get (cdr entry) :head-version)) + (classname + (if (equal version head-version) "head" ""))) + (insert (format "%s%s%s\n" + mode lang classname version))))))) + (let ((time (current-time-string nil t)) + (table-text (buffer-string)) + (emacs-version + (if emacs-executable + (with-temp-buffer + (call-process emacs-executable nil t nil + "-Q" "--batch" + "--eval" "(princ emacs-version)") + (buffer-string)) + emacs-version))) + (erase-buffer) + (insert-file-contents treesit-admin--compat-template-file-name) + (goto-char (point-min)) + (search-forward "___REPLACE_EMACS_VERSION___") + (replace-match emacs-version t) + (search-forward "___REPLACE_TIME___") + (replace-match (format "%s UTC" time) t) + (search-forward "___REPLACE_TABLE___") + (replace-match table-text t) + (write-region (point-min) (point-max) out-file)))) (provide 'treesit-admin) commit 5ec170985f4a9b2facc5ac883d0312f9cd270034 Author: Yuan Fu Date: Sat Dec 28 23:08:43 2024 -0800 ; Move treesit-admin into tree-sitter directory * admin/tree-sitter/compat-template.html: New file. * admin/tree-sitter/treesit-admin.el: Move. diff --git a/admin/tree-sitter/compat-template.html b/admin/tree-sitter/compat-template.html new file mode 100644 index 00000000000..487d4aacaef --- /dev/null +++ b/admin/tree-sitter/compat-template.html @@ -0,0 +1,24 @@ + + + + + + Emacs tree-sitter language grammar version compatibility + + + + + + + + + REPLACE + +
LanguageVersion
+ + diff --git a/admin/treesit-admin.el b/admin/tree-sitter/treesit-admin.el similarity index 100% rename from admin/treesit-admin.el rename to admin/tree-sitter/treesit-admin.el commit c9624c21117f7bece4d5a8271888155de5d086a2 Author: Yuan Fu Date: Sat Dec 28 23:06:52 2024 -0800 Add treesit-admin--last-compatible-grammar-for-modes This function computes the latest compatible grammar version for each major mode. * admin/treesit-admin.el (treesit-admin-file-name): Move. (treesit-admin--compat-template-file-name): New variable. (treesit-admin--mode-languages): New function. (treesit-admin--find-latest-compatible-revision): Return a plist instead. (treesit-admin--last-compatible-grammar-for-modes): New function. diff --git a/admin/treesit-admin.el b/admin/treesit-admin.el index 253307775e9..0787f6c9742 100644 --- a/admin/treesit-admin.el +++ b/admin/treesit-admin.el @@ -82,9 +82,6 @@ The source information are in the format of `treesit-language-source-alist'. This is for development only.") -(defvar treesit-admin-file-name (or load-file-name (buffer-file-name)) - "Filename of the source file treesit-admin.el.") - (defun treesit-admin--verify-major-mode-queries (modes langs source-alist grammar-dir) "Verify font-lock queries in MODES. @@ -194,6 +191,17 @@ queries that has problems with latest grammar." (nth 2 entry))))) (special-mode)))) +;;; Compatibility report + +(defvar treesit-admin-file-name (or load-file-name (buffer-file-name)) + "Filename of the source file treesit-admin.el.") + +(defvar treesit-admin--compat-template-file-name + (expand-file-name "compat-template.html" + (file-name-directory + (or load-file-name (buffer-file-name)))) + "Filename of the HTML template for the compatibility report.") + (defun treesit-admin-verify-major-mode-queries () "Varify font-lock queries in builtin major modes. @@ -230,12 +238,30 @@ Return non-nil if all queries are valid, nil otherwise." (setq all-queries-valid nil)))) all-queries-valid)) +(defun treesit-admin--mode-languages (mode) + "Return languages used by MODE in a list." + (let ((settings + (with-temp-buffer + (ignore-errors + (funcall mode) + (font-lock-mode -1) + treesit-font-lock-settings))) + (all-queries-valid t)) + (cl-remove-duplicates + (mapcar #'treesit-query-language + (mapcar #'treesit-font-lock-setting-query + settings))))) + (defun treesit-admin--find-latest-compatible-revision (mode language source-alist grammar-dir) "Find the latest revision for LANGUAGE that's compatible with MODE. MODE, LANGUAGE, SOURCE-ALIST, GRAMMAR-DIR are the same as in -`treesit-admin--verify-major-mode-queries'." +`treesit-admin--verify-major-mode-queries'. + +Return a plist (:version VERSION :head-version HEAD-VERSION). +HEAD-VERSION is the version of the HEAD, VERSION is the latest +compatible version." (let ((treesit-extra-load-path (list grammar-dir)) (treesit--install-language-grammar-full-clone t) (treesit--install-language-grammar-blobless t) @@ -243,14 +269,14 @@ MODE, LANGUAGE, SOURCE-ALIST, GRAMMAR-DIR are the same as in (workdir (make-temp-file "treesit-validate-workdir" t)) (emacs-executable (expand-file-name invocation-name invocation-directory)) - version exit-code) + head-version version exit-code) (pcase-let ((`(,url ,revision ,source-dir ,cc ,c++ ,commit) recipe)) (with-temp-buffer (treesit--git-clone-repo url revision workdir) (when commit (treesit--git-checkout-branch workdir commit)) - + (setq head-version (treesit--language-git-revision workdir)) (treesit--build-grammar workdir grammar-dir language source-dir cc c++) (while (not (eq exit-code 0)) @@ -272,7 +298,36 @@ MODE, LANGUAGE, SOURCE-ALIST, GRAMMAR-DIR are the same as in ',mode ',language) (kill-emacs 0) (kill-emacs -1))))))))) - version)) + (list :version version :head-version head-version))) + +(defun treesit-admin--last-compatible-grammar-for-modes + (modes source-alist grammar-dir) + "Generate an HTML page listing latest compatible grammar versions. + +MODES, SOURCE-ALIST, GRAMMAR-DIR are the same as +`treesit-admin--verify-major-mode-queries'. + +Return an alist of an alist of a plist: + + ((MODE . ((LANG . (:version VERSION :head-VERSION HEAD-VERSION)) ...)) ...) + +VERSION and HEAD-VERSION in the plist are the same as in +`treesit-admin--find-latest-compatible-revision'." + (mapcar + (lambda (mode) + (cons mode + (mapcar + (lambda (language) + (cons language + (treesit-admin--find-latest-compatible-revision + mode language source-alist grammar-dir))) + (treesit-admin--mode-languages mode)))) + modes)) + +(defun treesit-admin-generate-compatibility-report () + "Generate a language compatibility report." + (interactive) + ) (provide 'treesit-admin) commit d5ad51f25fba84ac9fad7baf8781a761d1cead24 Author: Yuan Fu Date: Sat Dec 28 18:36:59 2024 -0800 Add treesit-admin--find-latest-compatible-revision This function can find the last grammar revision that is compatible with a major mode. * admin/treesit-admin.el (treesit-admin-file-name): New variable. (treesit-admin--validate-mode-lang): (treesit-admin--find-latest-compatible-revision): New functions. diff --git a/admin/treesit-admin.el b/admin/treesit-admin.el index 36b8cb620b5..253307775e9 100644 --- a/admin/treesit-admin.el +++ b/admin/treesit-admin.el @@ -82,6 +82,9 @@ The source information are in the format of `treesit-language-source-alist'. This is for development only.") +(defvar treesit-admin-file-name (or load-file-name (buffer-file-name)) + "Filename of the source file treesit-admin.el.") + (defun treesit-admin--verify-major-mode-queries (modes langs source-alist grammar-dir) "Verify font-lock queries in MODES. @@ -205,6 +208,71 @@ queries that has problems with latest grammar." treesit-admin--builtin-language-sources "/tmp/tree-sitter-grammars")) +(defun treesit-admin--validate-mode-lang (mode lang) + "Validate queries for LANG in MODE. + +Return non-nil if all queries are valid, nil otherwise." + (let ((settings + (with-temp-buffer + (ignore-errors + (funcall mode) + (font-lock-mode -1) + treesit-font-lock-settings))) + (all-queries-valid t)) + (dolist (setting settings) + (let* ((query (treesit-font-lock-setting-query setting)) + (language (treesit-query-language query))) + ;; Validate query. + (when (and (eq lang language) + (not (ignore-errors + (treesit-query-compile language query t) + t))) + (setq all-queries-valid nil)))) + all-queries-valid)) + +(defun treesit-admin--find-latest-compatible-revision + (mode language source-alist grammar-dir) + "Find the latest revision for LANGUAGE that's compatible with MODE. + +MODE, LANGUAGE, SOURCE-ALIST, GRAMMAR-DIR are the same as in +`treesit-admin--verify-major-mode-queries'." + (let ((treesit-extra-load-path (list grammar-dir)) + (treesit--install-language-grammar-full-clone t) + (treesit--install-language-grammar-blobless t) + (recipe (alist-get language source-alist)) + (workdir (make-temp-file "treesit-validate-workdir" t)) + (emacs-executable + (expand-file-name invocation-name invocation-directory)) + version exit-code) + (pcase-let ((`(,url ,revision ,source-dir ,cc ,c++ ,commit) + recipe)) + (with-temp-buffer + (treesit--git-clone-repo url revision workdir) + (when commit + (treesit--git-checkout-branch workdir commit)) + + (treesit--build-grammar + workdir grammar-dir language source-dir cc c++) + (while (not (eq exit-code 0)) + (unless (null exit-code) + (treesit--git-checkout-branch workdir "HEAD~") + (treesit--build-grammar + workdir grammar-dir language source-dir cc c++)) + (setq version (treesit--language-git-revision workdir)) + (message "Validateing version %s" version) + (setq exit-code + (call-process + emacs-executable nil t nil + "-Q" "--batch" + "--eval" (prin1-to-string + `(let ((treesit-extra-load-path + '(,grammar-dir))) + (load ,treesit-admin-file-name) + (if (treesit-admin--validate-mode-lang + ',mode ',language) + (kill-emacs 0) + (kill-emacs -1))))))))) + version)) (provide 'treesit-admin) commit 9e1e9fdff44f047489d45ba4a73776cb0298574f Author: Yuan Fu Date: Sat Dec 28 14:54:17 2024 -0800 Refactor treesit-admin--verify-major-mode-queries Make treesit-admin--verify-major-mode-queries use treesit--install-language-grammar-1, rathre than the interactive command treesit-install-language-grammar. * admin/treesit-admin.el: (treesit-admin--verify-major-mode-queries): Add parameter SOURCE-ALIST. Use treesit--install-language-grammar-1. (treesit-admin-verify-major-mode-queries): Pass treesit-admin--builtin-language-sources to treesit-admin--verify-major-mode-queries. * lisp/treesit.el (treesit-install-language-grammar): Don't return revision of the git repo. diff --git a/admin/treesit-admin.el b/admin/treesit-admin.el index 440056aff21..36b8cb620b5 100644 --- a/admin/treesit-admin.el +++ b/admin/treesit-admin.el @@ -82,19 +82,19 @@ The source information are in the format of `treesit-language-source-alist'. This is for development only.") -(defun treesit-admin--verify-major-mode-queries (modes langs grammar-dir) +(defun treesit-admin--verify-major-mode-queries (modes langs source-alist grammar-dir) "Verify font-lock queries in MODES. LANGS is a list of languages, it should cover all the languages used by -MODES. GRAMMAR-DIR is a temporary direction in which grammars are -installed. +major modes in MODES. SOURCE-ALIST should have the same shape as +`treesit-language-source-alist'. GRAMMAR-DIR is a temporary direction +in which grammars are installed. If the font-lock queries work fine with the latest grammar, insert some comments in the source file saying that the modes are known to work with that version of grammar. At the end of the process, show a list of queries that has problems with latest grammar." (let ((treesit-extra-load-path (list grammar-dir)) - (treesit-language-source-alist treesit-admin--builtin-language-sources) (treesit--install-language-grammar-full-clone t) (treesit--install-language-grammar-blobless t) (version-alist nil) @@ -103,7 +103,9 @@ queries that has problems with latest grammar." (mode-language-alist nil) (file-modes-alist nil)) (dolist (lang langs) - (let ((ver (treesit-install-language-grammar lang grammar-dir))) + (let* ((recipe (assoc lang source-alist)) + (ver (apply #'treesit--install-language-grammar-1 + (cons grammar-dir recipe)))) (if ver (push (cons lang ver) version-alist) (error "Cannot get version for %s" lang)))) @@ -200,6 +202,7 @@ queries that has problems with latest grammar." (treesit-admin--verify-major-mode-queries '(cmake-ts-mode dockerfile-ts-mode go-ts-mode ruby-ts-mode) '(cmake dockerfile go ruby) + treesit-admin--builtin-language-sources "/tmp/tree-sitter-grammars")) diff --git a/lisp/treesit.el b/lisp/treesit.el index 73e7e5446d4..5e153bc6f78 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -4171,10 +4171,7 @@ executable programs, such as the C/C++ compiler and linker. Interactively, prompt for the directory in which to install the compiled grammar files. Non-interactively, use OUT-DIR; if it's nil, the grammar is installed to the standard location, the -\"tree-sitter\" directory under `user-emacs-directory'. - -Return the git revision of the installed grammar, but it only works when -`treesit--install-language-grammar-full-clone' is t." +\"tree-sitter\" directory under `user-emacs-directory'." (interactive (list (intern (completing-read "Language: " @@ -4199,13 +4196,12 @@ Return the git revision of the installed grammar, but it only works when default-out-dir) ;; When called non-interactively, OUT-DIR should ;; default to DEFAULT-OUT-DIR. - (or out-dir default-out-dir))) - version) + (or out-dir default-out-dir)))) (when recipe (condition-case err (progn - (setq version (apply #'treesit--install-language-grammar-1 - (cons out-dir recipe))) + (apply #'treesit--install-language-grammar-1 + (cons out-dir recipe)) ;; Check that the installed language grammar is loadable. (pcase-let ((`(,available . ,err) @@ -4226,8 +4222,7 @@ Return the git revision of the installed grammar, but it only works when (display-warning 'treesit (format "Error encountered when installing language grammar: %s" - err))))) - version)) + err))))))) (defun treesit--language-git-revision (repo-dir) "Return the Git revision of the repo in REPO-DIR. commit e2f791715299d97f401a38c75fa11bb51fdb8292 Author: Yuan Fu Date: Sat Dec 28 14:41:55 2024 -0800 Refactor treesit--install-language-grammar-1 Separate treesit--install-language-grammar-1 into two functions, one clones the repository, the other builds and installs the grammar. * lisp/treesit.el (treesit--install-language-grammar-1): Refactor out treesit--build-grammar. (treesit--build-grammar): New function. (treesit--language-git-revision): Now takes REPO-DIR as an argument. diff --git a/lisp/treesit.el b/lisp/treesit.el index 090197d86e3..73e7e5446d4 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -4229,17 +4229,18 @@ Return the git revision of the installed grammar, but it only works when err))))) version)) -(defun treesit--language-git-revision () - "Return the Git revision of current directory. +(defun treesit--language-git-revision (repo-dir) + "Return the Git revision of the repo in REPO-DIR. Return the output of \"git describe\". If anything goes wrong, return nil." (with-temp-buffer (cond - ((eq 0 (call-process "git" nil t nil "describe" "--tags")) + ((eq 0 (call-process "git" nil t nil "-C" repo-dir "describe" "--tags")) (string-trim (buffer-string))) ((eq 0 (progn (erase-buffer) - (call-process "git" nil t nil "rev-parse" "HEAD"))) + (call-process "git" nil t nil + "-C" repo-dir "rev-parse" "HEAD"))) (string-trim (buffer-string))) (t nil)))) @@ -4284,7 +4285,7 @@ clone if `treesit--install-language-grammar-blobless' is t." (defun treesit--install-language-grammar-1 (out-dir lang url &optional revision source-dir cc c++ commit) - "Install and compile a tree-sitter language grammar library. + "Compile and install a tree-sitter language grammar library. OUT-DIR is the directory to put the compiled library file. If it is nil, the \"tree-sitter\" directory under user's Emacs @@ -4292,31 +4293,19 @@ configuration directory is used (and automatically created if it does not exist). For LANG, URL, REVISION, SOURCE-DIR, GRAMMAR-DIR, CC, C++, COMMIT, see -`treesit-language-source-alist'. If anything goes wrong, this function -signals an error. +`treesit-language-source-alist'. Return the git revision of the installed grammar. The revision is generated by \"git describe\". It only works when -`treesit--install-language-grammar-full-clone' is t." - (let* ((lang (symbol-name lang)) +`treesit--install-language-grammar-full-clone' is t. + +If anything goes wrong, this function signals an `treesit-error'." + (let* ((default-directory (make-temp-file "treesit-workdir" t)) (maybe-repo-dir (expand-file-name url)) (url-is-dir (file-accessible-directory-p maybe-repo-dir)) - (default-directory (make-temp-file "treesit-workdir" t)) (workdir (if url-is-dir maybe-repo-dir (expand-file-name "repo"))) - (source-dir (expand-file-name (or source-dir "src") workdir)) - (cc (or cc (seq-find #'executable-find '("cc" "gcc" "c99")) - ;; If no C compiler found, just use cc and let - ;; `call-process' signal the error. - "cc")) - (c++ (or c++ (seq-find #'executable-find '("c++" "g++")) - "c++")) - (soext (or (car dynamic-library-suffixes) - (signal 'treesit-error '("Emacs cannot figure out the file extension for dynamic libraries for this system, because `dynamic-library-suffixes' is nil")))) - (out-dir (or (and out-dir (expand-file-name out-dir)) - (locate-user-emacs-file "tree-sitter"))) - (lib-name (concat "libtree-sitter-" lang soext)) version) (unwind-protect (with-temp-buffer @@ -4326,59 +4315,86 @@ generated by \"git describe\". It only works when (treesit--git-clone-repo url revision workdir)) (when commit (treesit--git-checkout-branch workdir commit)) - ;; We need to go into the source directory because some - ;; header files use relative path (#include "../xxx"). - ;; cd "${sourcedir}" - (setq default-directory source-dir) - (setq version (treesit--language-git-revision)) - (message "Compiling library") - ;; cc -fPIC -c -I. parser.c - (treesit--call-process-signal - cc nil t nil "-fPIC" "-c" "-I." "parser.c") - ;; cc -fPIC -c -I. scanner.c - (when (file-exists-p "scanner.c") - (treesit--call-process-signal - cc nil t nil "-fPIC" "-c" "-I." "scanner.c")) - ;; c++ -fPIC -I. -c scanner.cc - (when (file-exists-p "scanner.cc") - (treesit--call-process-signal - c++ nil t nil "-fPIC" "-c" "-I." "scanner.cc")) - ;; cc/c++ -fPIC -shared *.o -o "libtree-sitter-${lang}.${soext}" - (apply #'treesit--call-process-signal - (if (file-exists-p "scanner.cc") c++ cc) - nil t nil - (if (eq system-type 'cygwin) - `("-shared" "-Wl,-dynamicbase" - ,@(directory-files - default-directory nil - (rx bos (+ anychar) ".o" eos)) - "-o" ,lib-name) - `("-fPIC" "-shared" - ,@(directory-files - default-directory nil - (rx bos (+ anychar) ".o" eos)) - "-o" ,lib-name))) - ;; Copy out. - (unless (file-exists-p out-dir) - (make-directory out-dir t)) - (let* ((library-fname (expand-file-name lib-name out-dir)) - (old-fname (concat library-fname ".old"))) - ;; Rename the existing shared library, if any, then - ;; install the new one, and try deleting the old one. - ;; This is for Windows systems, where we cannot simply - ;; overwrite a DLL that is being used. - (if (file-exists-p library-fname) - (rename-file library-fname old-fname t)) - (copy-file lib-name (file-name-as-directory out-dir) t t) - ;; Ignore errors, in case the old version is still used. - (ignore-errors (delete-file old-fname))) - (message "Library installed to %s/%s" out-dir lib-name)) + (setq version (treesit--language-git-revision workdir)) + (treesit--build-grammar workdir out-dir lang source-dir cc c++)) ;; Remove workdir if it's not a repo owned by user and we ;; managed to create it in the first place. (when (and (not url-is-dir) (file-exists-p workdir)) (delete-directory workdir t))) version)) +(defun treesit--build-grammar (workdir out-dir lang source-dir cc c++) + "Compile a tree-sitter language grammar library. + +WORKDIR is the cloned repo's directory. OUT-DIR is the directory to put +the compiled library file. If it is nil, the \"tree-sitter\" directory +under user's Emacs configuration directory is used (and automatically +created if it does not exist). + +For LANG, SOURCE-DIR, CC, C++, see `treesit-language-source-alist'. + +If anything goes wrong, this function signals an `treesit-error'." + (let* ((lang (symbol-name lang)) + (source-dir (expand-file-name (or source-dir "src") workdir)) + (cc (or cc (seq-find #'executable-find '("cc" "gcc" "c99")) + ;; If no C compiler found, just use cc and let + ;; `call-process' signal the error. + "cc")) + (c++ (or c++ (seq-find #'executable-find '("c++" "g++")) + "c++")) + (soext (or (car dynamic-library-suffixes) + (signal 'treesit-error '("Emacs cannot figure out the file extension for dynamic libraries for this system, because `dynamic-library-suffixes' is nil")))) + (out-dir (or (and out-dir (expand-file-name out-dir)) + (locate-user-emacs-file "tree-sitter"))) + (lib-name (concat "libtree-sitter-" lang soext))) + (with-temp-buffer + ;; We need to go into the source directory because some + ;; header files use relative path (#include "../xxx"). + ;; cd "${sourcedir}" + (setq default-directory source-dir) + (message "Compiling library") + ;; cc -fPIC -c -I. parser.c + (treesit--call-process-signal + cc nil t nil "-fPIC" "-c" "-I." "parser.c") + ;; cc -fPIC -c -I. scanner.c + (when (file-exists-p "scanner.c") + (treesit--call-process-signal + cc nil t nil "-fPIC" "-c" "-I." "scanner.c")) + ;; c++ -fPIC -I. -c scanner.cc + (when (file-exists-p "scanner.cc") + (treesit--call-process-signal + c++ nil t nil "-fPIC" "-c" "-I." "scanner.cc")) + ;; cc/c++ -fPIC -shared *.o -o "libtree-sitter-${lang}.${soext}" + (apply #'treesit--call-process-signal + (if (file-exists-p "scanner.cc") c++ cc) + nil t nil + (if (eq system-type 'cygwin) + `("-shared" "-Wl,-dynamicbase" + ,@(directory-files + default-directory nil + (rx bos (+ anychar) ".o" eos)) + "-o" ,lib-name) + `("-fPIC" "-shared" + ,@(directory-files + default-directory nil + (rx bos (+ anychar) ".o" eos)) + "-o" ,lib-name))) + ;; Copy out. + (unless (file-exists-p out-dir) + (make-directory out-dir t)) + (let* ((library-fname (expand-file-name lib-name out-dir)) + (old-fname (concat library-fname ".old"))) + ;; Rename the existing shared library, if any, then + ;; install the new one, and try deleting the old one. + ;; This is for Windows systems, where we cannot simply + ;; overwrite a DLL that is being used. + (if (file-exists-p library-fname) + (rename-file library-fname old-fname t)) + (copy-file lib-name (file-name-as-directory out-dir) t t) + ;; Ignore errors, in case the old version is still used. + (ignore-errors (delete-file old-fname))) + (message "Library installed to %s/%s" out-dir lib-name)))) + ;;; Shortdocs (defun treesit--generate-shortdoc-examples () commit a22730f4d788d6476d5f3c6717ba8a3d4046e819 Author: Yuan Fu Date: Sat Dec 28 13:57:50 2024 -0800 Support COMMIT in treesit-language-source-alist * lisp/treesit.el (treesit-language-source-alist): Add COMMIT field. (treesit--install-language-grammar-1): Support COMMIT. diff --git a/lisp/treesit.el b/lisp/treesit.el index 50e510fa7db..090197d86e3 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -4090,14 +4090,16 @@ window." The value should be an alist where each element has the form - (LANG . (URL REVISION SOURCE-DIR CC C++)) + (LANG . (URL REVISION SOURCE-DIR CC C++ COMMIT)) Only LANG and URL are mandatory. LANG is the language symbol. URL is the URL of the grammar's Git repository or a directory where the repository has been cloned. -REVISION is the Git tag or branch of the desired version, -defaulting to the latest default branch. +REVISION is the Git tag or branch of the desired version, defaulting to +the latest default branch. If COMMIT is non-nil, checkout this commit +hash after cloning the repo. COMMIT has precedence over REVISION if +both are non-nil. SOURCE-DIR is the relative subdirectory in the repository in which the grammar's parser.c file resides, defaulting to \"src\". @@ -4266,7 +4268,8 @@ REVISION may be nil, in which case the cloned repo will be at its default branch. Use shallow clone by default. Do a full clone when -`treesit--install-language-grammar-full-clone' is t." +`treesit--install-language-grammar-full-clone' is t. Do a blobless +clone if `treesit--install-language-grammar-blobless' is t." (message "Cloning repository") ;; git clone xxx --depth 1 --quiet [-b yyy] workdir (let ((args (list "git" nil t nil "clone" url "--quiet"))) @@ -4280,7 +4283,7 @@ Use shallow clone by default. Do a full clone when (apply #'treesit--call-process-signal args))) (defun treesit--install-language-grammar-1 - (out-dir lang url &optional revision source-dir cc c++) + (out-dir lang url &optional revision source-dir cc c++ commit) "Install and compile a tree-sitter language grammar library. OUT-DIR is the directory to put the compiled library file. If it @@ -4288,9 +4291,9 @@ is nil, the \"tree-sitter\" directory under user's Emacs configuration directory is used (and automatically created if it does not exist). -For LANG, URL, REVISION, SOURCE-DIR, GRAMMAR-DIR, CC, C++, see -`treesit-language-source-alist'. If anything goes wrong, this -function signals an error. +For LANG, URL, REVISION, SOURCE-DIR, GRAMMAR-DIR, CC, C++, COMMIT, see +`treesit-language-source-alist'. If anything goes wrong, this function +signals an error. Return the git revision of the installed grammar. The revision is generated by \"git describe\". It only works when @@ -4321,6 +4324,8 @@ generated by \"git describe\". It only works when (when revision (treesit--git-checkout-branch workdir revision)) (treesit--git-clone-repo url revision workdir)) + (when commit + (treesit--git-checkout-branch workdir commit)) ;; We need to go into the source directory because some ;; header files use relative path (#include "../xxx"). ;; cd "${sourcedir}"