summaryrefslogtreecommitdiff
path: root/init/treesit/init-treesit-setup-available-languages.el
blob: 9a256918d408198fce0e666138c3af600635b0ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
;; -*- lexical-binding: t; -*-

;; This script is a quick workaround for setting up treesitter modes.
;; Hopefully this won't be needed for long but it works for now!
;;
;; This just runs through the list of modes below, checks if the
;; required treesitter parsers are installed, and if so,
;; sets up auto-mode-alist and interpreter-mode-alist
;; to open the respective source files with the treesitter
;; mode for that language.
;;
;; To use, you should just add the modes and other info to the list
;; below, and then "require" this file in your init.
;; The messages that get generated by this script may be burried
;; by other startup messages, so it may not appear to have done
;; anything!
;;
;; To test if it works, visit a file such as "x.py", then run
;; "M-x describe-mode". There should be some info about
;; the current major mode that looks like this:
;;
;; "The major mode is Python mode defined in python.el:
;; Major mode for editing Python files, using tree-sitter library."

(defvar -quiet? nil
  "Suppress messages when setting up treesitter modes.")

(defvar -modes `((python-ts-mode
                  ((:parsers . python)
                   (:file-ext . ,(rx ".py"))
                   (:interpreters . ("python" "python3"))))
                 (rust-ts-mode 
                  ((:parsers . rust)
                   (:file-ext . ,(rx ".rs"))))
                 (bash-ts-mode
                  ((:parsers . bash)
                   (:file-ext . ,(rx ".sh"))
                   (:interpreters . ("bash" "sh" "openrc-run"))))
                 (c-ts-mode 
                  ((:parsers . c)
                   (:file-ext . ,(rx ".c"))))
                 (c++-ts-mode 
                  ((:parsers . cpp)
                   (:file-ext . ,(rx (or ".c++" ".cpp" ".cxx"
                                         ".h++" ".hpp" ".hxx")))))
                 (c-or-c++-ts-mode 
                  ((:parsers . (c c++))
                   (:file-ext . ,(rx ".h"))))
                 (toml-ts-mode 
                  ((:parsers . toml)
                   (:file-ext . ,(rx ".toml")))))
  "Treesitter modes and some information required to set them up.

Parsers are the treesitter packages that need to be installed to 
use the associated mode. python-ts-mode requires the python treesitter
parser package to be installed for example.

File extension is for example .py for python scripts. Some
modes like c++-ts-mode are associated with a few 
extensions, and c-or-c++-mode is associated with .h
because the extension is ambiguous.

Interpreters are used to associate certain shebangs with the treesitter
mode. Files that start with '#!/usr/bin/env python' for example will
be associated with python-ts-mode if 'python' is included in the 
interpreters list.")

(defun -ready-quiet? (parser)
  (treesit-ready-p parser t))

(cl-defun -setup-mode? (&key ts-mode
                             required-parsers
                             file-extensions
                             interpreters)
  (when (seq-every-p '-ready-quiet? (ensure-list required-parsers))    
    (add-to-list 'auto-mode-alist (cons file-extensions ts-mode))
    (when interpreters
      (seq-each (lambda (interpreter)
                  (add-to-list 'interpreter-mode-alist (cons interpreter ts-mode)))
                (ensure-list interpreters)))
    t))

(seq-each (lambda (mode)
            (when (and (-setup-mode?
                        :ts-mode (car mode)
                        :required-parsers (alist-get :parsers (cadr mode))
                        :file-extensions (alist-get :file-ext (cadr mode))
                        :interpreters (alist-get :interpreters (cadr mode)))
                       (not -quiet?))
              (message "Setup treesitter mode %s" (car mode))))
          -modes)

(provide 'init-treesit-setup-available-languages)

;; Local Variables:
;; read-symbol-shorthands: (("-" . "init-treesit-setup-available-languages-"))
;; End: