unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Theodor Thornhill via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
To: Eli Zaretskii <eliz@gnu.org>
Cc: 59691@debbugs.gnu.org, casouri@gmail.com,
	jostein@secure.kjonigsen.net, jostein@kjonigsen.net
Subject: bug#59691: 29.0.60; typescript-ts-mode: any HTML-like elements causes fontification to become invalid and remaining parse-tree to become jsx-expression
Date: Thu, 01 Dec 2022 11:52:00 +0100	[thread overview]
Message-ID: <87k03bz99r.fsf@thornhill.no> (raw)
In-Reply-To: <838rjrigmq.fsf@gnu.org>

[-- Attachment #1: Type: text/plain, Size: 1134 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Theodor Thornhill <theo@thornhill.no>
>> Cc: casouri@gmail.com, jostein@secure.kjonigsen.net, 59691@debbugs.gnu.org,
>>  jostein@kjonigsen.net
>> Date: Thu, 01 Dec 2022 09:12:58 +0100
>> 
>> > Looks like some "git merge" snafu?  You are in fact reverting a change I
>> > made in NEWS yesterday.
>> >
>> 
>> You're right - I think I fixed it now.
>
> Yes, thanks.
>
>> > I don't see a change to auto-mode-alist to turn on each mode for the files
>> > it supports?  I thought this was the idea?  Or is this because we don't want
>> > tree-sitter based modes to be turned on by default?  In that case, how do we
>> > explain to users that they should use each mode in the relevant cases?
>> 
>> I think there should be
>> 
>> 
>> ;;;###autoload
>> (add-to-list 'auto-mode-alist '("\\.ts\\'" . typescript-ts-mode))
>> 
>> ;;;###autoload
>> (add-to-list 'auto-mode-alist '("\\.tsx\\'" . tsx-ts-mode))
>
> Yes, I missed that, sorry.  But the NEWS entry should clearly say that one
> mode is the default for *.ts files, the other for *.tsx files.

No worries :)

Is this patch suitable?

Theo


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Add-new-TypeScript-mode-tsx-ts-mode.patch --]
[-- Type: text/x-diff, Size: 12323 bytes --]

From bef31846598dfce861a32abdb8cc34c884ce12cc Mon Sep 17 00:00:00 2001
From: Theodor Thornhill <theo@thornhill.no>
Date: Tue, 29 Nov 2022 21:39:38 +0100
Subject: [PATCH] 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-mode--base-mode): Parent mode for typescript-ts-mode
and tsx-ts-mode.
(typescript-ts-mode): Derive from typescript-ts-mode--base-mode and
extend with language specific settings
(tsx-ts-mode): New major mode that derives from
typescript-ts-mode--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 4e091a5fed..2c1c220f51 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2970,7 +2970,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..c1beaf3134 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 @@ typescript-ts-mode--syntax-table
     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 @@ typescript-ts-mode--indent-rules
      ((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-ts-mode--operators
     "&&" "||" "!" "?.")
   "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 @@ typescript-ts-mode--font-lock-settings
 
      [(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 @@ typescript-ts-mode--font-lock-settings
      (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 @@ typescript-ts-mode--font-lock-settings
              (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 @@ typescript-ts-mode--font-lock-settings
        (_ (_ (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 @@ typescript-ts-mode--font-lock-settings
        (member_expression
         property: (property_identifier) @font-lock-function-name-face)]))
 
-   :language 'tsx
+   :language language
    :override t
    :feature 'pattern
    `((pair_pattern
@@ -231,7 +238,7 @@ typescript-ts-mode--font-lock-settings
 
      (array_pattern (identifier) @font-lock-variable-name-face))
 
-   :language 'tsx
+   :language language
    :override t
    :feature 'jsx
    `((jsx_opening_element
@@ -248,31 +255,31 @@ typescript-ts-mode--font-lock-settings
 
      (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 @@ typescript-ts-mode--font-lock-settings
      ((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-mode--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
+              (rx (or "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-mode--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-mode--base-mode "TypeScript[TSX]"
   "Major mode for editing TypeScript."
   :group 'typescript
   :syntax-table typescript-ts-mode--syntax-table
@@ -301,43 +362,27 @@ typescript-ts-mode
     ;; 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
-- 
2.34.1


  reply	other threads:[~2022-12-01 10:52 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-29 20:02 bug#59691: 29.0.60; typescript-ts-mode: any HTML-like elements causes fontification to become invalid and remaining parse-tree to become jsx-expression Jostein Kjønigsen
2022-11-29 21:01 ` bug#59691: Html-like constructs fail in typescript Theodor Thornhill via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-29 21:37   ` Jostein Kjønigsen
2022-11-29 21:47     ` Theodor Thornhill via Bug reports for GNU Emacs, the Swiss army knife of text editors
     [not found]       ` <786DAB7F-F45D-405B-A4E5-4A60FD6CE7A7@secure.kjonigsen.net>
2022-11-30 12:59         ` Jostein Kjønigsen
2022-11-30 13:16           ` Theodor Thornhill via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-30 12:35   ` Eli Zaretskii
2022-11-30 13:00     ` Theodor Thornhill via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-30 14:25       ` Eli Zaretskii
2022-11-30 14:47         ` Theodor Thornhill via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-30 10:22 ` bug#59691: 29.0.60; typescript-ts-mode: any HTML-like elements causes fontification to become invalid and remaining parse-tree to become jsx-expression Yuan Fu
2022-11-30 14:09   ` Eli Zaretskii
2022-11-30 15:21     ` Theodor Thornhill via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-30 16:05       ` Eli Zaretskii
2022-11-30 18:10         ` Theodor Thornhill via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-30 18:19           ` Eli Zaretskii
2022-11-30 18:20             ` Theodor Thornhill via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-30 18:21             ` Theodor Thornhill via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-12-01  6:01               ` Theodor Thornhill via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-12-01  7:44                 ` Eli Zaretskii
2022-12-01  8:12                   ` Theodor Thornhill via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-12-01 10:05                     ` Eli Zaretskii
2022-12-01 10:52                       ` Theodor Thornhill via Bug reports for GNU Emacs, the Swiss army knife of text editors [this message]
2022-12-01 12:10                         ` Eli Zaretskii
2022-12-02  4:44                           ` Yuan Fu
2022-12-02 20:29                             ` Theodor Thornhill via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-12-02 21:28                               ` Jostein Kjønigsen
2022-12-02 22:54                                 ` Theodor Thornhill via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-12-03  6:38                                 ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87k03bz99r.fsf@thornhill.no \
    --to=bug-gnu-emacs@gnu.org \
    --cc=59691@debbugs.gnu.org \
    --cc=casouri@gmail.com \
    --cc=eliz@gnu.org \
    --cc=jostein@kjonigsen.net \
    --cc=jostein@secure.kjonigsen.net \
    --cc=theo@thornhill.no \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).