1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-06 06:20:55 -08:00

New treesit generic mode 'liquid-generic-ts-mode' (bug#77255)

* lisp/treesit.el (treesit-replace-font-lock-feature-settings):
Check the query language in addition to checking the feature.
(treesit-font-lock-fontify-region): Use treesit-font-lock-setting-*
accessors.

* lisp/treesit-x.el (treesit-generic-mode-setup): Append new
font-lock rules to an existing treesit-font-lock-settings
possibly inherited from the parent.
(treesit-generic-mode-setup): Use treesit-merge-font-lock-feature-list
to merge with an existing feature list inherited from the parent.
(liquid-generic-ts-mode): New treesit generic mode.
(alpinejs-generic-ts-setup): New treesit generic setup.
This commit is contained in:
Juri Linkov 2025-04-01 20:17:17 +03:00
parent 883355cef7
commit 87da719b6c
2 changed files with 128 additions and 14 deletions

View file

@ -147,11 +147,15 @@ of `define-treesit-generic-mode'.
(when-let* ((query (treesit-generic-mode-font-lock-query lang)))
(setq-local treesit-font-lock-settings
(treesit-font-lock-rules
:language lang
:feature 'highlights
query))
(setq-local treesit-font-lock-feature-list '((highlights))))))
(append treesit-font-lock-settings
(treesit-font-lock-rules
:language lang
:feature 'highlights
query)))
(setq-local treesit-font-lock-feature-list
(treesit-merge-font-lock-feature-list
treesit-font-lock-feature-list
'((highlights)))))))
;;; Generic font-lock handling
@ -202,6 +206,112 @@ of `define-treesit-generic-mode'.
(setq-local comment-start "# ")
(setq-local comment-end ""))
(define-treesit-generic-mode liquid-generic-ts-mode
"Tree-sitter generic mode for Liquid templates."
:lang 'liquid
:source "https://github.com/hankthetank27/tree-sitter-liquid"
:auto-mode "\\.liquid\\'"
:name "Liquid"
:parent mhtml-ts-mode
(setq-local treesit-range-settings
(append treesit-range-settings
(treesit-range-rules
:embed 'html
:host 'liquid
'(((template_content) @cap)))))
(setq-local treesit-thing-settings
(append treesit-thing-settings
`((liquid (sexp (not ,(rx bos "program" eos)))
(list ,(rx bos (or "range"
"if_statement"
"for_loop_statement"
"case_statement"
"unless_statement"
"capture_statement"
"form_statement"
"tablerow_statement"
"paginate_statement")
eos))))))
(setq-local treesit-aggregated-outline-predicate
(append treesit-aggregated-outline-predicate
`((liquid . ,(rx bos (or "if_statement"
"for_loop_statement")
eos)))))
(when (treesit-ready-p 'yaml t)
(defvar yaml-ts-mode--font-lock-settings)
(require 'yaml-ts-mode)
(setq-local treesit-range-settings
(append treesit-range-settings
(treesit-range-rules
:embed 'yaml
:host 'liquid
:local t
'(((front_matter) @cap)))))
(setq-local treesit-font-lock-settings
(append treesit-font-lock-settings
yaml-ts-mode--font-lock-settings))))
(defvar alpinejs-generic-ts-attr-regexp
(rx bos (or "x-" ":" "@"))
"Regexp for HTML attributes handled by Alpine.js")
(defun alpinejs-generic-ts-attr-not-match (node)
(not (string-match-p alpinejs-generic-ts-attr-regexp
(treesit-node-text node t))))
(defun alpinejs-generic-ts-setup ()
"Tree-sitter generic setup for Alpine.js framework.
It uses JavaScript highlighting inside a limited set of HTML attributes.
Intended to be used in combination with such major modes as
`mhtml-ts-mode' and `liquid-generic-ts-mode'. For example:
\(add-hook \\='mhtml-ts-mode-hook \\='alpinejs-generic-ts-setup)
\(add-hook \\='liquid-generic-ts-mode-hook \\='alpinejs-generic-ts-setup)"
;; Use JavaScript highlighting for Alpinejs HTML attributes
(setq-local treesit-range-settings
(append treesit-range-settings
(treesit-range-rules
:embed 'javascript
:host 'html
:local t
`((attribute
(attribute_name) @_name
(:match ,alpinejs-generic-ts-attr-regexp @_name)
(quoted_attribute_value
(attribute_value) @cap))))))
;; Highlight only non-Alpinejs HTML attributes
(setq-local treesit-font-lock-settings
(treesit-replace-font-lock-feature-settings
(treesit-font-lock-rules
:language 'html
:override t
:feature 'string
`((attribute
(attribute_name) @_name
(:pred alpinejs-generic-ts-attr-not-match @_name)
(quoted_attribute_value) @font-lock-string-face)))
treesit-font-lock-settings))
;; Highlight only quotes for Alpinejs HTML attributes
(setq-local treesit-font-lock-settings
(append treesit-font-lock-settings
(treesit-font-lock-rules
:language 'html
:override t
:feature 'string
`((attribute
(attribute_name) @_name
(:match ,alpinejs-generic-ts-attr-regexp @_name)
(quoted_attribute_value "\"" @font-lock-string-face))))))
(treesit-major-mode-setup))
(provide 'treesit-x)
;;; treesit-x.el ends here

View file

@ -1636,12 +1636,16 @@ Both SETTINGS and NEW-SETTINGS must be a value suitable for
Return a value suitable for `treesit-font-lock-settings'"
(let ((result nil))
(dolist (new-setting new-settings)
(let ((new-feature (treesit-font-lock-setting-feature new-setting)))
(dolist (setting settings)
(let ((feature (treesit-font-lock-setting-feature setting)))
(if (eq new-feature feature)
(push new-setting result)
(push setting result))))))
(let ((new-feature (treesit-font-lock-setting-feature new-setting))
(new-lang (treesit-query-language
(treesit-font-lock-setting-query new-setting))))
(dolist (setting settings)
(let ((feature (treesit-font-lock-setting-feature setting))
(lang (treesit-query-language
(treesit-font-lock-setting-query setting))))
(if (and (eq new-lang lang) (eq new-feature feature))
(push new-setting result)
(push setting result))))))
(nreverse result)))
(defun treesit-add-font-lock-rules (rules &optional how feature)
@ -1881,9 +1885,9 @@ If LOUDLY is non-nil, display some debugging information."
;; 1ms in xdisp.c, and 0.3ms in a small C file (for typing a single
;; character), not worth it. --yuan
(dolist (setting treesit-font-lock-settings)
(let* ((query (nth 0 setting))
(enable (nth 1 setting))
(override (nth 3 setting))
(let* ((query (treesit-font-lock-setting-query setting))
(enable (treesit-font-lock-setting-enable setting))
(override (treesit-font-lock-setting-override setting))
(language (treesit-query-language query))
(root-nodes (cl-remove-if-not
(lambda (node)