summaryrefslogtreecommitdiff
path: root/lisp/progmodes/ruby-ts-mode.el
diff options
context:
space:
mode:
authorDmitry Gutov <dgutov@yandex.ru>2023-02-04 03:34:22 +0200
committerDmitry Gutov <dgutov@yandex.ru>2023-02-04 03:34:40 +0200
commitd99b5151f8c41d45084d10c49c86d6c228d5f730 (patch)
tree4ccad20c50882534a861ceb56c77904ea32c70f8 /lisp/progmodes/ruby-ts-mode.el
parentf25c15ceb7d9b26cc8b93648730571187ef36c85 (diff)
downloademacs-d99b5151f8c41d45084d10c49c86d6c228d5f730.tar.gz
emacs-d99b5151f8c41d45084d10c49c86d6c228d5f730.tar.bz2
emacs-d99b5151f8c41d45084d10c49c86d6c228d5f730.zip
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.
Diffstat (limited to 'lisp/progmodes/ruby-ts-mode.el')
-rw-r--r--lisp/progmodes/ruby-ts-mode.el85
1 files changed, 84 insertions, 1 deletions
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.