Skip to content

Commit 087e220

Browse files
committed
Initial commit of typescript-tree-sitter-mode
1 parent be4eea8 commit 087e220

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed

typescript-tree-sitter.el

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
;;; typescript-tree-sitter.el --- tree sitter support for Typescript -*- lexical-binding: t; -*-
2+
3+
;; Copyright (C) Theodor Thornhill
4+
5+
;; Author : Theodor Thornhill <[email protected]>
6+
;; Maintainer : Jostein Kjønigsen <[email protected]>
7+
;; Theodor Thornhill <[email protected]>
8+
;; Created : April 2022
9+
;; Modified : 2022
10+
;; Version : 0.4
11+
;; Keywords : typescript languages
12+
;; X-URL : https://github.com/emacs-typescript/typescript.el
13+
;; Package-Requires: ((emacs "26.1") (tree-sitter "0.12.1") (tree-sitter-indent "0.1") (tree-sitter-langs "0.9.1"))
14+
15+
;; This program is free software; you can redistribute it and/or modify
16+
;; it under the terms of the GNU General Public License as published by
17+
;; the Free Software Foundation, either version 3 of the License, or
18+
;; (at your option) any later version.
19+
20+
;; This program is distributed in the hope that it will be useful,
21+
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22+
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23+
;; GNU General Public License for more details.
24+
25+
;; You should have received a copy of the GNU General Public License
26+
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
27+
28+
29+
;;; Code:
30+
(require 'cl-lib)
31+
(require 'cl-extra)
32+
(require 'seq)
33+
34+
(when t
35+
;; In order for the package to be usable and installable (and hence
36+
;; compilable) without tree-sitter, wrap the `require's within a dummy `when'
37+
;; so they're only executed when loading this file but not when compiling it.
38+
(require 'tree-sitter)
39+
(require 'tree-sitter-hl)
40+
(require 'tree-sitter-indent)
41+
(require 'tree-sitter-langs))
42+
;; Vars and functions defined by the above packages:
43+
(defvar tree-sitter-major-mode-language-alist) ;From `tree-sitter-langs'.
44+
(declare-function tree-sitter-indent-mode "ext:tree-sitter-indent")
45+
(declare-function tree-sitter-indent-line "ext:tree-sitter-indent")
46+
(declare-function tree-sitter-hl-mode "ext:tree-sitter-hl")
47+
(declare-function tsc-node-end-position "ext:tree-sitter")
48+
(declare-function tsc-node-start-position "ext:tree-sitter")
49+
50+
(defvar typescript-tree-sitter-syntax-table)
51+
(defvar typescript-tree-sitter-map)
52+
53+
;;; Tree-sitter indentation
54+
55+
(defgroup typescript-tree-sitter-indent nil "Indent lines using Tree-sitter as backend"
56+
:group 'tree-sitter)
57+
58+
(defcustom typescript-tree-sitter-indent-offset 2
59+
"Indent offset for typescript-tree-sitter-mode."
60+
:type 'integer
61+
:group 'typescript)
62+
63+
(defvar tree-sitter-indent-typescript-tree-sitter-scopes
64+
'((indent-all
65+
;; these nodes are always indented
66+
. ("."))
67+
(indent-rest
68+
;; if parent node is one of these and node is not first → indent
69+
. ())
70+
(indent-body
71+
;; if parent node is one of these and current node is in middle → indent
72+
. (statement_block
73+
array_pattern
74+
arguments
75+
parenthesized_expression
76+
jsx_element
77+
jsx_self_closing_element
78+
jsx_opening_element))
79+
(paren-indent
80+
;; if parent node is one of these → indent to paren opener
81+
. ())
82+
(align-char-to
83+
;; chaining char → node types we move parentwise to find the first chaining char
84+
. ())
85+
(aligned-siblings
86+
;; siblings (nodes with same parent) should be aligned to the first child
87+
. ())
88+
(multi-line-text
89+
;; if node is one of these, then don't modify the indent
90+
;; this is basically a peaceful way out by saying "this looks like something
91+
;; that cannot be indented using AST, so best I leave it as-is"
92+
. ())
93+
(outdent
94+
;; these nodes always outdent (1 shift in opposite direction)
95+
. ())
96+
(align-to-node-line
97+
;; this group has lists of alist (node type . (node types... ))
98+
;; we move parentwise, searching for one of the node
99+
;; types associated with the key node type. if found,
100+
;; align key node with line where the ancestor node
101+
;; was found.
102+
. ()))
103+
"Scopes for indenting Typescript.")
104+
105+
(defvar typescript-tree-sitter-mode-map
106+
(let ((map (make-sparse-keymap)))
107+
map)
108+
"Keymap used in typescript-tree-sitter buffers.")
109+
110+
(defvar typescript-tree-sitter-mode-syntax-table
111+
(let ((table (make-syntax-table)))
112+
(modify-syntax-entry ?@ "_" table)
113+
table))
114+
115+
;;;###autoload
116+
(define-derived-mode typescript-tree-sitter-mode prog-mode "Typescript"
117+
"Major mode for editing Typescript code.
118+
119+
Key bindings:
120+
\\{typescript-tree-sitter-mode-map}"
121+
:group 'typescript
122+
:syntax-table typescript-tree-sitter-mode-syntax-table
123+
124+
(setq-local indent-line-function #'tree-sitter-indent-line)
125+
;; (setq-local beginning-of-defun-function #'typescript-beginning-of-defun)
126+
;; (setq-local end-of-defun-function #'typescript-end-of-defun)
127+
128+
;; https://github.com/ubolonton/emacs-tree-sitter/issues/84
129+
(unless font-lock-defaults
130+
(setq font-lock-defaults '(nil)))
131+
132+
;; Comments
133+
(setq-local comment-start "// ")
134+
(setq-local comment-start-skip "\\(?://+\\|/\\*+\\)\\s *")
135+
(setq-local comment-end "")
136+
137+
(tree-sitter-hl-mode)
138+
(tree-sitter-indent-mode))
139+
140+
(add-to-list 'tree-sitter-major-mode-language-alist '(typescript-tree-sitter-mode . tsx))
141+
142+
(provide 'typescript-tree-sitter)
143+
144+
;;; typescript-tree-sitter.el ends here

0 commit comments

Comments
 (0)