emacs-diffs
[Top][All Lists]
Advanced

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

emacs-29 d99b5151f8c: Add syntax-propertize-function to ruby-ts-mode


From: Dmitry Gutov
Subject: emacs-29 d99b5151f8c: Add syntax-propertize-function to ruby-ts-mode
Date: Fri, 3 Feb 2023 20:36:06 -0500 (EST)

branch: emacs-29
commit d99b5151f8c41d45084d10c49c86d6c228d5f730
Author: Dmitry Gutov <dgutov@yandex.ru>
Commit: Dmitry Gutov <dgutov@yandex.ru>

    Add syntax-propertize-function to ruby-ts-mode
    
    * lisp/progmodes/ruby-ts-mode.el (ruby-ts--s-p-query):
    New variable.
    (ruby-ts--syntax-propertize): New function.
    (ruby-ts--parser-after-change): New function.
    (ruby-ts-mode): Use both of them.
---
 lisp/progmodes/ruby-ts-mode.el | 85 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 84 insertions(+), 1 deletion(-)

diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el
index 7725d0824e3..02cc1aad5e6 100644
--- a/lisp/progmodes/ruby-ts-mode.el
+++ b/lisp/progmodes/ruby-ts-mode.el
@@ -95,6 +95,11 @@
 (declare-function treesit-node-end "treesit.c")
 (declare-function treesit-node-start "treesit.c")
 (declare-function treesit-node-string "treesit.c")
+(declare-function treesit-query-compile "treesit.c")
+(declare-function treesit-query-capture "treesit.c")
+(declare-function treesit-parser-add-notifier "treesit.c")
+(declare-function treesit-parser-buffer "treesit.c")
+(declare-function treesit-parser-list "treesit.c")
 
 (defgroup ruby-ts nil
   "Major mode for editing Ruby code."
@@ -1002,6 +1007,70 @@ leading double colon is not added."
         (concat result sep method-name)
       result)))
 
+(defvar ruby-ts--s-p-query
+  (when (treesit-available-p)
+    (treesit-query-compile 'ruby
+                           '(((heredoc_body) @heredoc)
+                             ;; $' $" $`.
+                             ((global_variable) @global_var
+                              (:match "\\`\\$[#\"'`:?]" @global_var))
+                             ;; ?' ?" ?` are character literals.
+                             ((character) @char
+                              (:match "\\`?[#\"'`:?]" @char))
+                             ;; Symbols like :+, :<=> or :foo=.
+                             ((simple_symbol) @symbol
+                              (:match "[[:punct:]]" @symbol))
+                             ;; Method calls with name ending with ? or !.
+                             ((call method: (identifier) @ident)
+                              (:match "[?!]\\'" @ident))
+                             ;; Backtick method redefinition.
+                             ((operator "`" @backtick))
+                             ;; TODO: Stop at interpolations.
+                             ((regex "/" @regex-slash))
+                             ;; =begin...=end
+                             ((comment) @comm
+                              (:match "\\`=" @comm))
+                             ;; Percent literals: %w[], %q{}, ...
+                             ((string) @percent
+                              (:match "\\`%" @percent))))))
+
+(defun ruby-ts--syntax-propertize (beg end)
+  (let ((captures (treesit-query-capture 'ruby ruby-ts--s-p-query beg end)))
+    (pcase-dolist (`(,name . ,node) captures)
+      (pcase name
+        ('regex_slash
+         (put-text-property (treesit-node-start node) (treesit-node-end node)
+                            'syntax-table (string-to-syntax "\"/")))
+        ('ident
+         (put-text-property (1- (treesit-node-end node)) (treesit-node-end 
node)
+                            'syntax-table (string-to-syntax "_")))
+        ('symbol
+         (put-text-property (1+ (treesit-node-start node)) (treesit-node-end 
node)
+                            'syntax-table (string-to-syntax "_")))
+        ('heredoc
+         (put-text-property (treesit-node-start node) (1+ (treesit-node-start 
node))
+                            'syntax-table (string-to-syntax "\""))
+         (put-text-property (1- (treesit-node-end node)) (treesit-node-end 
node)
+                            'syntax-table (string-to-syntax "\"")))
+        ('percent
+         (put-text-property (1+ (treesit-node-start node)) (+ 2 
(treesit-node-start node))
+                            'syntax-table (string-to-syntax "|"))
+         (put-text-property (1- (treesit-node-end node)) (treesit-node-end 
node)
+                            'syntax-table (string-to-syntax "|")))
+        ((or 'global_var 'char)
+         (put-text-property (treesit-node-start node) (1+ (treesit-node-start 
node))
+                            'syntax-table (string-to-syntax "'"))
+         (put-text-property (1+ (treesit-node-start node)) (treesit-node-end 
node)
+                            'syntax-table (string-to-syntax "_")))
+        ('backtick
+         (put-text-property (treesit-node-start node) (treesit-node-end node)
+                            'syntax-table (string-to-syntax "_")))
+        ('comm
+         (dolist (pos (list (treesit-node-start node)
+                            (1- (treesit-node-end node))))
+           (put-text-property pos (1+ pos) 'syntax-table
+                              (string-to-syntax "!"))))))))
+
 (defvar-keymap ruby-ts-mode-map
   :doc "Keymap used in Ruby mode"
   :parent prog-mode-map
@@ -1049,7 +1118,21 @@ leading double colon is not added."
                   interpolation literal symbol assignment)
                 ( bracket error function operator punctuation)))
 
-  (treesit-major-mode-setup))
+  (treesit-major-mode-setup)
+
+  (treesit-parser-add-notifier (car (treesit-parser-list))
+                               #'ruby-ts--parser-after-change)
+
+  (setq-local syntax-propertize-function #'ruby-ts--syntax-propertize))
+
+(defun ruby-ts--parser-after-change (ranges parser)
+  ;; Make sure we re-syntax-propertize the full node that is being
+  ;; edited.  This is most pertinent to multi-line complex nodes such
+  ;; as heredocs.
+  (when ranges
+    (with-current-buffer (treesit-parser-buffer parser)
+      (syntax-ppss-flush-cache (cl-loop for r in ranges
+                                        minimize (car r))))))
 
 (if (treesit-ready-p 'ruby)
     ;; Copied from ruby-mode.el.



reply via email to

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