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.
This commit is contained in:
Dmitry Gutov 2023-02-04 03:34:22 +02:00
parent f25c15ceb7
commit d99b5151f8

View file

@ -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.