kak-tree/src/tree.rs
2023-11-12 00:21:50 +01:00

80 lines
2.6 KiB
Rust

use tree_sitter::{Node, Range};
pub fn named_children<'a>(node: &'a Node) -> impl Iterator<Item = Node<'a>> {
(0..node.child_count()).map(move |i| node.child(i).unwrap())
}
pub fn shrink_to_range<'a>(root_node: Node<'a>, range: &Range) -> Node<'a> {
let mut node = root_node;
'outer: loop {
let parent = node;
let mut cursor = parent.walk();
for child in parent.children(&mut cursor) {
if child.range().start_byte <= range.start_byte
&& range.end_byte <= child.range().end_byte
{
node = child;
continue 'outer;
}
}
return highest_node_of_same_range(node);
}
}
pub fn nodes_in_range<'a>(root_node: Node<'a>, range: &Range) -> Vec<Node<'a>> {
let mut nodes = Vec::new();
let node = shrink_to_range(root_node, range);
if node.range().start_byte >= range.start_byte && range.end_byte >= node.range().end_byte {
nodes.push(node);
return nodes;
}
let mut cursor = node.walk();
for child in node.children(&mut cursor) {
if child.range().start_byte <= range.start_byte && range.end_byte >= child.range().end_byte
{
nodes.extend(nodes_in_range(
child,
&Range {
start_byte: range.start_byte,
start_point: range.start_point,
end_byte: child.range().end_byte,
end_point: child.range().end_point,
},
));
} else if child.range().start_byte >= range.start_byte
&& range.end_byte <= child.range().end_byte
{
nodes.extend(nodes_in_range(
child,
&Range {
start_byte: child.range().start_byte,
start_point: child.range().start_point,
end_byte: range.end_byte,
end_point: range.end_point,
},
));
} else if child.range().start_byte >= range.start_byte
&& range.end_byte >= child.range().end_byte
{
nodes.push(child);
}
}
nodes
}
fn highest_node_of_same_range<'a>(current_node: Node<'a>) -> Node<'a> {
let start_byte = current_node.start_byte();
let end_byte = current_node.end_byte();
let mut node = current_node;
while let Some(parent) = node.parent().and_then(|parent| {
if parent.start_byte() < start_byte || end_byte < parent.end_byte() {
None
} else {
Some(parent)
}
}) {
node = parent
}
node
}