From 574fac36584f7bd1d7cb511bca2bad013578ee06 Mon Sep 17 00:00:00 2001 From: MDeiml Date: Tue, 26 Jul 2022 16:58:53 +0200 Subject: [PATCH] Add injection.include-unnamed-children parameter --- helix-core/src/syntax.rs | 60 +++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs index dfc3bef76d8c1..99b61699988d9 100644 --- a/helix-core/src/syntax.rs +++ b/helix-core/src/syntax.rs @@ -766,12 +766,13 @@ impl Syntax { ); let mut injections = Vec::new(); for mat in matches { - let (language_name, content_node, include_children) = injection_for_match( - &layer.config, - &layer.config.injections_query, - &mat, - source_slice, - ); + let (language_name, content_node, include_children, include_unnamed_children) = + injection_for_match( + &layer.config, + &layer.config.injections_query, + &mat, + source_slice, + ); // Explicitly remove this match so that none of its other captures will remain // in the stream of captures. @@ -782,8 +783,12 @@ impl Syntax { if let (Some(language_name), Some(content_node)) = (language_name, content_node) { if let Some(config) = (injection_callback)(&language_name) { - let ranges = - intersect_ranges(&layer.ranges, &[content_node], include_children); + let ranges = intersect_ranges( + &layer.ranges, + &[content_node], + include_children, + include_unnamed_children, + ); if !ranges.is_empty() { injections.push((config, ranges)); @@ -794,8 +799,11 @@ impl Syntax { // Process combined injections. if let Some(combined_injections_query) = &layer.config.combined_injections_query { - let mut injections_by_pattern_index = - vec![(None, Vec::new(), false); combined_injections_query.pattern_count()]; + let mut injections_by_pattern_index = vec![ + (None, Vec::new(), false, false); + combined_injections_query + .pattern_count() + ]; let matches = cursor.matches( combined_injections_query, layer.tree().root_node(), @@ -803,7 +811,12 @@ impl Syntax { ); for mat in matches { let entry = &mut injections_by_pattern_index[mat.pattern_index]; - let (language_name, content_node, include_children) = injection_for_match( + let ( + language_name, + content_node, + include_children, + include_unnamed_children, + ) = injection_for_match( &layer.config, combined_injections_query, &mat, @@ -816,8 +829,10 @@ impl Syntax { entry.1.push(content_node); } entry.2 = include_children; + entry.3 = include_unnamed_children; } - for (lang_name, content_nodes, includes_children) in injections_by_pattern_index + for (lang_name, content_nodes, includes_children, includes_unnamed_children) in + injections_by_pattern_index { if let (Some(lang_name), false) = (lang_name, content_nodes.is_empty()) { if let Some(config) = (injection_callback)(&lang_name) { @@ -825,6 +840,7 @@ impl Syntax { &layer.ranges, &content_nodes, includes_children, + includes_unnamed_children, ); if !ranges.is_empty() { injections.push((config, ranges)); @@ -1435,6 +1451,7 @@ fn intersect_ranges( parent_ranges: &[Range], nodes: &[Node], includes_children: bool, + includes_unnamed_children: bool, ) -> Vec { let mut cursor = nodes[0].walk(); let mut result = Vec::new(); @@ -1457,9 +1474,9 @@ fn intersect_ranges( }; for excluded_range in node - .named_children(&mut cursor) + .children(&mut cursor) .filter_map(|child| { - if includes_children { + if includes_children || (includes_unnamed_children && !child.is_named()) { None } else { Some(child.range()) @@ -1791,7 +1808,7 @@ fn injection_for_match<'a>( query: &'a Query, query_match: &QueryMatch<'a, 'a>, source: RopeSlice<'a>, -) -> (Option>, Option>, bool) { +) -> (Option>, Option>, bool, bool) { let content_capture_index = config.injection_content_capture_index; let language_capture_index = config.injection_language_capture_index; @@ -1808,6 +1825,7 @@ fn injection_for_match<'a>( } let mut include_children = false; + let mut include_unnamed_children = false; for prop in query.property_settings(query_match.pattern_index) { match prop.key.as_ref() { // In addition to specifying the language name via the text of a @@ -1824,11 +1842,21 @@ fn injection_for_match<'a>( // node itself. This can be changed using a `#set!` predicate that // sets the `injection.include-children` key. "injection.include-children" => include_children = true, + + // Some queries might only exclude named children but include unnamed + // children in their `injection.content` node. This can be enabled using + // a `#set!` predicate that sets the `injection.include-unnamed-children` key. + "injection.include-unnamed-children" => include_unnamed_children = true, _ => {} } } - (language_name, content_node, include_children) + ( + language_name, + content_node, + include_children, + include_unnamed_children, + ) } pub struct Merge {