Use new in-crate TreeCursor

pull/10323/head
Skyler Hawthorne 1 year ago committed by Michael Davis
parent fa67c5c474
commit c99c333337

@ -1,5 +1,4 @@
use crate::{movement::Direction, syntax::TreeCursor, Range, RopeSlice, Selection, Syntax}; use crate::{syntax::TreeCursor, Range, RopeSlice, Selection, Syntax};
use tree_sitter::{Node, Tree};
pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
let cursor = &mut syntax.walk(); let cursor = &mut syntax.walk();
@ -41,85 +40,46 @@ pub fn select_next_sibling(syntax: &Syntax, text: RopeSlice, selection: Selectio
}) })
} }
fn find_parent_with_more_children(mut node: Node) -> Option<Node> { pub fn select_all_siblings(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
while let Some(parent) = node.parent() { selection.transform_iter(|range| {
if parent.child_count() > 1 { let mut cursor = syntax.walk();
return Some(parent); let (from, to) = range.into_byte_range(text);
} cursor.reset_to_byte_range(from, to);
node = parent;
}
None if !cursor.goto_parent_with(|parent| parent.child_count() > 1) {
return vec![range].into_iter();
} }
pub fn select_all_siblings(tree: &Tree, text: RopeSlice, selection: Selection) -> Selection { select_children(&mut cursor, text, range).into_iter()
let root_node = &tree.root_node();
selection.transform_iter(|range| {
let from = text.char_to_byte(range.from());
let to = text.char_to_byte(range.to());
root_node
.descendant_for_byte_range(from, to)
.and_then(find_parent_with_more_children)
.and_then(|parent| select_children(parent, text, range.direction()))
.unwrap_or_else(|| vec![range].into_iter())
}) })
} }
pub fn select_all_children(tree: &Tree, text: RopeSlice, selection: Selection) -> Selection { pub fn select_all_children(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
let root_node = &tree.root_node();
selection.transform_iter(|range| { selection.transform_iter(|range| {
let from = text.char_to_byte(range.from()); let mut cursor = syntax.walk();
let to = text.char_to_byte(range.to()); let (from, to) = range.into_byte_range(text);
cursor.reset_to_byte_range(from, to);
root_node select_children(&mut cursor, text, range).into_iter()
.descendant_for_byte_range(from, to)
.and_then(|parent| select_children(parent, text, range.direction()))
.unwrap_or_else(|| vec![range].into_iter())
}) })
} }
fn select_children( fn select_children<'n>(
node: Node, cursor: &'n mut TreeCursor<'n>,
text: RopeSlice, text: RopeSlice,
direction: Direction, range: Range,
) -> Option<<Vec<Range> as std::iter::IntoIterator>::IntoIter> { ) -> Vec<Range> {
let mut cursor = node.walk(); let children = cursor
.named_children()
let children = node .map(|child| Range::from_node(child, text, range.direction()))
.named_children(&mut cursor)
.map(|child| {
let from = text.byte_to_char(child.start_byte());
let to = text.byte_to_char(child.end_byte());
if direction == Direction::Backward {
Range::new(to, from)
} else {
Range::new(from, to)
}
})
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if !children.is_empty() { if !children.is_empty() {
Some(children.into_iter()) children
} else { } else {
None vec![range]
} }
} }
fn find_sibling_recursive<F>(node: Node, sibling_fn: F) -> Option<Node>
where
F: Fn(Node) -> Option<Node>,
{
sibling_fn(node).or_else(|| {
node.parent()
.and_then(|node| find_sibling_recursive(node, sibling_fn))
})
}
pub fn select_prev_sibling(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { pub fn select_prev_sibling(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
select_node_impl(syntax, text, selection, |cursor| { select_node_impl(syntax, text, selection, |cursor| {
while !cursor.goto_prev_sibling() { while !cursor.goto_prev_sibling() {

@ -90,6 +90,19 @@ impl<'a> TreeCursor<'a> {
true true
} }
pub fn goto_parent_with<P>(&mut self, predicate: P) -> bool
where
P: Fn(&Node) -> bool,
{
while self.goto_parent() {
if predicate(&self.node()) {
return true;
}
}
false
}
/// Finds the injection layer that has exactly the same range as the given `range`. /// Finds the injection layer that has exactly the same range as the given `range`.
fn layer_id_of_byte_range(&self, search_range: Range<usize>) -> Option<LayerId> { fn layer_id_of_byte_range(&self, search_range: Range<usize>) -> Option<LayerId> {
let start_idx = self let start_idx = self
@ -102,7 +115,7 @@ impl<'a> TreeCursor<'a> {
.find_map(|range| (range.start == search_range.start).then_some(range.layer_id)) .find_map(|range| (range.start == search_range.start).then_some(range.layer_id))
} }
pub fn goto_first_child(&mut self) -> bool { fn goto_first_child_impl(&mut self, named: bool) -> bool {
// Check if the current node's range is an exact injection layer range. // Check if the current node's range is an exact injection layer range.
if let Some(layer_id) = self if let Some(layer_id) = self
.layer_id_of_byte_range(self.node().byte_range()) .layer_id_of_byte_range(self.node().byte_range())
@ -111,8 +124,16 @@ impl<'a> TreeCursor<'a> {
// Switch to the child layer. // Switch to the child layer.
self.current = layer_id; self.current = layer_id;
self.cursor = self.layers[self.current].tree().root_node(); self.cursor = self.layers[self.current].tree().root_node();
true return true;
} else if let Some(child) = self.cursor.child(0) { }
let child = if named {
self.cursor.named_child(0)
} else {
self.cursor.child(0)
};
if let Some(child) = child {
// Otherwise descend in the current tree. // Otherwise descend in the current tree.
self.cursor = child; self.cursor = child;
true true
@ -121,8 +142,22 @@ impl<'a> TreeCursor<'a> {
} }
} }
pub fn goto_next_sibling(&mut self) -> bool { pub fn goto_first_child(&mut self) -> bool {
if let Some(sibling) = self.cursor.next_sibling() { self.goto_first_child_impl(false)
}
pub fn goto_first_named_child(&mut self) -> bool {
self.goto_first_child_impl(true)
}
fn goto_next_sibling_impl(&mut self, named: bool) -> bool {
let sibling = if named {
self.cursor.next_named_sibling()
} else {
self.cursor.next_sibling()
};
if let Some(sibling) = sibling {
self.cursor = sibling; self.cursor = sibling;
true true
} else { } else {
@ -130,8 +165,22 @@ impl<'a> TreeCursor<'a> {
} }
} }
pub fn goto_prev_sibling(&mut self) -> bool { pub fn goto_next_sibling(&mut self) -> bool {
if let Some(sibling) = self.cursor.prev_sibling() { self.goto_next_sibling_impl(false)
}
pub fn goto_next_named_sibling(&mut self) -> bool {
self.goto_next_sibling_impl(true)
}
fn goto_prev_sibling_impl(&mut self, named: bool) -> bool {
let sibling = if named {
self.cursor.prev_named_sibling()
} else {
self.cursor.prev_sibling()
};
if let Some(sibling) = sibling {
self.cursor = sibling; self.cursor = sibling;
true true
} else { } else {
@ -139,6 +188,14 @@ impl<'a> TreeCursor<'a> {
} }
} }
pub fn goto_prev_sibling(&mut self) -> bool {
self.goto_prev_sibling_impl(false)
}
pub fn goto_prev_named_sibling(&mut self) -> bool {
self.goto_prev_sibling_impl(true)
}
/// Finds the injection layer that contains the given start-end range. /// Finds the injection layer that contains the given start-end range.
fn layer_id_containing_byte_range(&self, start: usize, end: usize) -> LayerId { fn layer_id_containing_byte_range(&self, start: usize, end: usize) -> LayerId {
let start_idx = self let start_idx = self
@ -157,4 +214,51 @@ impl<'a> TreeCursor<'a> {
let root = self.layers[self.current].tree().root_node(); let root = self.layers[self.current].tree().root_node();
self.cursor = root.descendant_for_byte_range(start, end).unwrap_or(root); self.cursor = root.descendant_for_byte_range(start, end).unwrap_or(root);
} }
/// Returns an iterator over the children of the node the TreeCursor is on
/// at the time this is called.
pub fn children(&'a mut self) -> ChildIter {
let parent = self.node();
ChildIter {
cursor: self,
parent,
named: false,
}
}
/// Returns an iterator over the named children of the node the TreeCursor is on
/// at the time this is called.
pub fn named_children(&'a mut self) -> ChildIter {
let parent = self.node();
ChildIter {
cursor: self,
parent,
named: true,
}
}
}
pub struct ChildIter<'n> {
cursor: &'n mut TreeCursor<'n>,
parent: Node<'n>,
named: bool,
}
impl<'n> Iterator for ChildIter<'n> {
type Item = Node<'n>;
fn next(&mut self) -> Option<Self::Item> {
// first iteration, just visit the first child
if self.cursor.node() == self.parent {
self.cursor
.goto_first_child_impl(self.named)
.then(|| self.cursor.node())
} else {
self.cursor
.goto_next_sibling_impl(self.named)
.then(|| self.cursor.node())
}
}
} }

@ -38,7 +38,7 @@ use helix_core::{
textobject, textobject,
unicode::width::UnicodeWidthChar, unicode::width::UnicodeWidthChar,
visual_offset_from_block, Deletion, LineEnding, Position, Range, Rope, RopeGraphemes, visual_offset_from_block, Deletion, LineEnding, Position, Range, Rope, RopeGraphemes,
RopeReader, RopeSlice, Selection, SmallVec, Tendril, Transaction, RopeReader, RopeSlice, Selection, SmallVec, Syntax, Tendril, Transaction,
}; };
use helix_view::{ use helix_view::{
document::{FormatterError, Mode, SCRATCH_BUFFER_NAME}, document::{FormatterError, Mode, SCRATCH_BUFFER_NAME},
@ -4976,17 +4976,23 @@ pub fn extend_parent_node_start(cx: &mut Context) {
move_node_bound_impl(cx, Direction::Backward, Movement::Extend) move_node_bound_impl(cx, Direction::Backward, Movement::Extend)
} }
fn select_all_siblings(cx: &mut Context) { fn select_all_impl<F>(editor: &mut Editor, select_fn: F)
let motion = |editor: &mut Editor| { where
F: Fn(&Syntax, RopeSlice, Selection) -> Selection,
{
let (view, doc) = current!(editor); let (view, doc) = current!(editor);
if let Some(syntax) = doc.syntax() { if let Some(syntax) = doc.syntax() {
let text = doc.text().slice(..); let text = doc.text().slice(..);
let current_selection = doc.selection(view.id); let current_selection = doc.selection(view.id);
let selection = let selection = select_fn(syntax, text, current_selection.clone());
object::select_all_siblings(syntax.tree(), text, current_selection.clone());
doc.set_selection(view.id, selection); doc.set_selection(view.id, selection);
} }
}
fn select_all_siblings(cx: &mut Context) {
let motion = |editor: &mut Editor| {
select_all_impl(editor, object::select_all_siblings);
}; };
cx.editor.apply_motion(motion); cx.editor.apply_motion(motion);
@ -4994,19 +5000,10 @@ fn select_all_siblings(cx: &mut Context) {
fn select_all_children(cx: &mut Context) { fn select_all_children(cx: &mut Context) {
let motion = |editor: &mut Editor| { let motion = |editor: &mut Editor| {
let (view, doc) = current!(editor); select_all_impl(editor, object::select_all_children);
if let Some(syntax) = doc.syntax() {
let text = doc.text().slice(..);
let current_selection = doc.selection(view.id);
let selection =
object::select_all_children(syntax.tree(), text, current_selection.clone());
doc.set_selection(view.id, selection);
}
}; };
motion(cx.editor); cx.editor.apply_motion(motion);
cx.editor.last_motion = Some(Motion(Box::new(motion)));
} }
fn match_brackets(cx: &mut Context) { fn match_brackets(cx: &mut Context) {
@ -6040,7 +6037,10 @@ fn jump_to_label(cx: &mut Context, labels: Vec<Range>, behaviour: Movement) {
let doc = doc.id(); let doc = doc.id();
cx.on_next_key(move |cx, event| { cx.on_next_key(move |cx, event| {
let alphabet = &cx.editor.config().jump_label_alphabet; let alphabet = &cx.editor.config().jump_label_alphabet;
let Some(i ) = event.char().and_then(|ch| alphabet.iter().position(|&it| it == ch)) else { let Some(i) = event
.char()
.and_then(|ch| alphabet.iter().position(|&it| it == ch))
else {
doc_mut!(cx.editor, &doc).remove_jump_labels(view); doc_mut!(cx.editor, &doc).remove_jump_labels(view);
return; return;
}; };
@ -6053,7 +6053,10 @@ fn jump_to_label(cx: &mut Context, labels: Vec<Range>, behaviour: Movement) {
cx.on_next_key(move |cx, event| { cx.on_next_key(move |cx, event| {
doc_mut!(cx.editor, &doc).remove_jump_labels(view); doc_mut!(cx.editor, &doc).remove_jump_labels(view);
let alphabet = &cx.editor.config().jump_label_alphabet; let alphabet = &cx.editor.config().jump_label_alphabet;
let Some(inner ) = event.char().and_then(|ch| alphabet.iter().position(|&it| it == ch)) else { let Some(inner) = event
.char()
.and_then(|ch| alphabet.iter().position(|&it| it == ch))
else {
return; return;
}; };
if let Some(mut range) = labels.get(outer + inner).copied() { if let Some(mut range) = labels.get(outer + inner).copied() {

@ -607,16 +607,16 @@ async fn select_all_children() -> anyhow::Result<()> {
let tests = vec![ let tests = vec![
// basic tests // basic tests
( (
helpers::platform_line(indoc! {r##" indoc! {r##"
let foo = bar#[(a, b, c)|]#; let foo = bar#[(a, b, c)|]#;
"##}), "##},
"<A-I>", "<A-I>",
helpers::platform_line(indoc! {r##" indoc! {r##"
let foo = bar(#[a|]#, #(b|)#, #(c|)#); let foo = bar(#[a|]#, #(b|)#, #(c|)#);
"##}), "##},
), ),
( (
helpers::platform_line(indoc! {r##" indoc! {r##"
let a = #[[ let a = #[[
1, 1,
2, 2,
@ -624,9 +624,9 @@ async fn select_all_children() -> anyhow::Result<()> {
4, 4,
5, 5,
]|]#; ]|]#;
"##}), "##},
"<A-I>", "<A-I>",
helpers::platform_line(indoc! {r##" indoc! {r##"
let a = [ let a = [
#[1|]#, #[1|]#,
#(2|)#, #(2|)#,
@ -634,11 +634,11 @@ async fn select_all_children() -> anyhow::Result<()> {
#(4|)#, #(4|)#,
#(5|)#, #(5|)#,
]; ];
"##}), "##},
), ),
// direction is preserved // direction is preserved
( (
helpers::platform_line(indoc! {r##" indoc! {r##"
let a = #[|[ let a = #[|[
1, 1,
2, 2,
@ -646,9 +646,9 @@ async fn select_all_children() -> anyhow::Result<()> {
4, 4,
5, 5,
]]#; ]]#;
"##}), "##},
"<A-I>", "<A-I>",
helpers::platform_line(indoc! {r##" indoc! {r##"
let a = [ let a = [
#[|1]#, #[|1]#,
#(|2)#, #(|2)#,
@ -656,11 +656,11 @@ async fn select_all_children() -> anyhow::Result<()> {
#(|4)#, #(|4)#,
#(|5)#, #(|5)#,
]; ];
"##}), "##},
), ),
// can't pick any more children - selection stays the same // can't pick any more children - selection stays the same
( (
helpers::platform_line(indoc! {r##" indoc! {r##"
let a = [ let a = [
#[1|]#, #[1|]#,
#(2|)#, #(2|)#,
@ -668,9 +668,9 @@ async fn select_all_children() -> anyhow::Result<()> {
#(4|)#, #(4|)#,
#(5|)#, #(5|)#,
]; ];
"##}), "##},
"<A-I>", "<A-I>",
helpers::platform_line(indoc! {r##" indoc! {r##"
let a = [ let a = [
#[1|]#, #[1|]#,
#(2|)#, #(2|)#,
@ -678,11 +678,11 @@ async fn select_all_children() -> anyhow::Result<()> {
#(4|)#, #(4|)#,
#(5|)#, #(5|)#,
]; ];
"##}), "##},
), ),
// each cursor does the sibling select independently // each cursor does the sibling select independently
( (
helpers::platform_line(indoc! {r##" indoc! {r##"
let a = #[|[ let a = #[|[
1, 1,
2, 2,
@ -698,9 +698,9 @@ async fn select_all_children() -> anyhow::Result<()> {
"four", "four",
"five", "five",
]|)#; ]|)#;
"##}), "##},
"<A-I>", "<A-I>",
helpers::platform_line(indoc! {r##" indoc! {r##"
let a = [ let a = [
#[|1]#, #[|1]#,
#(|2)#, #(|2)#,
@ -716,7 +716,7 @@ async fn select_all_children() -> anyhow::Result<()> {
#("four"|)#, #("four"|)#,
#("five"|)#, #("five"|)#,
]; ];
"##}), "##},
), ),
]; ];

Loading…
Cancel
Save