emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/tree-sitter c88a1631e3 2/3: Make tree-sitter font-lock support d


From: Yuan Fu
Subject: feature/tree-sitter c88a1631e3 2/3: Make tree-sitter font-lock support decoration levels
Date: Sun, 9 Oct 2022 20:21:01 -0400 (EDT)

branch: feature/tree-sitter
commit c88a1631e3f76926bf0fed49fa1b704d6eaf2155
Author: Yuan Fu <casouri@gmail.com>
Commit: Yuan Fu <casouri@gmail.com>

    Make tree-sitter font-lock support decoration levels
    
    * admin/notes/tree-sitter/html-manual/Parser_002dbased-Font-Lock.html:
    Update.
    * admin/notes/tree-sitter/html-manual/Parsing-Program-Source.html:
    Update.
    * doc/lispref/modes.texi: Mention the new :level option.
    * lisp/treesit.el (treesit-font-lock-settings): Update docstring.
    (treesit-font-lock-rules): Support :level.  Relayout the let form.
    (treesit-font-lock-fontify-region): Support :level.
---
 .../html-manual/Parser_002dbased-Font-Lock.html    |  9 ++++
 .../html-manual/Parsing-Program-Source.html        |  4 ++
 doc/lispref/modes.texi                             | 10 ++++
 lisp/treesit.el                                    | 57 +++++++++++++++++-----
 4 files changed, 67 insertions(+), 13 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 246ebf0519..c91152edc0 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
@@ -117,8 +117,17 @@ every query must specify the language.  Other keywords are 
optional:
 <tr><td width="15%"></td><td width="15%"><code>keep</code></td><td 
width="60%">Fill-in regions without an existing face</td></tr>
 <tr><td width="15%"><code>:toggle</code></td><td 
width="15%"><var>symbol</var></td><td width="60%">If non-nil, its value should 
be a variable name.  The variable&rsquo;s value
 (nil/non-nil) disables/enables the query during fontification.</td></tr>
+<tr><td width="15%"></td><td width="15%">nil</td><td width="60%">Always enable 
this query.</td></tr>
+<tr><td width="15%"><code>:level</code></td><td 
width="15%"><var>integer</var></td><td width="60%">If non-nil, its value should 
be the decoration level for this query.
+Decoration level is controlled by 
<code>font-lock-maximum-decoration</code>.</td></tr>
+<tr><td width="15%"></td><td width="15%">nil</td><td width="60%">Always enable 
this query.</td></tr>
 </table>
 
+<p>Note that a query is applied only when both <code>:toggle</code> and
+<code>:level</code> permit it.  <code>:level</code> is used for global,
+coarse-grained control, whereas <code>:toggle</code> is for local,
+fine-grained control.
+</p>
 <p>Capture names in <var>query</var> should be face names like
 <code>font-lock-keyword-face</code>.  The captured node will be fontified
 with that face.  Capture names can also be function names, in which
diff --git a/admin/notes/tree-sitter/html-manual/Parsing-Program-Source.html 
b/admin/notes/tree-sitter/html-manual/Parsing-Program-Source.html
index 7b6e51468a..81b42f7f52 100644
--- a/admin/notes/tree-sitter/html-manual/Parsing-Program-Source.html
+++ b/admin/notes/tree-sitter/html-manual/Parsing-Program-Source.html
@@ -94,6 +94,10 @@ for this Emacs instance.
 see <a href="Parser_002dbased-Font-Lock.html">Parser-based Font Lock</a>, <a 
href="Parser_002dbased-Indentation.html">Parser-based Indentation</a>, and
 <a href="List-Motion.html">Moving over Balanced Expressions</a>.
 </p>
+<p>About naming convention: use &ldquo;tree-sitter&rdquo; when referring to it 
as a
+noun, like <code>python-use-tree-sitter</code>, but use &ldquo;treesit&rdquo; 
for
+prefixes, like <code>python-treesit-indent-function</code>.
+</p>
 <p>To access the syntax tree of the text in a buffer, we need to first
 load a language definition and create a parser with it.  Next, we can
 query the parser for specific nodes in the syntax tree.  Then, we can
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index dcc0b2958d..b1287c6ad0 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -3935,8 +3935,18 @@ every query must specify the language.  Other keywords 
are optional:
 @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.
+@item @tab nil @tab Always enable this query.
+@item @code{:level} @tab @var{integer} @tab
+If non-nil, its value should be the decoration level for this query.
+Decoration level is controlled by @code{font-lock-maximum-decoration}.
+@item @tab nil @tab Always enable this query.
 @end multitable
 
+Note that a query is applied only when both @code{:toggle} and
+@code{:level} permit it.  @code{:level} is used for global,
+coarse-grained control, whereas @code{:toggle} is for local,
+fine-grained control.
+
 Capture names in @var{query} should be face names like
 @code{font-lock-keyword-face}.  The captured node will be fontified
 with that face.  Capture names can also be function names, in which
diff --git a/lisp/treesit.el b/lisp/treesit.el
index db96a89975..7132f1d5ee 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 TOGGLE)
+    (LANGUAGE QUERY OVERRIDE TOGGLE LEVEL)
 
 Each SETTING controls one parser (often of different language).
 LANGUAGE is the language symbol.  See Info node `(elisp)Language
@@ -308,7 +308,11 @@ t, nil, append, prepend, keep.  See more in
 
 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.")
+fontification.  If TOGGLE is nil, the query is always activated.
+
+LEVEL is the decoration level of this query or nil.  Decoration
+level is controlled by `font-lock-maximum-decoration'.  If LEVEL
+is nil, the query is always activated.")
 
 (defun treesit-font-lock-rules (&rest args)
   "Return a value suitable for `treesit-font-lock-settings'.
@@ -344,6 +348,15 @@ include:
                       The value of that variable (non-nil/nil)
                       activates/deactivates the query during
                       fontification.
+             nil      Always activate this query.
+  :level     <integer>If non-nil, the value is the decoration
+                      level of this query.
+                      (See `font-lock-maximum-decoration'.)
+             nil      Always activate this query.
+
+Note that a query is applied only when both :toggle and :level
+permit it.  :level is used for global, coarse-grained control,
+whereas :toggle is for local, fine-grained control.
 
 Capture names in QUERY should be face names like
 `font-lock-keyword-face'.  The captured node will be fontified
@@ -356,18 +369,16 @@ a capture name is not a face name nor a function name, it 
is
 ignored.
 
 \(fn :KEYWORD VALUE QUERY...)"
-  (let (;; Tracks the current language that following queries will
-        ;; apply to.
-        (current-language nil)
-        ;; Tracks :override flag.
-        (current-override nil)
-        ;; Track :toggle flag.
-        (current-toggle t)
+  (let (;; Tracks the current :language/:override/:toggle/:level value
+        ;; that following queries will apply to.
+        current-language current-override
+        current-toggle current-level
         ;; The list this function returns.
         (result nil))
     (while args
       (let ((token (pop args)))
         (pcase token
+          ;; (1) Process keywords.
           (:language
            (let ((lang (pop args)))
              (when (or (not (symbolp lang)) (null lang))
@@ -393,6 +404,14 @@ ignored.
                        `("Value of :toggle should be a variable name"
                          ,var)))
              (setq current-toggle var)))
+          (:level
+           (let ((level (pop args)))
+             (when (not (and (integerp level) (> level 0)))
+               (signal 'treesit-font-lock-error
+                       `("Value of :level should be a positive integer"
+                         ,level)))
+             (setq current-level level)))
+          ;; (2) Process query.
           ((pred treesit-query-p)
            (when (null current-language)
              (signal 'treesit-font-lock-error
@@ -402,12 +421,14 @@ ignored.
              (push `(,current-language
                      ,(treesit-query-compile current-language token)
                      ,current-override
-                     ,current-toggle)
+                     ,current-toggle
+                     ,current-level)
                    result))
            ;; Clears any configurations set for this query.
            (setq current-language nil
                  current-override nil
-                 current-toggle nil))
+                 current-toggle nil
+                 current-level nil))
           (_ (signal 'treesit-font-lock-error
                      `("Unexpected value" token))))))
     (nreverse result)))
@@ -423,10 +444,20 @@ If LOUDLY is non-nil, message some debugging information."
            (match-pattern (nth 1 setting))
            (override (nth 2 setting))
            (toggle (nth 3 setting))
+           (level (nth 4 setting))
            (parser (treesit-parser-create language)))
       (when-let ((node (treesit-node-on start end parser))
-                 (activate (or (null toggle)
-                               (symbol-value toggle))))
+                 ;; Only activate this query if both :toggle and
+                 ;; :level permit it.
+                 (activate
+                  (and (or (null toggle)
+                           (symbol-value toggle))
+                       (or (null level)
+                           (pcase (font-lock-value-in-major-mode
+                                   font-lock-maximum-decoration)
+                             ('t t)
+                             ('nil (eq level 1))
+                             (lvl (<= level lvl)))))))
         (ignore activate)
         (let ((captures (treesit-query-capture
                          node match-pattern



reply via email to

[Prev in Thread] Current Thread [Next in Thread]