<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’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
@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
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
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'.
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
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))
`("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
(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)))
(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