Tree Sitter, change loaded parser

I was wondering if anyone else has tried to do this. I recently started working in a project that uses JS Flow. Since flow syntax is quite similar to typescript, I was hoping I could load the typescript parser instead of the javascript one if flow-minor-mode is active. Only problem, not sure how to do it. I’ve been playing around with the value of tree-sitter-lang but it doesn’t seem to do much. Anybody else can think of a way? Or if there is an alternative better solution please tell me.

Edit: While writing this post I came around this:

(defun tree-sitter--setup ()
  "Enable `tree-sitter' in the current buffer."
  (unless tree-sitter-language
    ;; Determine the language symbol based on `major-mode' .
    (let ((lang-symbol (alist-get major-mode tree-sitter-major-mode-language-alist)))
      (unless lang-symbol
        (error "No language registered for major mode `%s'" major-mode))
      (setq tree-sitter-language (tree-sitter-require lang-symbol))))
  (unless tree-sitter-parser
    (setq tree-sitter-parser (tsc-make-parser))
    (tsc-set-language tree-sitter-parser tree-sitter-language))
  (add-hook 'before-change-functions #'tree-sitter--before-change :append :local)
  (add-hook 'after-change-functions #'tree-sitter--after-change :append :local))

Seems like modifying tree-sitter-major-mode-language-alist is the way to go, maybe I’ll make a derived major mode for flow files and register it to use typescript. I’ll update the post when I try that with the results.

Creating a derived major mode is the way to go in this case, you can do it pretty simply in fact.

first we define the derived mode

(define-derived-mode flow-mode rjsx-mode "Flow")

replace rjsx-mode with the major-mode you use to edit flow

then it would be as simple as adding that to the language alists

(after! evil-textobj-tree-sitter
  (pushnew! evil-textobj-tree-sitter-major-mode-language-alist '(flow-mode . "typescript")))

(after! tree-sitter
   (pushnew! tree-sitter-major-mode-language-alist '(flow-mode . typescript)))

Then its just a matter of registering flow-mode with the file extension in the auto-mode-alist and your good to go!

This is very similar to the way doom handles typescript-tsx-mode but deriving from web-mode instead of a javascript mode

Note this can also be generalised to other languages and syntaxes, For example I have this for scss files.

(after! tree-sitter
  (pushnew! tree-sitter-major-mode-language-alist
            '(scss-mode . css)))

(after! evil-textobj-tree-sitter
  (pushnew! evil-textobj-tree-sitter-major-mode-language-alist
            '(scss-mode . "css")))