From 69ab588bb54178df0d3be6b4c04dabb49f5a2ac9 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Wed, 2 Nov 2022 17:03:03 -0700 Subject: [PATCH] Pass region start and end to tree-sitter fontification functions * doc/lispref/modes.texi (Parser-based Font Lock): Update manual. * lisp/progmodes/js.el (js--fontify-template-string) * lisp/progmodes/python.el (python--treesit-fontify-string): Update function to only fontify within the region. * lisp/treesit.el (treesit-font-lock-rules): Update docstring. (treesit-font-lock-fontify-region): Pass START and END to fontification functions. --- doc/lispref/modes.texi | 16 +++++++++------- lisp/progmodes/js.el | 22 ++++++++++++---------- lisp/progmodes/python.el | 12 +++++++----- lisp/treesit.el | 19 +++++++++++++------ 4 files changed, 41 insertions(+), 28 deletions(-) diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index c6f848ffb23..c1b092247bd 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -3979,13 +3979,15 @@ with that face. @findex treesit-fontify-with-override Capture names can also be function names, in which case the function -is called with 2 arguments: @var{node} and @var{override}, where -@var{node} is the node itself, and @var{override} is the override -property of the rule which captured this node. (If this function -wants to respect the @var{override} argument, it can use -@code{treesit-fontify-with-override}.) Beyond the 2 arguments -presented, this function should accept more arguments as optional -arguments for future extensibility. +is called with 4 arguments: @var{node} and @var{override}, @var{start} +and @var{end}, where @var{node} is the node itself, @var{override} is +the override property of the rule which captured this node, and +@var{start} and @var{end} limits the region in which this function +should fontify. (If this function wants to respect the @var{override} +argument, it can use @code{treesit-fontify-with-override}.) + +Beyond the 4 arguments presented, this function should accept more +arguments as optional arguments for future extensibility. If a capture name is both a face and a function, the face takes priority. If a capture name is neither a face nor a function, it is diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el index 76d4ec748a0..c77c0fb90be 100644 --- a/lisp/progmodes/js.el +++ b/lisp/progmodes/js.el @@ -3573,9 +3573,10 @@ This function is intended for use in `after-change-functions'." @font-lock-constant-face))) "Tree-sitter font-lock settings.") -(defun js--fontify-template-string (node override &rest _) +(defun js--fontify-template-string (node override start end &rest _) "Fontify template string but not substitution inside it. -BEG, END, NODE refers to the template_string node. +NODE is the template_string node. START and END marks the region +to be fontified. OVERRIDE is the override flag described in `treesit-font-lock-rules'." @@ -3585,16 +3586,17 @@ OVERRIDE is the override flag described in ;; closing "`". That's why we have to track BEG instead of just ;; fontifying each child. (let ((child (treesit-node-child node 0)) - (beg (treesit-node-start node))) + (font-beg (treesit-node-start node))) (while child - (if (equal (treesit-node-type child) "template_substitution") + (let ((font-end (if (equal (treesit-node-type child) + "template_substitution") + (treesit-node-start child) + (treesit-node-end child)))) + (setq font-beg (max beg font-beg)) + (when (< font-beg end) (treesit-fontify-with-override - beg (treesit-node-start child) - 'font-lock-string-face override) - (treesit-fontify-with-override - beg (treesit-node-end child) - 'font-lock-string-face override)) - (setq beg (treesit-node-end child) + font-beg font-end 'font-lock-string-face override))) + (setq font-beg (treesit-node-end child) child (treesit-node-next-sibling child))))) (defun js-treesit-current-defun () diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 603cdb14e15..8db96b117f3 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -1015,11 +1015,12 @@ It makes underscores and dots word constituent chars.") "VMSError" "WindowsError" )) -(defun python--treesit-fontify-string (node override &rest _) +(defun python--treesit-fontify-string (node override start end &rest _) "Fontify string. -NODE is the leading quote in the string. Do not fontify the initial -f for f-strings. OVERRIDE is the override flag described in -`treesit-font-lock-rules'." +NODE is the leading quote in the string. Do not fontify the +initial f for f-strings. OVERRIDE is the override flag described +in `treesit-font-lock-rules'. START and END marks the region to +be fontified." (let* ((string (treesit-node-parent node)) (string-beg (treesit-node-start string)) (string-end (treesit-node-end string)) @@ -1033,7 +1034,8 @@ f for f-strings. OVERRIDE is the override flag described in 'font-lock-string-face))) (when (eq (char-after string-beg) ?f) (cl-incf string-beg)) - (treesit-fontify-with-override string-beg string-end face override))) + (treesit-fontify-with-override + (max start string-beg) (min end string-end) face override))) (defvar python--treesit-settings (treesit-font-lock-rules diff --git a/lisp/treesit.el b/lisp/treesit.el index 6a7ba87e836..d6058cdc43f 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -502,11 +502,18 @@ Other keywords include: Capture names in QUERY should be face names like `font-lock-keyword-face'. The captured node will be fontified -with that face. Capture names can also be function names, in -which case the function should have a signature (NODE OVERRIDE -&rest _), where NODE is the tree-sitter node object, and OVERRIDE -is the override option of that rule. This function should accept -more arguments as optional arguments for future extensibility. +with that face. + +Capture names can also be function names, in which case the +function should have a signature + + (NODE OVERRIDE START END &rest _) + +where NODE is the tree-sitter node object, OVERRIDE is the +override option of that rule, and START and END marks the region +to be fontified. This function should accept more arguments as +optional arguments for future extensibility. And this function +shouldn't fontify text outside START and END. If a capture name is both a face and a function, the face takes priority. If a capture name is not a face name nor a function @@ -754,7 +761,7 @@ If LOUDLY is non-nil, display some debugging information." (max node-start start) (min node-end end) face override)) ((functionp face) - (funcall face node override))) + (funcall face node override start end))) ;; Don't raise an error if FACE is neither a face nor ;; a function. This is to allow intermediate capture ;; names used for #match and #eq. -- 2.39.5