1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-02-04 14:40:54 -08:00

Add an argument OVERRIDE to tree-sitter font-lock functions

* doc/lispref/modes.texi (Parser-based Font Lock): Reflect this change
in manual.
* lisp/progmodes/js.el (js--fontify-template-string): Add _OVERRIDE
argument.
* lisp/progmodes/python.el (python--treesit-fontify-string): Add
_OVERRIDE argument.
* lisp/treesit.el (treesit-font-lock-rules): Update docstring.
(treesit-fontify-with-override): New function.
(treesit-font-lock-fontify-region): Extract out into
treesit-fontify-with-override.
This commit is contained in:
Yuan Fu 2022-10-31 15:03:49 -07:00
parent 9fab83ed7a
commit eeeae5e9ee
No known key found for this signature in database
GPG key ID: 56E19BC57664A442
4 changed files with 49 additions and 31 deletions

View file

@ -3975,12 +3975,22 @@ that starts with @code{@@}), and tree-sitter will return matched nodes
tagged with those same capture names. For the purpose of
fontification, 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
case the function is called with 3 arguments: @var{start}, @var{end},
and @var{node}, where @var{start} and @var{end} are the start and end
position of the node in buffer, and @var{node} is the node itself. 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 ignored.
with that face.
@findex treesit-fontify-with-override
Capture names can also be function names, in which case the function
is called with 4 arguments: @var{start}, @var{end}, @var{node}, and
@var{override}, where @var{start} and @var{end} are the start and end
position of the node in buffer, @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 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
ignored.
@end defun
@defvar treesit-font-lock-feature-list

View file

@ -3573,7 +3573,7 @@ This function is intended for use in `after-change-functions'."
@font-lock-constant-face)))
"Tree-sitter font-lock settings.")
(defun js--fontify-template-string (beg end node)
(defun js--fontify-template-string (beg end node _override &rest _)
"Fontify template string but not substitution inside it.
BEG, END, NODE refers to the template_string node."
(ignore end)

View file

@ -1015,7 +1015,7 @@ It makes underscores and dots word constituent chars.")
"VMSError" "WindowsError"
))
(defun python--treesit-fontify-string (_beg _end node)
(defun python--treesit-fontify-string (_beg _end node _override &rest _)
"Fontify string.
NODE is the last quote in the string. Do not fontify the initial
f for f-strings."

View file

@ -410,7 +410,7 @@ omitted, default END to BEG."
return rng
finally return nil))))
;;; Font-lock
;;; Fontification
(define-error 'treesit-font-lock-error
"Generic tree-sitter font-lock error"
@ -500,12 +500,14 @@ 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 is called with (START END NODE), where
START and END are the start and end position of the node in
buffer, and NODE is the tree-sitter node object. 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 name, it is
ignored.
which case the function is called with (START END NODE OVERRIDE),
where START and END are the start and end position of the node in
buffer, 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. 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
name, it is ignored.
\(fn :KEYWORD VALUE QUERY...)"
;; Other tree-sitter function don't tend to be called unless
@ -600,6 +602,26 @@ Set the ENABLE flag for each setting in
do (setf (nth 1 (nth idx treesit-font-lock-settings))
(if (memq feature features) t nil)))))
(defun treesit-fontify-with-override (start end face override)
"Apply FACE to the region between START and END.
OVERRIDE can be nil, t, `append', `prepend', or `keep'.
See `treesit-font-lock-rules' for their semantic."
(pcase override
('nil (unless (text-property-not-all
start end 'face nil)
(put-text-property start end 'face face)))
('t (put-text-property start end 'face face))
('append (font-lock-append-text-property
start end 'face face))
('prepend (font-lock-prepend-text-property
start end 'face face))
('keep (font-lock-fillin-text-property
start end 'face face))
(_ (signal 'treesit-font-lock-error
(list
"Unrecognized value of :override option"
override)))))
(defun treesit-font-lock-fontify-region
(start end &optional loudly)
"Fontify the region between START and END.
@ -633,23 +655,9 @@ If LOUDLY is non-nil, display some debugging information."
(end (treesit-node-end node)))
(cond
((facep face)
(pcase override
('nil (unless (text-property-not-all
start end 'face nil)
(put-text-property start end 'face face)))
('t (put-text-property start end 'face face))
('append (font-lock-append-text-property
start end 'face face))
('prepend (font-lock-prepend-text-property
start end 'face face))
('keep (font-lock-fillin-text-property
start end 'face face))
(_ (signal 'treesit-font-lock-error
(list
"Unrecognized value of :override option"
override)))))
(treesit-fontify-with-override start end face override))
((functionp face)
(funcall face start end node)))
(funcall face start end node override)))
;; 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.