mirror of
https://github.com/helix-editor/helix.git
synced 2024-11-22 01:16:18 +04:00
Exclude only named children without injection.include-children (#3129)
* Exclude only named children without injection.include-children * Add injection.include-unnamed-children parameter
This commit is contained in:
parent
08b442f4cc
commit
6b244e2fef
@ -752,7 +752,7 @@ fn point_sub(a: Point, b: Point) -> Point {
|
|||||||
);
|
);
|
||||||
let mut injections = Vec::new();
|
let mut injections = Vec::new();
|
||||||
for mat in matches {
|
for mat in matches {
|
||||||
let (language_name, content_node, include_children) = injection_for_match(
|
let (language_name, content_node, included_children) = injection_for_match(
|
||||||
&layer.config,
|
&layer.config,
|
||||||
&layer.config.injections_query,
|
&layer.config.injections_query,
|
||||||
&mat,
|
&mat,
|
||||||
@ -769,7 +769,7 @@ fn point_sub(a: Point, b: Point) -> Point {
|
|||||||
{
|
{
|
||||||
if let Some(config) = (injection_callback)(&language_name) {
|
if let Some(config) = (injection_callback)(&language_name) {
|
||||||
let ranges =
|
let ranges =
|
||||||
intersect_ranges(&layer.ranges, &[content_node], include_children);
|
intersect_ranges(&layer.ranges, &[content_node], included_children);
|
||||||
|
|
||||||
if !ranges.is_empty() {
|
if !ranges.is_empty() {
|
||||||
injections.push((config, ranges));
|
injections.push((config, ranges));
|
||||||
@ -781,7 +781,10 @@ fn point_sub(a: Point, b: Point) -> Point {
|
|||||||
// Process combined injections.
|
// Process combined injections.
|
||||||
if let Some(combined_injections_query) = &layer.config.combined_injections_query {
|
if let Some(combined_injections_query) = &layer.config.combined_injections_query {
|
||||||
let mut injections_by_pattern_index =
|
let mut injections_by_pattern_index =
|
||||||
vec![(None, Vec::new(), false); combined_injections_query.pattern_count()];
|
vec![
|
||||||
|
(None, Vec::new(), IncludedChildren::default());
|
||||||
|
combined_injections_query.pattern_count()
|
||||||
|
];
|
||||||
let matches = cursor.matches(
|
let matches = cursor.matches(
|
||||||
combined_injections_query,
|
combined_injections_query,
|
||||||
layer.tree().root_node(),
|
layer.tree().root_node(),
|
||||||
@ -789,7 +792,7 @@ fn point_sub(a: Point, b: Point) -> Point {
|
|||||||
);
|
);
|
||||||
for mat in matches {
|
for mat in matches {
|
||||||
let entry = &mut injections_by_pattern_index[mat.pattern_index];
|
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, included_children) = injection_for_match(
|
||||||
&layer.config,
|
&layer.config,
|
||||||
combined_injections_query,
|
combined_injections_query,
|
||||||
&mat,
|
&mat,
|
||||||
@ -801,16 +804,16 @@ fn point_sub(a: Point, b: Point) -> Point {
|
|||||||
if let Some(content_node) = content_node {
|
if let Some(content_node) = content_node {
|
||||||
entry.1.push(content_node);
|
entry.1.push(content_node);
|
||||||
}
|
}
|
||||||
entry.2 = include_children;
|
entry.2 = included_children;
|
||||||
}
|
}
|
||||||
for (lang_name, content_nodes, includes_children) in injections_by_pattern_index
|
for (lang_name, content_nodes, included_children) in injections_by_pattern_index
|
||||||
{
|
{
|
||||||
if let (Some(lang_name), false) = (lang_name, content_nodes.is_empty()) {
|
if let (Some(lang_name), false) = (lang_name, content_nodes.is_empty()) {
|
||||||
if let Some(config) = (injection_callback)(&lang_name) {
|
if let Some(config) = (injection_callback)(&lang_name) {
|
||||||
let ranges = intersect_ranges(
|
let ranges = intersect_ranges(
|
||||||
&layer.ranges,
|
&layer.ranges,
|
||||||
&content_nodes,
|
&content_nodes,
|
||||||
includes_children,
|
included_children,
|
||||||
);
|
);
|
||||||
if !ranges.is_empty() {
|
if !ranges.is_empty() {
|
||||||
injections.push((config, ranges));
|
injections.push((config, ranges));
|
||||||
@ -1408,6 +1411,19 @@ fn sort_key(&mut self) -> Option<(usize, bool, isize)> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
enum IncludedChildren {
|
||||||
|
None,
|
||||||
|
All,
|
||||||
|
Unnamed,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for IncludedChildren {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Compute the ranges that should be included when parsing an injection.
|
// Compute the ranges that should be included when parsing an injection.
|
||||||
// This takes into account three things:
|
// This takes into account three things:
|
||||||
// * `parent_ranges` - The ranges must all fall within the *current* layer's ranges.
|
// * `parent_ranges` - The ranges must all fall within the *current* layer's ranges.
|
||||||
@ -1420,7 +1436,7 @@ fn sort_key(&mut self) -> Option<(usize, bool, isize)> {
|
|||||||
fn intersect_ranges(
|
fn intersect_ranges(
|
||||||
parent_ranges: &[Range],
|
parent_ranges: &[Range],
|
||||||
nodes: &[Node],
|
nodes: &[Node],
|
||||||
includes_children: bool,
|
included_children: IncludedChildren,
|
||||||
) -> Vec<Range> {
|
) -> Vec<Range> {
|
||||||
let mut cursor = nodes[0].walk();
|
let mut cursor = nodes[0].walk();
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
@ -1444,11 +1460,15 @@ fn intersect_ranges(
|
|||||||
|
|
||||||
for excluded_range in node
|
for excluded_range in node
|
||||||
.children(&mut cursor)
|
.children(&mut cursor)
|
||||||
.filter_map(|child| {
|
.filter_map(|child| match included_children {
|
||||||
if includes_children {
|
IncludedChildren::None => Some(child.range()),
|
||||||
None
|
IncludedChildren::All => None,
|
||||||
} else {
|
IncludedChildren::Unnamed => {
|
||||||
Some(child.range())
|
if child.is_named() {
|
||||||
|
Some(child.range())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.chain([following_range].iter().cloned())
|
.chain([following_range].iter().cloned())
|
||||||
@ -1777,7 +1797,7 @@ fn injection_for_match<'a>(
|
|||||||
query: &'a Query,
|
query: &'a Query,
|
||||||
query_match: &QueryMatch<'a, 'a>,
|
query_match: &QueryMatch<'a, 'a>,
|
||||||
source: RopeSlice<'a>,
|
source: RopeSlice<'a>,
|
||||||
) -> (Option<Cow<'a, str>>, Option<Node<'a>>, bool) {
|
) -> (Option<Cow<'a, str>>, Option<Node<'a>>, IncludedChildren) {
|
||||||
let content_capture_index = config.injection_content_capture_index;
|
let content_capture_index = config.injection_content_capture_index;
|
||||||
let language_capture_index = config.injection_language_capture_index;
|
let language_capture_index = config.injection_language_capture_index;
|
||||||
|
|
||||||
@ -1793,7 +1813,7 @@ fn injection_for_match<'a>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut include_children = false;
|
let mut included_children = IncludedChildren::default();
|
||||||
for prop in query.property_settings(query_match.pattern_index) {
|
for prop in query.property_settings(query_match.pattern_index) {
|
||||||
match prop.key.as_ref() {
|
match prop.key.as_ref() {
|
||||||
// In addition to specifying the language name via the text of a
|
// In addition to specifying the language name via the text of a
|
||||||
@ -1809,12 +1829,17 @@ fn injection_for_match<'a>(
|
|||||||
// `injection.content` node - only the ranges that belong to the
|
// `injection.content` node - only the ranges that belong to the
|
||||||
// node itself. This can be changed using a `#set!` predicate that
|
// node itself. This can be changed using a `#set!` predicate that
|
||||||
// sets the `injection.include-children` key.
|
// sets the `injection.include-children` key.
|
||||||
"injection.include-children" => include_children = true,
|
"injection.include-children" => included_children = IncludedChildren::All,
|
||||||
|
|
||||||
|
// 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" => included_children = IncludedChildren::Unnamed,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(language_name, content_node, include_children)
|
(language_name, content_node, included_children)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Merge<I> {
|
pub struct Merge<I> {
|
||||||
|
Loading…
Reference in New Issue
Block a user