emacs-diffs
[Top][All Lists]
Advanced

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

feature/tree-sitter 625ea08652 1/2: Improve tree-sitter fontification on


From: Yuan Fu
Subject: feature/tree-sitter 625ea08652 1/2: Improve tree-sitter fontification on large buffers
Date: Sun, 20 Nov 2022 20:07:05 -0500 (EST)

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

    Improve tree-sitter fontification on large buffers
    
    * lisp/treesit.el (treesit--children-covering-range)
    (treesit--children-covering-range-recurse): New functions.  They are
    not currently used but could be useful in the future, so I left them
    in place.
    (treesit-font-lock-fontify-region):
    * lisp/treesit.el (treesit-font-lock-fontify-region): Use the result
    of treesit-node-on instead of the root node.
---
 lisp/treesit.el | 60 +++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 52 insertions(+), 8 deletions(-)

diff --git a/lisp/treesit.el b/lisp/treesit.el
index 674c984dfe..d65ad31b47 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -748,6 +748,37 @@ instead."
         (remove-text-properties start end '(rear-nonsticky nil))
       (put-text-property start end 'rear-nonsticky new-prop))))
 
+(defun treesit--children-covering-range (node start end)
+  "Return a list of children of NODE covering a range.
+The range is between START and END."
+  (let* ((child (treesit-node-first-child-for-pos node start))
+         (result (list child)))
+    (while (and (< (treesit-node-end child) end)
+                (setq child (treesit-node-next-sibling child)))
+      (push child result))
+    (nreverse result)))
+
+(defun treesit--children-covering-range-recurse (node start end threshold)
+  "Return a list of children of NODE covering a range.
+Recursively go down the parse tree and collect children, until
+all nodes in the returned list are smaller than THRESHOLD.  The
+range is between START and END."
+  (let* ((child (treesit-node-first-child-for-pos node start))
+         result)
+    (while (and child (<= (treesit-node-start child) end))
+      ;; If child still too large, recurse down.  Otherwise collect
+      ;; child.
+      (if (> (- (treesit-node-end child)
+                (treesit-node-start child))
+             threshold)
+          (dolist (r (treesit--children-covering-range-recurse
+                      child start end threshold))
+            (push r result))
+        (push child result))
+      (setq child (treesit-node-next-sibling child)))
+    ;; If NODE has no child, keep NODE.
+    (or result node)))
+
 ;; Some details worth explaining:
 ;;
 ;; 1. When we apply face to a node, we clip the face into the
@@ -768,18 +799,31 @@ If LOUDLY is non-nil, display some debugging information."
            (enable (nth 1 setting))
            (override (nth 3 setting))
            (language (treesit-query-language query)))
-      ;; Why root node rather than (treesit-node-on start end)?  If
-      ;; you insert an ending quote into a buffer, jit-lock only wants
-      ;; to fontify that single quote, and (treesit-node-on start end)
-      ;; will give you that quote node.  We want to capture the string
-      ;; and apply string face to it, but querying on the quote node
-      ;; will not give us the string node.
-      (when-let ((root (treesit-buffer-root-node language))
+      ;; If you insert an ending quote into a buffer, jit-lock only
+      ;; wants to fontify that single quote, and (treesit-node-on
+      ;; start end) will give you that quote node.  We want to capture
+      ;; the string and apply string face to it, but querying on the
+      ;; quote node will not give us the string node.  OTOH, if you
+      ;; query the root node, it will be very slow in very large
+      ;; (MB's) buffers.  So we still use `treesit-node-on', but try
+      ;; to enlarge it if the node seems small.  (The threshold for
+      ;; small is arbitrary.) TODO: Sometimes the node returned by
+      ;; `treesit-node-on' is still much larger than the region we
+      ;; want to fontify.  I tried to recursively go down to its
+      ;; children and get a set of smaller nodes that span the region.
+      ;; But this didn't work too well.
+      (when-let ((node-on (treesit-node-on start end language))
                  ;; Only activate if ENABLE flag is t.
                  (activate (eq t enable)))
         (ignore activate)
+        ;; The node seems small, enlarge it.
+        (while (and (< (- (treesit-node-end node-on)
+                          (treesit-node-start node-on))
+                       40)
+                    (treesit-node-parent node-on))
+          (setq node-on (treesit-node-parent node-on)))
         (let ((captures (treesit-query-capture
-                         root query start end))
+                         node-on query start end))
               (inhibit-point-motion-hooks t))
           (with-silent-modifications
             (dolist (capture captures)



reply via email to

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