From 8bc6e31502244ca16bbf7b163a7a321ec9094882 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Fri, 7 Oct 2022 01:21:09 -0700 Subject: [PATCH] Add a :toggle option for tree-sitter font-lock * admin/notes/tree-sitter/html-manual/Parser_002dbased-Font-Lock.html: Update html manual. * admin/notes/tree-sitter/html-manual/build-manual.sh: Fix manual path. * admin/notes/tree-sitter/starter-guide: Mention :toggle. * doc/lispref/modes.texi: Mention :toggle. * lisp/treesit.el (treesit-font-lock-settings): Update docstring. (treesit-font-lock-rules): Handle :toggle. Also change some wrong-type-argument signal to treesit-font-lock-error which is easier to understand. (treesit-font-lock-fontify-region): Handle :toggle. --- .../Parser_002dbased-Font-Lock.html | 2 + .../tree-sitter/html-manual/build-manual.sh | 2 +- admin/notes/tree-sitter/starter-guide | 20 ++++----- doc/lispref/modes.texi | 3 ++ lisp/treesit.el | 42 ++++++++++++++++--- 5 files changed, 52 insertions(+), 17 deletions(-) diff --git a/admin/notes/tree-sitter/html-manual/Parser_002dbased-Font-Lock.html b/admin/notes/tree-sitter/html-manual/Parser_002dbased-Font-Lock.html index ec89b7749c8..246ebf05193 100644 --- a/admin/notes/tree-sitter/html-manual/Parser_002dbased-Font-Lock.html +++ b/admin/notes/tree-sitter/html-manual/Parser_002dbased-Font-Lock.html @@ -115,6 +115,8 @@ every query must specify the language. Other keywords are optional: appendAppend the new face to existing ones prependPrepend the new face to existing ones keepFill-in regions without an existing face +:togglesymbolIf non-nil, its value should be a variable name. The variable’s value +(nil/non-nil) disables/enables the query during fontification.

Capture names in query should be face names like diff --git a/admin/notes/tree-sitter/html-manual/build-manual.sh b/admin/notes/tree-sitter/html-manual/build-manual.sh index adde3f2a2af..8d931b143b2 100755 --- a/admin/notes/tree-sitter/html-manual/build-manual.sh +++ b/admin/notes/tree-sitter/html-manual/build-manual.sh @@ -1,6 +1,6 @@ #!/bin/bash -MANUAL_DIR="../../../doc/lispref" +MANUAL_DIR="../../../../doc/lispref" THIS_DIR=$(pwd) echo "Build manual" diff --git a/admin/notes/tree-sitter/starter-guide b/admin/notes/tree-sitter/starter-guide index 6cf8cf8a236..129f9ee5fa4 100644 --- a/admin/notes/tree-sitter/starter-guide +++ b/admin/notes/tree-sitter/starter-guide @@ -238,22 +238,22 @@ You’ll notice that tree-sitter’s font-lock doesn’t respect ‘font-lock-maximum-decoration’, major modes are free to set ‘treesit-font-lock-settings’ based on the value of ‘font-lock-maximum-decoration’, or provide more fine-grained control -through other mode-specific means. +through other mode-specific means. (Towards that end, the :toggle option in treesit-font-lock-rules is very useful.) * Indent -Indent works like this: We have a bunch of rules that look like this: +Indent works like this: We have a bunch of rules that look like (MATCHER ANCHOR OFFSET) -At the beginning point is at the BOL of a line, we want to know which -column to indent this line to. Let NODE be the node at point, we pass -this node to the MATCHER of each rule, one of them will match the node -("this node is a closing bracket!"). Then we pass the node to the -ANCHOR, which returns a point, eg, the BOL of the previous line. We -find the column number of that point (eg, 4), add OFFSET to it (eg, -0), and that is the column we want to indent the current line to (4 + -0 = 4). +When the indentation process starts, point is at the BOL of a line, we +want to know which column to indent this line to. Let NODE be the node +at point, we pass this node to the MATCHER of each rule, one of them +will match the node (eg, "this node is a closing bracket!"). Then we pass +the node to the ANCHOR, which returns a point, eg, the BOL of the +previous line. We find the column number of that point (eg, 4), add +OFFSET to it (eg, 0), and that is the column we want to indent the +current line to (4 + 0 = 4). For MATHCER we have diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index 883f9d8491f..dcc0b2958d5 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -3932,6 +3932,9 @@ every query must specify the language. 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{:toggle} @tab @var{symbol} @tab +If non-nil, its value should be a variable name. The variable's value +(nil/non-nil) disables/enables the query during fontification. @end multitable Capture names in @var{query} should be face names like diff --git a/lisp/treesit.el b/lisp/treesit.el index bb13021a274..db96a899750 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -289,7 +289,7 @@ should always use `treesit-font-lock-rules' to set this variable. Each SETTING is of form - (LANGUAGE QUERY OVERRIDE) + (LANGUAGE QUERY OVERRIDE TOGGLE) Each SETTING controls one parser (often of different language). LANGUAGE is the language symbol. See Info node `(elisp)Language @@ -304,7 +304,11 @@ used over and over. 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'. + +TOGGLE should be a variable (symbol) or nil. The variable's +value (nil/non-nil) controls whether to activate the query during +fontification. If TOGGLE is nil, the query is always activated.") (defun treesit-font-lock-rules (&rest args) "Return a value suitable for `treesit-font-lock-settings'. @@ -320,6 +324,7 @@ configure the query (and only that query). For example, (treesit-font-lock-rules :language \\='javascript :override t + :enable 'html-fontify-script \\='((true) @font-lock-constant-face (false) @font-lock-constant-face) :language \\='html @@ -335,6 +340,10 @@ 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 + :toggle If non-nil, the value should be a variable. + The value of that variable (non-nil/nil) + activates/deactivates the query during + fontification. Capture names in QUERY should be face names like `font-lock-keyword-face'. The captured node will be fontified @@ -352,6 +361,8 @@ ignored. (current-language nil) ;; Tracks :override flag. (current-override nil) + ;; Track :toggle flag. + (current-toggle t) ;; The list this function returns. (result nil)) (while args @@ -360,15 +371,28 @@ ignored. (:language (let ((lang (pop args))) (when (or (not (symbolp lang)) (null lang)) - (signal 'wrong-type-argument `(symbolp ,lang))) + (signal 'treesit-font-lock-error + `("Value of :language should be a symbol" + ,lang))) (setq current-language lang))) (:override (let ((flag (pop args))) (when (not (memq flag '(t nil append prepend keep))) + (signal 'treesit-font-lock-error + `("Value of :override should be one of t, nil, append, prepend, keep" + ,flag)) (signal 'wrong-type-argument `((or t nil append prepend keep) ,flag))) (setq current-override flag))) + (:toggle + (let ((var (pop args))) + (when (or (not (symbolp var)) + (memq var '(t nil))) + (signal 'treesit-font-lock-error + `("Value of :toggle should be a variable name" + ,var))) + (setq current-toggle var))) ((pred treesit-query-p) (when (null current-language) (signal 'treesit-font-lock-error @@ -377,11 +401,13 @@ ignored. (push `(,current-language token) result) (push `(,current-language ,(treesit-query-compile current-language token) - ,current-override) + ,current-override + ,current-toggle) result)) ;; Clears any configurations set for this query. (setq current-language nil - current-override nil)) + current-override nil + current-toggle nil)) (_ (signal 'treesit-font-lock-error `("Unexpected value" token)))))) (nreverse result))) @@ -396,8 +422,12 @@ If LOUDLY is non-nil, message some debugging information." (let* ((language (nth 0 setting)) (match-pattern (nth 1 setting)) (override (nth 2 setting)) + (toggle (nth 3 setting)) (parser (treesit-parser-create language))) - (when-let ((node (treesit-node-on start end parser))) + (when-let ((node (treesit-node-on start end parser)) + (activate (or (null toggle) + (symbol-value toggle)))) + (ignore activate) (let ((captures (treesit-query-capture node match-pattern ;; Specifying the range is important. More -- 2.39.2