]> git.eshelyaron.com Git - emacs.git/commitdiff
Install new toggle scheme for tree-sitter
authorYuan Fu <casouri@gmail.com>
Tue, 18 Oct 2022 20:06:25 +0000 (13:06 -0700)
committerYuan Fu <casouri@gmail.com>
Tue, 18 Oct 2022 20:17:12 +0000 (13:17 -0700)
Basically we now have treesit-mode and global-treesit-mode.  Major
modes set major-mode-backend-function which treesit-mode calls to
activate/deactivate tree-sitter.

js.el needs a bit explanation: I'm so sorry for messing up the
history, but basically now js-mode and js-json-mode should be exactly
the same as before any tree-sitter change was introduced, sans some
initialization code that are moved to js(-json)--backend-toggle.
js-mode and js-json-mode now just sets major-mode-backend-function and
initialize with js(-json)--backend-toggle.

* lisp/treesit.el (treesit-mode-inhibit-message): New option.
(treesit-can-enable-p): Remove function.
(major-mode-backend-function)
(treesit-remapped-major-mode-alist): New variables.
(treesit-mode)
(global-treesit-mode): New minor modes.
(global-treesit-mode--turn-on)
(treesit-ready-p): New functions.

* lisp/progmodes/python.el: Remove option.
(python--backend-toggle): New function.
(python-mode): Remove the if-form, all the initialization code are
moved to python--backend-toggle, python-mode now just sets
major-mode-backend-function and initialize with
python--backend-toggle.
* lisp/progmodes/js.el (js--treesit-can-enable-p)
(js--json-treesit-can-enable-p)
(js--treesit-enable)
(js--json-treesit-enable): Remove functions.
(js--backend-toggle)
(js-json--backend-toggle): New function.

* lisp/progmodes/ts-mode.el (ts-mode): Use treesit-ready-p.

lisp/progmodes/js.el
lisp/progmodes/python.el
lisp/progmodes/ts-mode.el
lisp/treesit.el

index 667416852ef3bfb7fe0cd6838f134b297d18bf97..51f5b720479f7dabb7dd9943de1363fda666e16e 100644 (file)
@@ -3639,28 +3639,39 @@ ARG is the same as in `end-of-defun."
                    js--treesit-defun-type-regexp 'end))
         (setq arg (1- arg))))))
 
-(defun js--treesit-can-enable-p ()
-  (if (and js-use-tree-sitter
-           (treesit-can-enable-p)
-           (treesit-language-available-p 'javascript))
-      t
-    (message "Cannot enable Tree Sitter for JavaScript.")
-    nil))
+(defun js--backend-toggle (backend warn)
+  "Toggle backend for `js-mode'.
+For BACKEND and WARN see `treesit-mode-function'."
+  (cond
+   ;; Tree-sitter.
+   ((and (eq backend 'treesit) (treesit-ready-p warn 'javascript))
+    (setq-local treesit-simple-indent-rules js--treesit-indent-rules)
+    (setq-local indent-line-function #'treesit-indent)
 
-(defun js--treesit-enable ()
-  (setq-local treesit-simple-indent-rules js--treesit-indent-rules)
-  (setq-local indent-line-function #'treesit-indent)
+    (setq-local beginning-of-defun-function #'js--treesit-beginning-of-defun)
+    (setq-local end-of-defun-function #'js--treesit-end-of-defun)
 
-  (setq-local beginning-of-defun-function #'js--treesit-beginning-of-defun)
-  (setq-local end-of-defun-function #'js--treesit-end-of-defun)
+    (setq-local font-lock-keywords-only t)
+    (setq-local treesit-font-lock-settings js--treesit-settings)
+    (setq-local treesit-font-lock-feature-list '((basic)))
 
-  (setq-local font-lock-keywords-only t)
-  (setq-local treesit-font-lock-settings js--treesit-settings)
-  (setq-local treesit-font-lock-feature-list '((basic)))
+    (add-hook 'which-func-functions #'js-treesit-current-defun nil t)
 
-  (add-hook 'which-func-functions #'js-treesit-current-defun nil t)
+    (treesit-font-lock-enable))
+   ;; Elisp.
+   ((eq backend 'elisp)
+    (setq-local indent-line-function #'js-indent-line)
+    (setq-local beginning-of-defun-function #'js-beginning-of-defun)
+    (setq-local end-of-defun-function #'js-end-of-defun)
 
-  (treesit-font-lock-enable))
+    (setq-local font-lock-defaults
+                (list js--font-lock-keywords nil nil nil nil
+                      '(font-lock-syntactic-face-function
+                        . js-font-lock-syntactic-face-function)))
+
+    ;; Imenu
+    (setq imenu-case-fold-search nil)
+    (setq imenu-create-index-function #'js--imenu-create-index))))
 
 ;;; Main Function
 
@@ -3668,98 +3679,79 @@ ARG is the same as in `end-of-defun."
 (define-derived-mode js-mode prog-mode "JavaScript"
   "Major mode for editing JavaScript."
   :group 'js
+  ;; Ensure all CC Mode "lang variables" are set to valid values.
+  (c-init-language-vars js-mode)
+  (setq-local open-paren-in-column-0-is-defun-start nil)
+  (setq-local syntax-propertize-function #'js-syntax-propertize)
+  (add-hook 'syntax-propertize-extend-region-functions
+            #'syntax-propertize-multiline 'append 'local)
+  (add-hook 'syntax-propertize-extend-region-functions
+            #'js--syntax-propertize-extend-region 'append 'local)
+  (setq-local prettify-symbols-alist js--prettify-symbols-alist)
+
+  (setq-local parse-sexp-ignore-comments t)
+  (setq-local which-func-imenu-joiner-function #'js--which-func-joiner)
+
   ;; Comments
   (setq-local comment-start "// ")
   (setq-local comment-start-skip "\\(?://+\\|/\\*+\\)\\s *")
   (setq-local comment-end "")
 
-  (if (js--treesit-can-enable-p)
-      (js--treesit-enable)
-    ;; Ensure all CC Mode "lang variables" are set to valid values.
-    (c-init-language-vars js-mode)
-    (setq-local indent-line-function #'js-indent-line)
-    (setq-local beginning-of-defun-function #'js-beginning-of-defun)
-    (setq-local end-of-defun-function #'js-end-of-defun)
-    (setq-local open-paren-in-column-0-is-defun-start nil)
-    (setq-local font-lock-defaults
-                (list js--font-lock-keywords nil nil nil nil
-                      '(font-lock-syntactic-face-function
-                        . js-font-lock-syntactic-face-function)))
-    (setq-local syntax-propertize-function #'js-syntax-propertize)
-    (add-hook 'syntax-propertize-extend-region-functions
-              #'syntax-propertize-multiline 'append 'local)
-    (add-hook 'syntax-propertize-extend-region-functions
-              #'js--syntax-propertize-extend-region 'append 'local)
-    (setq-local prettify-symbols-alist js--prettify-symbols-alist)
-
-    (setq-local parse-sexp-ignore-comments t)
-    (setq-local which-func-imenu-joiner-function #'js--which-func-joiner)
-
-    (setq-local fill-paragraph-function #'js-fill-paragraph)
-    (setq-local normal-auto-fill-function #'js-do-auto-fill)
-
-    ;; Parse cache
-    (add-hook 'before-change-functions #'js--flush-caches t t)
-
-    ;; Frameworks
-    (js--update-quick-match-re)
-
-    ;; Syntax extensions
-    (unless (js-jsx--detect-and-enable)
-      (add-hook 'after-change-functions #'js-jsx--detect-after-change nil t))
-    (js-use-syntactic-mode-name)
-
-    ;; Imenu
-    (setq imenu-case-fold-search nil)
-    (setq imenu-create-index-function #'js--imenu-create-index)
-
-    ;; for filling, pretend we're cc-mode
-    (c-foreign-init-lit-pos-cache)
-    (add-hook 'before-change-functions #'c-foreign-truncate-lit-pos-cache nil t)
-    (setq-local comment-line-break-function #'c-indent-new-comment-line)
-    (setq-local comment-multi-line t)
-    (setq-local electric-indent-chars
-               (append "{}():;," electric-indent-chars)) ;FIXME: js2-mode adds "[]*".
-    (setq-local electric-layout-rules
-               '((?\; . after) (?\{ . after) (?\} . before)))
-
-    (let ((c-buffer-is-cc-mode t))
-      ;; FIXME: These are normally set by `c-basic-common-init'.  Should
-      ;; we call it instead?  (Bug#6071)
-      (make-local-variable 'paragraph-start)
-      (make-local-variable 'paragraph-separate)
-      (make-local-variable 'paragraph-ignore-fill-prefix)
-      (make-local-variable 'adaptive-fill-mode)
-      (make-local-variable 'adaptive-fill-regexp)
-      ;; While the full CC Mode style system is not yet in use, set the
-      ;; pertinent style variables manually.
-      (c-initialize-builtin-style)
-      (let ((style (cc-choose-style-for-mode 'js-mode c-default-style)))
-        (c-set-style style))
-      (setq c-block-comment-prefix "* "
-            c-comment-prefix-regexp "//+\\|\\**")
-      (c-setup-paragraph-variables))
-
-    ;; Important to fontify the whole buffer syntactically! If we don't,
-    ;; then we might have regular expression literals that aren't marked
-    ;; as strings, which will screw up parse-partial-sexp, scan-lists,
-    ;; etc. and produce maddening "unbalanced parenthesis" errors.
-    ;; When we attempt to find the error and scroll to the portion of
-    ;; the buffer containing the problem, JIT-lock will apply the
-    ;; correct syntax to the regular expression literal and the problem
-    ;; will mysteriously disappear.
-    ;; FIXME: We should instead do this fontification lazily by adding
-    ;; calls to syntax-propertize wherever it's really needed.
-    ;;(syntax-propertize (point-max))
-    ))
-
-(defcustom js-json-use-tree-sitter nil
-  "If non-nil, `js-json-mode' tries to use tree-sitter.
-Currently `js-json-mode' uses tree-sitter for font-locking and
-indentation."
-  :version "29.1"
-  :type 'boolean
-  :safe 'booleanp)
+  ;; Parse cache
+  (add-hook 'before-change-functions #'js--flush-caches t t)
+
+  ;; Frameworks
+  (js--update-quick-match-re)
+
+  ;; Syntax extensions
+  (unless (js-jsx--detect-and-enable)
+    (add-hook 'after-change-functions #'js-jsx--detect-after-change nil t))
+  (js-use-syntactic-mode-name)
+
+  ;; for filling, pretend we're cc-mode
+  (c-foreign-init-lit-pos-cache)
+  (add-hook 'before-change-functions #'c-foreign-truncate-lit-pos-cache nil t)
+  (setq-local comment-line-break-function #'c-indent-new-comment-line)
+  (setq-local comment-multi-line t)
+  (setq-local electric-indent-chars
+             (append "{}():;," electric-indent-chars)) ;FIXME: js2-mode adds "[]*".
+  (setq-local electric-layout-rules
+             '((?\; . after) (?\{ . after) (?\} . before)))
+
+  (setq-local fill-paragraph-function #'js-fill-paragraph)
+  (setq-local normal-auto-fill-function #'js-do-auto-fill)
+
+  (let ((c-buffer-is-cc-mode t))
+    ;; FIXME: These are normally set by `c-basic-common-init'.  Should
+    ;; we call it instead?  (Bug#6071)
+    (make-local-variable 'paragraph-start)
+    (make-local-variable 'paragraph-separate)
+    (make-local-variable 'paragraph-ignore-fill-prefix)
+    (make-local-variable 'adaptive-fill-mode)
+    (make-local-variable 'adaptive-fill-regexp)
+    ;; While the full CC Mode style system is not yet in use, set the
+    ;; pertinent style variables manually.
+    (c-initialize-builtin-style)
+    (let ((style (cc-choose-style-for-mode 'js-mode c-default-style)))
+      (c-set-style style))
+    (setq c-block-comment-prefix "* "
+          c-comment-prefix-regexp "//+\\|\\**")
+    (c-setup-paragraph-variables))
+
+  ;; Important to fontify the whole buffer syntactically! If we don't,
+  ;; then we might have regular expression literals that aren't marked
+  ;; as strings, which will screw up parse-partial-sexp, scan-lists,
+  ;; etc. and produce maddening "unbalanced parenthesis" errors.
+  ;; When we attempt to find the error and scroll to the portion of
+  ;; the buffer containing the problem, JIT-lock will apply the
+  ;; correct syntax to the regular expression literal and the problem
+  ;; will mysteriously disappear.
+  ;; FIXME: We should instead do this fontification lazily by adding
+  ;; calls to syntax-propertize wherever it's really needed.
+  ;; (syntax-propertize (point-max))
+
+  (js--backend-toggle 'elisp nil)
+  (setq-local major-mode-backend-function #'js--backend-toggle))
 
 (defvar js--json-treesit-settings
   (treesit-font-lock-rules
@@ -3791,37 +3783,29 @@ indentation."
      ((parent-is "object") parent-bol ,js-indent-level)
      )))
 
-
-(defun js--json-treesit-can-enable-p ()
-  (if (and js-json-use-tree-sitter
-           (treesit-can-enable-p)
-           (treesit-language-available-p 'json))
-      t
-    (error "Cannot enable Tree Sitter for JSON.")
-    nil))
-
-
-(defun js--json-treesit-enable ()
-  (setq-local treesit-simple-indent-rules js--json-treesit-indent-rules)
-  (setq-local indent-line-function #'treesit-indent)
-
-  (setq-local beginning-of-defun-function #'ignore)
-  (setq-local end-of-defun-function #'ignore)
-
-  (setq-local font-lock-defaults '(nil t))
-  (setq-local treesit-font-lock-settings js--json-treesit-settings)
-
-  (treesit-font-lock-enable))
-
+(defun js--json-backend-toggle (backend warn)
+  "Toggle backend for `json-mode'.
+For BACKEND and WARN see `treesit-mode-function'."
+  (cond
+   ;; Tree-sitter.
+   ((and (eq backend 'treesit) (treesit-ready-p warn 'json))
+    (setq-local treesit-simple-indent-rules js--json-treesit-indent-rules)
+    (setq-local indent-line-function #'treesit-indent)
+
+    (setq-local font-lock-keywords-only t)
+    (setq-local treesit-font-lock-settings js--json-treesit-settings)
+    (treesit-font-lock-enable))
+   ;; Elisp.
+   ((eq backend 'elisp)
+    (js--backend-toggle 'elisp nil))))
 
 ;;;###autoload
 (define-derived-mode js-json-mode js-mode "JSON"
-  (if (js--json-treesit-can-enable-p)
-      (js--json-treesit-enable)
-    (setq-local js-enabled-frameworks nil)
-    ;; Speed up `syntax-ppss': JSON files can be big but can't hold
-    ;; regexp matchers nor #! thingies (and `js-enabled-frameworks' is nil).
-    (setq-local syntax-propertize-function #'ignore)))
+  (setq-local js-enabled-frameworks nil)
+  ;; Speed up `syntax-ppss': JSON files can be big but can't hold
+  ;; regexp matchers nor #! thingies (and `js-enabled-frameworks' is nil).
+  (setq-local syntax-propertize-function #'ignore)
+  (setq-local major-mode-backend-function #'js--json-backend-toggle))
 
 ;; Since we made JSX support available and automatically-enabled in
 ;; the base `js-mode' (for ease of use), now `js-jsx-mode' simply
@@ -3848,11 +3832,9 @@ could set `js-jsx-syntax' to t in your init file, or in a
 `js-jsx-enable' in `js-mode-hook'.  You may be better served by
 one of the aforementioned options instead of using this mode."
   :group 'js
-  (if (js--treesit-can-enable-p)
-      (js--treesit-enable)
-    (js-jsx-enable)
-    (setq-local comment-region-function #'js-jsx--comment-region)
-    (js-use-syntactic-mode-name)))
+  (js-jsx-enable)
+  (setq-local comment-region-function #'js-jsx--comment-region)
+  (js-use-syntactic-mode-name))
 
 (defun js-jsx--comment-region (beg end &optional arg)
   (if (or (js-jsx--context)
index c48f9e95e98232541f3a0eef46441ba9d8442203..374bc02a78c0a034332aac8a801de9f9cb22d0fa 100644 (file)
   :version "24.3"
   :link '(emacs-commentary-link "python"))
 
-(defcustom python-use-tree-sitter nil
-  "If non-nil, `python-mode' tries to use tree-sitter.
-Currently `python-mode' uses tree-sitter for font-locking, imenu,
-and movement functions."
-  :type 'boolean
-  :version "29.1")
-
 (defcustom python-interpreter "python"
   "Python interpreter for noninteractive use.
 To customize the Python shell, modify `python-shell-interpreter'
@@ -6382,6 +6375,32 @@ Add import for undefined name `%s' (empty to skip): "
 (defvar electric-indent-inhibit)
 (defvar prettify-symbols-alist)
 
+(defun python--backend-toggle (backend warn)
+  "Toggle backend for `python-mode'.
+BACKEND and WARN are explained in `treesit-mode-function'."
+  (if (and (eq backend 'treesit) (treesit-ready-p warn 'python))
+      (progn
+        (setq-local font-lock-keywords-only t)
+        (setq-local treesit-font-lock-feature-list
+                    '((basic) (moderate) (elaborate)))
+        (setq-local treesit-font-lock-settings
+                    python--treesit-settings)
+        (treesit-font-lock-enable)
+        (setq-local imenu-create-index-function
+                    #'python-imenu-treesit-create-index)
+        (add-hook 'which-func-functions
+                  #'python-info-treesit-current-defun nil t))
+    (setq-local font-lock-defaults
+                `(,python-font-lock-keywords
+                  nil nil nil nil
+                  (font-lock-syntactic-face-function
+                   . python-font-lock-syntactic-face-function)
+                  (font-lock-extend-after-change-region-function
+                   . python-font-lock-extend-region)))
+    (setq-local imenu-create-index-function
+                #'python-imenu-create-index)
+    (add-hook 'which-func-functions #'python-info-current-defun nil t)))
+
 ;;;###autoload
 (define-derived-mode python-mode prog-mode "Python"
   "Major mode for editing Python files.
@@ -6398,22 +6417,9 @@ Add import for undefined name `%s' (empty to skip): "
 
   (setq-local forward-sexp-function python-forward-sexp-function)
 
-  (if (and python-use-tree-sitter
-           (treesit-can-enable-p))
-      (progn
-        (setq-local font-lock-keywords-only t)
-        (setq-local treesit-font-lock-feature-list
-                    '((basic) (moderate) (elaborate)))
-        (setq-local treesit-font-lock-settings
-                    python--treesit-settings)
-        (treesit-font-lock-enable))
-    (setq-local font-lock-defaults
-              `(,python-font-lock-keywords
-                nil nil nil nil
-                (font-lock-syntactic-face-function
-                 . python-font-lock-syntactic-face-function)
-                (font-lock-extend-after-change-region-function
-                 . python-font-lock-extend-region))))
+  (python--backend-toggle 'elisp nil)
+
+  (setq-local major-mode-backend-function #'python--backend-toggle)
 
   (setq-local syntax-propertize-function
               python-syntax-propertize-function)
@@ -6442,22 +6448,9 @@ Add import for undefined name `%s' (empty to skip): "
   (add-hook 'post-self-insert-hook
             #'python-indent-post-self-insert-function 'append 'local)
 
-  (if (and python-use-tree-sitter
-           (treesit-can-enable-p))
-      (setq-local imenu-create-index-function
-                  #'python-imenu-treesit-create-index)
-    (setq-local imenu-create-index-function
-                #'python-imenu-create-index))
-
   (setq-local add-log-current-defun-function
               #'python-info-current-defun)
 
-  (if (and python-use-tree-sitter
-           (treesit-can-enable-p))
-      (add-hook 'which-func-functions
-                #'python-info-treesit-current-defun nil t)
-    (add-hook 'which-func-functions #'python-info-current-defun nil t))
-
   (setq-local skeleton-further-elements
               '((abbrev-mode nil)
                 (< '(backward-delete-char-untabify (min python-indent-offset
index 6e4aeebde87c29cb8ffbdbe7c7ed3f5c4d8f642b..dffe9fcfcf292d121558c5b7b608266531398a83 100644 (file)
@@ -338,8 +338,7 @@ ARG is the same as in `end-of-defun."
   :syntax-table ts-mode--syntax-table
 
   (cond
-   ((and (treesit-can-enable-p)
-         (treesit-language-available-p 'tsx))
+   ((treesit-ready-p nil 'tsx)
     ;; Comments
     (setq-local comment-start "// ")
     (setq-local comment-start-skip "\\(?://+\\|/\\*+\\)\\s *")
@@ -351,15 +350,13 @@ ARG is the same as in `end-of-defun."
     (setq-local beginning-of-defun-function #'ts-mode--beginning-of-defun)
     (setq-local end-of-defun-function #'ts-mode--end-of-defun)
 
-    (unless font-lock-defaults
-      (setq font-lock-defaults '(nil t)))
-
+    (setq font-lock-keywords-only t)
     (setq-local treesit-font-lock-settings ts-mode--settings)
 
     (setq treesit-font-lock-feature-list '((basic)))
     (treesit-font-lock-enable))
    (t
-    (message "Tree sitter for TypeScript isn't available, defaulting to js-mode")
+    (message "Tree-sitter for TypeScript isn't available, falling back to `js-mode'")
     (js-mode))))
 
 (provide 'ts-mode)
index 86da9e158664d9ce07257cabfb2210f4c5ad3306..91ffb1eff15cf08da81b39b34d8c20be2eb0fd44 100644 (file)
   :type 'integer
   :version "29.1")
 
+(defcustom treesit-mode-inhibit-message nil
+  "If non-nil, don't print message when tree-sitter can't activate."
+  :type 'boolean
+  :version "29.1")
+
 (declare-function treesit-available-p "treesit.c")
 
-(defun treesit-can-enable-p ()
-  "Return non-nil if current buffer can activate tree-sitter.
-Currently this function checks whether tree-sitter is available
-and the buffer size."
-  (and (treesit-available-p)
-       (< (buffer-size) treesit-max-buffer-size)))
+(defvar-local major-mode-backend-function nil
+  "A function that toggles the \"backend\" for a major mode.
+
+The function is passed two argument BACKEND and WARN.  BACKEND is
+a symbol representing the backend we want to activate.  Currently
+it can be `treesit' or `elisp'.
+
+If WARN is non-nil, display a warning if tree-sitter can't
+activate, if WARN is nil, just print an message and don't display
+warning.")
+
+;;;###autoload
+(define-minor-mode treesit-mode
+  "Activate tree-sitter to power major-mode features.
+
+This mode is merely a SUGGESTION of turning on tree-sitter,
+actual activation of tree-sitter functionalities depends on
+whether the major mode supports tree-sitter, availability of
+specific tree-sitter language definition, etc."
+  :version "29.1"
+  :group 'languages
+  (when major-mode-backend-function
+    (funcall major-mode-backend-function
+             (if treesit-mode 'treesit 'elisp)
+             (eq this-command 'treesit-mode))))
+
+(defvar treesit-remapped-major-mode-alist nil
+  "A list like `major-mode-remap-alist'.
+
+When major modes activate tree-sitter by switching to another
+major mode and `global-treesit-mode' is on, they add an
+entry (MODE . NEW-MODE) to `major-mode-remap-alist', so next time
+Emacs uses NEW-MODE directly.
+
+These remaps should be removed when `global-treesit-mode' is
+turned off, so we record each (MODE . NEW-MODE) in this variable.")
+
+;;;###autoload
+(define-globalized-minor-mode global-treesit-mode treesit-mode
+  global-treesit-mode--turn-on
+  :group 'languages
+  :predicate t
+  (when (not global-treesit-mode)
+    (dolist (map treesit-remapped-major-mode-alist)
+      (setq major-mode-remap-alist
+            (remove map major-mode-remap-alist)))))
+
+(defun global-treesit-mode--turn-on ()
+  "Function used to determine whether to turn on `treesit-mode'.
+Called in every buffer if `global-treesit-mode' is on."
+  (treesit-mode))
+
+(defun treesit-ready-p (warn &rest languages)
+  "Check that tree-sitter is ready to be used.
+
+If tree-sitter is not ready and WARN is nil-nil, emit a warning;
+if WARN is nil, print a message.  But if
+`treesit-mode-inhibit-message' is non-nil, don't even print the
+message.
+
+LANGUAGES are languages we want check for availability."
+  (let (msg)
+    ;; Check for each condition and set MSG.
+    (catch 'term
+      (when (not (treesit-available-p))
+        (setq msg "tree-sitter library is not built with Emacs")
+        (throw 'term nil))
+      (when (> (buffer-size) treesit-max-buffer-size)
+        (setq msg "buffer larger than `treesit-max-buffer-size'")
+        (throw 'term nil))
+      (dolist (lang languages)
+        (pcase-let ((`(,available . ,err)
+                     (treesit-language-available-p lang t)))
+          (when (not available)
+            (setq msg (format "language definition for %s is unavailable (%s): %s"
+                              lang (nth 0 err)
+                              (string-join
+                               (mapcar (lambda (x) (format "%s" x))
+                                       (cdr err))
+                               " ")))
+            (throw 'term nil)))))
+    ;; Decide if all conditions met and whether emit a warning.
+    (if (not msg)
+        t
+      (setq msg (concat "Cannot activate tree-sitter, because " msg))
+      (if warn
+          (display-warning 'treesit msg)
+        (unless treesit-mode-inhibit-message
+          (message "%s" msg)))
+      nil)))
 
 ;;; Parser API supplement