Wrap selection in siblings if reached boundary sibling

This commit is contained in:
Jakub Kaczor 2024-07-14 23:58:57 +02:00
parent 079f544260
commit 8ea52b33db
2 changed files with 62 additions and 10 deletions

View File

@ -42,11 +42,8 @@ pub fn select_next_sibling(syntax: &Syntax, text: RopeSlice, selection: Selectio
text, text,
selection, selection,
|cursor| { |cursor| {
while !cursor.goto_next_sibling() { cursor.goto_parent_until_has_siblings();
if !cursor.goto_parent() { cursor.goto_next_sibling_or_wrap();
break;
}
}
}, },
Some(Direction::Forward), Some(Direction::Forward),
) )
@ -98,11 +95,8 @@ pub fn select_prev_sibling(syntax: &Syntax, text: RopeSlice, selection: Selectio
text, text,
selection, selection,
|cursor| { |cursor| {
while !cursor.goto_prev_sibling() { cursor.goto_parent_until_has_siblings();
if !cursor.goto_parent() { cursor.goto_prev_sibling_or_wrap();
break;
}
}
}, },
Some(Direction::Backward), Some(Direction::Backward),
) )

View File

@ -103,6 +103,17 @@ pub fn goto_parent_with<P>(&mut self, predicate: P) -> bool
false false
} }
pub fn goto_parent_until_has_siblings(&mut self) {
while self.is_only_child() {
self.goto_parent();
}
}
/// Check if a cursor points to the node that is a child and has no siblings
pub fn is_only_child(&self) -> bool {
self.node().parent().is_some_and(|p| p.child_count() == 1)
}
/// 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
@ -146,6 +157,29 @@ pub fn goto_first_child(&mut self) -> bool {
self.goto_first_child_impl(false) self.goto_first_child_impl(false)
} }
pub fn goto_last_child(&mut self) -> bool {
// Check if the current node's range is an exact injection layer range.
if let Some(layer_id) = self
.layer_id_of_byte_range(self.node().byte_range())
.filter(|&layer_id| layer_id != self.current)
{
// Switch to the child layer.
self.current = layer_id;
self.cursor = self.layers[self.current].tree().root_node();
return true;
}
let child = self.cursor.children(&mut self.cursor.walk()).last();
if let Some(child) = child {
// Otherwise descend in the current tree.
self.cursor = child;
true
} else {
false
}
}
pub fn goto_first_named_child(&mut self) -> bool { pub fn goto_first_named_child(&mut self) -> bool {
self.goto_first_child_impl(true) self.goto_first_child_impl(true)
} }
@ -238,6 +272,30 @@ pub fn named_children(&'a mut self) -> ChildIter {
named: true, named: true,
} }
} }
pub fn goto_first_sibling(&mut self) {
self.goto_parent();
self.goto_first_child();
}
pub fn goto_last_sibling(&mut self) {
self.goto_parent();
self.goto_last_child();
}
pub fn goto_next_sibling_or_wrap(&mut self) {
let went_to_next = self.goto_next_sibling();
if !went_to_next {
self.goto_first_sibling();
}
}
pub fn goto_prev_sibling_or_wrap(&mut self) {
let went_to_prev = self.goto_prev_sibling();
if !went_to_prev {
self.goto_last_sibling();
}
}
} }
pub struct ChildIter<'n> { pub struct ChildIter<'n> {