From 247f3fc16f33dafe3849384dbccc852ab2a38305 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Thu, 19 Dec 2024 19:02:59 -0800 Subject: [PATCH] Add keyword :reversed to treesit-font-lock-rules This keyword will be useful for implementing string-interpolation feature. * doc/lispref/modes.texi (Parser-based Font Lock): Document the new keyword. * lisp/treesit.el (treesit-font-lock-settings): Document. (treesit-font-lock-setting-reversed): New function. (treesit-font-lock-rules): Add new keyword. (treesit-font-lock-recompute-features): Handle new keyword. (cherry picked from commit 05ab13ebc7237bcf23bc84a6a345d0b563404c2d) --- doc/lispref/modes.texi | 6 +++++- lisp/treesit.el | 39 +++++++++++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index 6662da72d6d..6e44b9674c2 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -4342,6 +4342,8 @@ Other keywords are optional: @item @tab @code{append} @tab Append the new face to existing ones @item @tab @code{prepend} @tab Prepend the new face to existing ones @item @tab @code{keep} @tab Fill-in regions without an existing face +@item @code{:reversed} @tab @code{t} +@tab Enable @var{query} when @var{feature} is not in the feature list. @item @code{:default-language} @tab @var{language} @tab Every @var{query} after this keyword will use @var{language} by default. @@ -4425,6 +4427,7 @@ For this variable to take effect, a Lisp program should call @findex treesit-font-lock-setting-feature @findex treesit-font-lock-setting-enable @findex treesit-font-lock-setting-override +@findex treesit-font-lock-setting-reversed @defvar treesit-font-lock-settings A list of settings for tree-sitter based font lock. The exact format of each individual setting is considered internal. One should always use @@ -4435,7 +4438,8 @@ the setting's query, feature, enable flag and override flag: @code{treesit-font-lock-setting-query}, @code{treesit-font-lock-setting-feature}, @code{treesit-font-lock-setting-enable}, -@code{treesit-font-lock-setting-override}. +@code{treesit-font-lock-setting-override}, +@code{treesit-font-lock-setting-reversed}. @c Because the format is internal, we don't document them here. Though @c we do have it explained in the docstring. We also expose the fact diff --git a/lisp/treesit.el b/lisp/treesit.el index 0fa0862f441..98903dffa69 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -865,7 +865,7 @@ debugging: Currently each SETTING has the form: - (QUERY ENABLE FEATURE OVERRIDE) + (QUERY ENABLE FEATURE OVERRIDE REVERSE) QUERY must be a compiled query. See Info node `(elisp)Pattern Matching' for how to write a query and compile it. @@ -879,7 +879,10 @@ which features are enabled with `treesit-font-lock-level' and OVERRIDE is the override flag for this query. Its value can be t, nil, append, prepend, keep. See more in -`treesit-font-lock-rules'.") +`treesit-font-lock-rules'. + +If REVERSED is t, enable the QUERY when FEATURE is not in the feature +list.") ;; Follow cl-defstruct naming conventions, in case we use cl-defstruct ;; in the future. @@ -899,6 +902,10 @@ t, nil, append, prepend, keep. See more in "Return the OVERRIDE flag of SETTING in `treesit-font-lock-settings'." (nth 3 setting)) +(defsubst treesit-font-lock-setting-reversed (setting) + "Return the REVERSED flag of SETTING in `treesit-font-lock-settings'." + (nth 4 setting)) + (defsubst treesit--font-lock-setting-clone-enable (setting) "Return enabled SETTING." (let ((new-setting (copy-tree setting))) @@ -1029,6 +1036,8 @@ Other keywords include: `append' Append the new face to existing ones. `prepend' Prepend the new face to existing ones. `keep' Fill-in regions without an existing face. + :reversed t Enable the query only if the feature is + NOT in feature list. :default-language LANGUAGE Every QUERY after this keyword will use LANGUAGE by default. @@ -1063,6 +1072,7 @@ name, it is ignored." ;; DEFAULT-LANGUAGE will be chosen when current-language is ;; not set. default-language + current-reversed ;; The list this function returns. (result nil)) (while query-specs @@ -1098,6 +1108,13 @@ name, it is ignored." `("Value of :feature should be a symbol" ,var))) (setq current-feature var))) + (:reversed + (let ((var (pop query-specs))) + (when (not (memq var '(t nil))) + (signal 'treesit-font-lock-error + `("Value of :reversed can only be t or nil" + ,var))) + (setq current-reversed var))) ;; (2) Process query. ((pred treesit-query-p) (let ((lang (or default-language current-language))) @@ -1112,12 +1129,14 @@ name, it is ignored." (push `(,(treesit-query-compile lang token) t ,current-feature - ,current-override) + ,current-override + ,current-reversed) result)) ;; Clears any configurations set for this query. (setq current-language nil current-override nil - current-feature nil))) + current-feature nil + current-reversed nil))) (_ (signal 'treesit-font-lock-error `("Unexpected value" ,token)))))) (nreverse result)))) @@ -1186,9 +1205,11 @@ and leave settings for other languages unchanged." (additive (or add-list remove-list))) (cl-loop for idx = 0 then (1+ idx) for setting in treesit-font-lock-settings - for lang = (treesit-query-language (nth 0 setting)) - for feature = (nth 2 setting) - for current-value = (nth 1 setting) + for lang = (treesit-query-language + (treesit-font-lock-setting-query setting)) + for feature = (treesit-font-lock-setting-feature setting) + for current-value = (treesit-font-lock-setting-enable setting) + for reversed = (treesit-font-lock-setting-reversed setting) ;; Set the ENABLE flag for the setting if its language is ;; relevant. if (or (null language) @@ -1196,7 +1217,9 @@ and leave settings for other languages unchanged." do (setf (nth 1 (nth idx treesit-font-lock-settings)) (cond ((not additive) - (if (memq feature features) t nil)) + (if (not reversed) + (if (memq feature features) t nil) + (if (memq feature features) nil t))) ((memq feature add-list) t) ((memq feature remove-list) nil) (t current-value)))))) -- 2.39.5