Skip to content

Commit 031e78b

Browse files
committed
Add a "rainbow.include-children" property for HTML
This allows us to use rainbow nesting highlights for HTML tags. The nesting node is the HTML grammar's `element` node. `<`/`>` are direct descendants of `start_tag` and `end_tag` rather than `element` though. `<`/`>` is not valid in this grammar except in cases where we want to highlight it. So we can exclude the `start_tag` and `end_tag` parents (which aren't scopes) and instead have the `element` match on any children `<`/`>`. Note that "rainbow.include-children" only applies to the scope captured with `@rainbow.scope`: any children scopes will disable the setting.
1 parent b1112ed commit 031e78b

File tree

3 files changed

+28
-11
lines changed

3 files changed

+28
-11
lines changed

book/src/generated/lang-support.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
| haskell || | | | `haskell-language-server-wrapper` |
4545
| hcl || || | `terraform-ls` |
4646
| heex ||| | | |
47-
| html || | | | `vscode-html-language-server` |
47+
| html || | | | `vscode-html-language-server` |
4848
| idris | | | | | `idris2-lsp` |
4949
| iex || | | | |
5050
| java || | || `jdtls` |

helix-core/src/syntax.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2000,13 +2000,22 @@ impl<'a> Iterator for RainbowIter<'a> {
20002000
// If the node represents a rainbow scope, push a new rainbow scope onto
20012001
// the scope stack.
20022002
if Some(capture.index) == layer.config.rainbow_scope_capture_index {
2003-
let scope = RainbowScope {
2003+
let mut scope = RainbowScope {
20042004
range: range.clone(),
20052005
node_id: capture.node.id(),
20062006
highlight: Highlight(
20072007
self.context.rainbow_stack.len() % self.context.rainbow_length,
20082008
),
20092009
};
2010+
for prop in layer
2011+
.config
2012+
.rainbow_query
2013+
.property_settings(match_.pattern_index)
2014+
{
2015+
if prop.key.as_ref() == "rainbow.include-children" {
2016+
scope.node_id = usize::MAX;
2017+
}
2018+
}
20102019
self.context.rainbow_stack.push(scope);
20112020
}
20122021

@@ -2024,15 +2033,10 @@ impl<'a> Iterator for RainbowIter<'a> {
20242033

20252034
if Some(capture.index) == layer.config.rainbow_bracket_capture_index {
20262035
if let Some(scope) = self.context.rainbow_stack.last() {
2027-
// Check that the parent of the `@rainbow.bracket` capture is
2028-
// the `@rainbow.scope` node. This allows us to have bracket
2029-
// highlights for type parameters/arguments in Rust for example
2030-
// without also highlighting operators like < and >.
2031-
if capture
2032-
.node
2033-
.parent()
2034-
.map(|p| p.id() == scope.node_id)
2035-
.unwrap_or_default()
2036+
// If the scope includes all children or if this capture is a direct descendant of
2037+
// the scope's captured node then this capture inherits the scope's highlight.
2038+
if scope.node_id == usize::MAX
2039+
|| capture.node.parent().map(|p| p.id()) == Some(scope.node_id)
20362040
{
20372041
rainbow_highlight = Some(scope.highlight);
20382042
}

runtime/queries/html/rainbows.scm

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[
2+
(doctype)
3+
(erroneous_end_tag)
4+
] @rainbow.scope
5+
6+
([
7+
(element)
8+
(script_element)
9+
(style_element)
10+
] @rainbow.scope
11+
(#set! rainbow.include-children))
12+
13+
["<" ">" "<!" "</" "/>"] @rainbow.bracket

0 commit comments

Comments
 (0)