emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

emacs-29 1aa1f8432b 1/2: Add new TypeScript mode tsx-ts-mode


From: Yuan Fu
Subject: emacs-29 1aa1f8432b 1/2: Add new TypeScript mode tsx-ts-mode
Date: Thu, 1 Dec 2022 23:44:25 -0500 (EST)

branch: emacs-29
commit 1aa1f8432b085305f0f46c42a9054987ac9afc2a
Author: Theodor Thornhill <theo@thornhill.no>
Commit: Yuan Fu <casouri@gmail.com>

    Add new TypeScript mode tsx-ts-mode
    
    There are in fact two languages supporting TypeScript for tree-sitter.
    Because TSX causes some ambiguities with types there are two grammars,
    one called typescript and one called tsx.  To account for this and to
    be as correct as possible we enable using both.
    
    * lisp/progmodes/typescript-ts-mode.el
    (typescript-ts-mode--indent-rules): Change to a function to accomodate
    the two languages.
    (typescript-ts-mode--font-lock-settings): Change to a function to
    accomodate the two languages.
    (typescript-ts-base-mode): Parent mode for typescript-ts-mode
    and tsx-ts-mode.
    (typescript-ts-mode): Derive from typescript-ts-base-mode and
    extend with language specific settings
    (tsx-ts-mode): New major mode that derives from
    typescript-ts-base-mode and extend it with language specific
    settings
    
    Add autoload cookies for the respective file type extensions: .ts and
    .tsx.
    
    * etc/NEWS: Mention the new mode.
---
 etc/NEWS                             |   9 +-
 lisp/progmodes/typescript-ts-mode.el | 155 ++++++++++++++++++++++-------------
 2 files changed, 108 insertions(+), 56 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 547b488a57..d38ccadba6 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2989,7 +2989,14 @@ when visiting JSON files.
 ** New major mode 'typescript-ts-mode'.
 A major mode based on the tree-sitter library for editing programs
 in the TypeScript language.  It includes support for font-locking,
-indentation, and navigation.
+indentation, and navigation.  This mode will be auto-enabled for
+files with the '.ts' extension.
+
+** New major mode 'tsx-ts-mode'.
+A major mode based on the tree-sitter library for editing programs
+in the TypeScript language, with support for TSX.  It includes
+support for font-locking, indentation, and navigation.  This mode
+will be auto-enabled for files with the '.tsx' extension.
 
 ** New major mode 'c-ts-mode'.
 A major mode based on the tree-sitter library for editing programs
diff --git a/lisp/progmodes/typescript-ts-mode.el 
b/lisp/progmodes/typescript-ts-mode.el
index 6c926a4e3e..e09bacdcb1 100644
--- a/lisp/progmodes/typescript-ts-mode.el
+++ b/lisp/progmodes/typescript-ts-mode.el
@@ -22,6 +22,10 @@
 ;; You should have received a copy of the GNU General Public License
 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+
+;;; Commentary:
+;;
+
 ;;; Code:
 
 (require 'treesit)
@@ -56,8 +60,10 @@
     table)
   "Syntax table for `typescript-ts-mode'.")
 
-(defvar typescript-ts-mode--indent-rules
-  `((tsx
+(defun typescript-ts-mode--indent-rules (language)
+  "Rules used for indentation.
+Argument LANGUAGE is either `typescript' or `tsx'."
+  `((,language
      ((parent-is "program") parent-bol 0)
      ((node-is "}") parent-bol 0)
      ((node-is ")") parent-bol 0)
@@ -82,14 +88,13 @@
      ((parent-is "arrow_function") parent-bol typescript-ts-mode-indent-offset)
      ((parent-is "parenthesized_expression") parent-bol 
typescript-ts-mode-indent-offset)
 
-     ;; TSX
-     ((parent-is "jsx_opening_element") parent 
typescript-ts-mode-indent-offset)
-     ((node-is "jsx_closing_element") parent 0)
-     ((parent-is "jsx_element") parent typescript-ts-mode-indent-offset)
-     ((node-is "/") parent 0)
-     ((parent-is "jsx_self_closing_element") parent 
typescript-ts-mode-indent-offset)
-     (no-node parent-bol 0)))
-  "Tree-sitter indent rules.")
+     ,@(when (eq language 'tsx)
+         `(((parent-is "jsx_opening_element") parent 
typescript-ts-mode-indent-offset)
+           ((node-is "jsx_closing_element") parent 0)
+           ((parent-is "jsx_element") parent typescript-ts-mode-indent-offset)
+           ((node-is "/") parent 0)
+           ((parent-is "jsx_self_closing_element") parent 
typescript-ts-mode-indent-offset)))
+     (no-node parent-bol 0))))
 
 (defvar typescript-ts-mode--keywords
   '("!" "abstract" "as" "async" "await" "break"
@@ -110,14 +115,16 @@
     "&&" "||" "!" "?.")
   "TypeScript operators for tree-sitter font-locking.")
 
-(defvar typescript-ts-mode--font-lock-settings
+(defun typescript-ts-mode--font-lock-settings (language)
+  "Tree-sitter font-lock settings.
+Argument LANGUAGE is either `typescript' or `tsx'."
   (treesit-font-lock-rules
-   :language 'tsx
+   :language language
    :override t
    :feature 'comment
    `((comment) @font-lock-comment-face)
 
-   :language 'tsx
+   :language language
    :override t
    :feature 'constant
    `(((identifier) @font-lock-constant-face
@@ -125,13 +132,13 @@
 
      [(true) (false) (null)] @font-lock-constant-face)
 
-   :language 'tsx
+   :language language
    :override t
    :feature 'keyword
    `([,@typescript-ts-mode--keywords] @font-lock-keyword-face
      [(this) (super)] @font-lock-keyword-face)
 
-   :language 'tsx
+   :language language
    :override t
    :feature 'string
    `((regex pattern: (regex_pattern)) @font-lock-string-face
@@ -139,7 +146,7 @@
      (template_string) @js--fontify-template-string
      (template_substitution ["${" "}"] @font-lock-builtin-face))
 
-   :language 'tsx
+   :language language
    :override t
    :feature 'declaration
    `((function
@@ -177,7 +184,7 @@
              (identifier) @font-lock-function-name-face)
       value: (array (number) (function))))
 
-   :language 'tsx
+   :language language
    :override t
    :feature 'identifier
    `((nested_type_identifier
@@ -208,7 +215,7 @@
        (_ (_ (identifier) @font-lock-variable-name-face))
        (_ (_ (_ (identifier) @font-lock-variable-name-face)))]))
 
-   :language 'tsx
+   :language language
    :override t
    :feature 'expression
    '((assignment_expression
@@ -223,7 +230,7 @@
        (member_expression
         property: (property_identifier) @font-lock-function-name-face)]))
 
-   :language 'tsx
+   :language language
    :override t
    :feature 'pattern
    `((pair_pattern
@@ -231,7 +238,7 @@
 
      (array_pattern (identifier) @font-lock-variable-name-face))
 
-   :language 'tsx
+   :language language
    :override t
    :feature 'jsx
    `((jsx_opening_element
@@ -248,31 +255,31 @@
 
      (jsx_attribute (property_identifier) @font-lock-constant-face))
 
-   :language 'tsx
+   :language language
    :feature 'number
    `((number) @font-lock-number-face
      ((identifier) @font-lock-number-face
       (:match "^\\(:?NaN\\|Infinity\\)$" @font-lock-number-face)))
 
-   :language 'tsx
+   :language language
    :feature 'operator
    `([,@typescript-ts-mode--operators] @font-lock-operator-face
      (ternary_expression ["?" ":"] @font-lock-operator-face))
 
-   :language 'tsx
+   :language language
    :feature 'bracket
    '((["(" ")" "[" "]" "{" "}"]) @font-lock-bracket-face)
 
-   :language 'tsx
+   :language language
    :feature 'delimiter
    '((["," "." ";" ":"]) @font-lock-delimiter-face)
 
-   :language 'tsx
+   :language language
    :feature 'escape-sequence
    :override t
    '((escape_sequence) @font-lock-escape-face)
 
-   :language 'tsx
+   :language language
    :override t
    :feature 'property
    `((pair value: (identifier) @font-lock-variable-name-face)
@@ -280,17 +287,71 @@
      ((shorthand_property_identifier) @font-lock-property-face)
 
      ((shorthand_property_identifier_pattern)
-      @font-lock-property-face)))
-  "Tree-sitter font-lock settings.")
+      @font-lock-property-face))))
 
 ;;;###autoload
 (add-to-list 'auto-mode-alist '("\\.ts\\'" . typescript-ts-mode))
 
 ;;;###autoload
-(add-to-list 'auto-mode-alist '("\\.tsx\\'" . typescript-ts-mode))
+(add-to-list 'auto-mode-alist '("\\.tsx\\'" . tsx-ts-mode))
 
 ;;;###autoload
-(define-derived-mode typescript-ts-mode prog-mode "TypeScript"
+(define-derived-mode typescript-ts-base-mode prog-mode "TypeScript"
+  "Major mode for editing TypeScript."
+  :group 'typescript
+  :syntax-table typescript-ts-mode--syntax-table
+
+  ;; Comments.
+  (setq-local comment-start "// ")
+  (setq-local comment-end "")
+  (setq-local comment-start-skip "\\(?://+\\|/\\*+\\)\\s *")
+  (setq-local comment-end-skip
+              (rx (* (syntax whitespace))
+                  (group (or (syntax comment-end)
+                             (seq (+ "*") "/")))))
+
+  ;; Electric
+  (setq-local electric-indent-chars
+              (append "{}():;," electric-indent-chars))
+
+  ;; Navigation.
+  (setq-local treesit-defun-type-regexp
+              (regexp-opt '("class_declaration"
+                            "method_definition"
+                            "function_declaration"
+                            "lexical_declaration")))
+  ;; Imenu.
+  (setq-local imenu-create-index-function #'js--treesit-imenu)
+
+  ;; Which-func (use imenu).
+  (setq-local which-func-functions nil))
+
+;;;###autoload
+(define-derived-mode typescript-ts-mode typescript-ts-base-mode "TypeScript"
+  "Major mode for editing TypeScript."
+  :group 'typescript
+  :syntax-table typescript-ts-mode--syntax-table
+
+  (when (treesit-ready-p 'typescript)
+    (treesit-parser-create 'typescript)
+
+    ;; Indent.
+    (setq-local treesit-simple-indent-rules
+                (typescript-ts-mode--indent-rules 'typescript))
+
+    ;; Font-lock.
+    (setq-local treesit-font-lock-settings
+                (typescript-ts-mode--font-lock-settings 'typescript))
+    (setq-local treesit-font-lock-feature-list
+                '((comment declaration)
+                  (keyword string)
+                  (constant expression identifier number pattern property)
+                  (bracket delimiter)))
+
+    (treesit-major-mode-setup)))
+
+;;;###autoload
+(define-derived-mode tsx-ts-mode typescript-ts-base-mode "TypeScript[TSX]"
   "Major mode for editing TypeScript."
   :group 'typescript
   :syntax-table typescript-ts-mode--syntax-table
@@ -301,43 +362,27 @@
     ;; Comments.
     (setq-local comment-start "// ")
     (setq-local comment-end "")
-    (setq-local comment-start-skip (rx (group "/" (or (+ "/") (+ "*")))
-                                       (* (syntax whitespace))))
+    (setq-local comment-start-skip "\\(?://+\\|/\\*+\\)\\s *")
     (setq-local comment-end-skip
                 (rx (* (syntax whitespace))
                     (group (or (syntax comment-end)
                                (seq (+ "*") "/")))))
 
-    ;; Electric
-    (setq-local electric-indent-chars
-                (append "{}():;," electric-indent-chars))
-
     ;; Indent.
-    (setq-local treesit-simple-indent-rules typescript-ts-mode--indent-rules)
-
-    ;; Navigation.
-    (setq-local treesit-defun-type-regexp
-                (rx (or "class_declaration"
-                        "method_definition"
-                        "function_declaration"
-                        "lexical_declaration")))
+    (setq-local treesit-simple-indent-rules
+                (typescript-ts-mode--indent-rules 'tsx))
 
     ;; Font-lock.
-    (setq-local treesit-font-lock-settings 
typescript-ts-mode--font-lock-settings)
+    (setq-local treesit-font-lock-settings
+                (typescript-ts-mode--font-lock-settings 'tsx))
     (setq-local treesit-font-lock-feature-list
-                '(( comment declaration)
-                  ( keyword string)
-                  ( constant expression identifier jsx number pattern property)
-                  ( bracket delimiter)))
-    ;; Imenu.
-    (setq-local imenu-create-index-function #'js--treesit-imenu)
-
-    ;; Which-func (use imenu).
-    (setq-local which-func-functions nil)
+                '((comment declaration)
+                  (keyword string)
+                  (constant expression identifier jsx number pattern property)
+                  (bracket delimiter)))
 
     (treesit-major-mode-setup)))
 
-
 (provide 'typescript-ts-mode)
 
 ;;; typescript-ts-mode.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]