Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-core/src/object.rs')
| -rw-r--r-- | helix-core/src/object.rs | 88 |
1 files changed, 24 insertions, 64 deletions
diff --git a/helix-core/src/object.rs b/helix-core/src/object.rs index ff810489..28629235 100644 --- a/helix-core/src/object.rs +++ b/helix-core/src/object.rs @@ -1,5 +1,4 @@ -use crate::{movement::Direction, syntax::TreeCursor, Range, RopeSlice, Selection, Syntax}; -use tree_sitter::{Node, Tree}; +use crate::{syntax::TreeCursor, Range, RopeSlice, Selection, Syntax}; pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { 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> { - while let Some(parent) = node.parent() { - if parent.child_count() > 1 { - return Some(parent); - } - - node = parent; - } - - None -} - -pub fn select_all_siblings(tree: &Tree, text: RopeSlice, selection: Selection) -> Selection { - let root_node = &tree.root_node(); - +pub fn select_all_siblings(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { selection.transform_iter(|range| { - let from = text.char_to_byte(range.from()); - let to = text.char_to_byte(range.to()); + let mut cursor = syntax.walk(); + let (from, to) = range.into_byte_range(text); + cursor.reset_to_byte_range(from, to); + + if !cursor.goto_parent_with(|parent| parent.child_count() > 1) { + return vec![range].into_iter(); + } - 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()) + select_children(&mut cursor, text, range).into_iter() }) } -pub fn select_all_children(tree: &Tree, text: RopeSlice, selection: Selection) -> Selection { - let root_node = &tree.root_node(); - +pub fn select_all_children(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { 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(|parent| select_children(parent, text, range.direction())) - .unwrap_or_else(|| vec![range].into_iter()) + let mut cursor = syntax.walk(); + let (from, to) = range.into_byte_range(text); + cursor.reset_to_byte_range(from, to); + select_children(&mut cursor, text, range).into_iter() }) } -fn select_children( - node: Node, +fn select_children<'n>( + cursor: &'n mut TreeCursor<'n>, text: RopeSlice, - direction: Direction, -) -> Option<<Vec<Range> as std::iter::IntoIterator>::IntoIter> { - let mut cursor = node.walk(); - - let children = node - .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) - } - }) + range: Range, +) -> Vec<Range> { + let children = cursor + .named_children() + .map(|child| Range::from_node(child, text, range.direction())) .collect::<Vec<_>>(); if !children.is_empty() { - Some(children.into_iter()) + children } 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 { select_node_impl(syntax, text, selection, |cursor| { while !cursor.goto_prev_sibling() { |