From a1ab5f429daa7484874f9c76ecb9add7e93756e2 Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Fri, 28 Nov 2025 09:23:57 +0200 Subject: [PATCH] * lisp/cus-start.el: Make 'treesit-extra-load-path' customizable. * lisp/treesit.el (treesit-auto-install-grammar): Add the value 'ask-dir'. (treesit-ensure-installed): When 'treesit-auto-install-grammar' is 'ask' or 'ask-dir', ask for the directory to install the grammar library using the first writable directory of 'treesit-extra-load-path' as default. Also add the provided directory to 'treesit-extra-load-path' afterwards. * src/treesit.c (treesit-extra-load-path): In the docstring mention the fact that the first directory is special (bug#79862). --- etc/NEWS | 5 +++++ lisp/cus-start.el | 3 +++ lisp/treesit.el | 40 ++++++++++++++++++++++++++++++---------- src/treesit.c | 4 +++- 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 18b2be9cb8c..ef2c54efcde 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -924,6 +924,11 @@ It controls the automatic installation of tree-sitter grammar libraries needed for tree-sitter based modes, if these grammar libraries are not available when such modes are turned on. +*** 'treesit-extra-load-path' now is a customizable user option. +The first directory in the list is used as the default directory +to install the language grammar when 'treesit-auto-install-grammar' +is 'ask' or 'ask-dir'. + *** 'treesit-language-source-alist' supports keywords. The language and URL are mandatory, but remaining data can use keywords: '(json "https://github.com/tree-sitter/tree-sitter-json" :commit "4d770d3")'. diff --git a/lisp/cus-start.el b/lisp/cus-start.el index 19ac478e21a..b59decbc1a9 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -621,6 +621,9 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of (const :tag "Default" nil) (const :tag "Silent" ignore) function)) + ;; treesit.c + (treesit-extra-load-path + treesit (repeat (directory :format "%v"))) ;; undo.c (undo-limit undo integer "27.1") (undo-strong-limit undo integer "27.1") diff --git a/lisp/treesit.el b/lisp/treesit.el index e365fc218dd..b5cb01d03d3 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -5461,8 +5461,12 @@ The copied query files are queries/highlights.scm." "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 `ask', ask for confirmation before installing the required grammar library. +If `ask-dir', ask for confirmation and also for a directory name where +to install the grammar library. The directory name is also asked when +the value is `ask' and `treesit-extra-load-path' is customized to a list +of directories. 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." @@ -5470,7 +5474,9 @@ might display a warning and/or fail to turn on the mode." (const :tag "Always automatically install grammar libraries" always) (const :tag "Ask whether to install missing grammar libraries" - ask)) + ask) + (const :tag "Ask where to install missing grammar libraries" + ask-dir)) :version "31.1") (defun treesit-ensure-installed (lang) @@ -5479,14 +5485,28 @@ The option `treesit-auto-install-grammar' defines whether to install the grammar library if it's unavailable." (when (treesit-available-p) (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))))) + (let (out-dir) + (when (or (eq treesit-auto-install-grammar 'always) + (and (memq treesit-auto-install-grammar '(ask ask-dir)) + (y-or-n-p (format "\ +Tree-sitter grammar for `%s' is missing; install it?" lang)) + (or (and (eq treesit-auto-install-grammar 'ask) + ;; Still ask dir for customized path + (null treesit-extra-load-path)) + (let ((default-out-dir + (or (seq-find #'file-writable-p + treesit-extra-load-path) + (locate-user-emacs-file "tree-sitter")))) + (setq out-dir (read-directory-name + (format-prompt "\ +Install grammar for `%s' to" nil lang) + default-out-dir + treesit-extra-load-path t)) + (add-to-list 'treesit-extra-load-path out-dir) + t)))) + (treesit-install-language-grammar lang out-dir) + ;; Check that the grammar was installed successfully + (treesit-ready-p lang)))))) ;;; Treesit enabled modes diff --git a/src/treesit.c b/src/treesit.c index 3230d0a50a1..d3b6f36ec81 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -5273,7 +5273,9 @@ The value should be a list of directories. When trying to load a tree-sitter language definition, Emacs first looks in the directories mentioned in this variable, then in the `tree-sitter' subdirectory of `user-emacs-directory', and -then in the system default locations for dynamic libraries, in that order. */); +then in the system default locations for dynamic libraries, in that order. +The first writeable directory in the list is special: it's used as the +default directory when automatically installing the language grammar. */); Vtreesit_extra_load_path = Qnil; DEFVAR_LISP ("treesit-thing-settings",