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 | 111 |
1 files changed, 44 insertions, 67 deletions
diff --git a/helix-core/src/object.rs b/helix-core/src/object.rs index e0c02d0a..02e72859 100644 --- a/helix-core/src/object.rs +++ b/helix-core/src/object.rs @@ -25,38 +25,59 @@ pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) } pub fn shrink_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { - select_node_impl( - syntax, - text, - selection, - |cursor| { - cursor.goto_first_child(); - }, - None, - ) + selection.transform(move |range| { + let (from, to) = range.into_byte_range(text); + let mut cursor = syntax.walk(); + cursor.reset_to_byte_range(from, to); + + if let Some(node) = cursor + .into_iter() + .find(|node| node.is_named() && node.is_contained_within(from..to)) + { + return Range::from_node(node, text, range.direction()); + } + + range + }) } pub fn select_next_sibling(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { - select_node_impl( - syntax, - text, - selection, - |cursor| { - while !cursor.goto_next_sibling() { - if !cursor.goto_parent() { - break; - } + selection.transform(move |range| { + let (from, to) = range.into_byte_range(text); + let mut cursor = syntax.walk(); + cursor.reset_to_byte_range(from, to); + + while !cursor.goto_next_sibling() { + if !cursor.goto_parent() { + return range; } - }, - Some(Direction::Forward), - ) + } + + Range::from_node(cursor.node(), text, Direction::Forward) + }) +} + +pub fn select_prev_sibling(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { + selection.transform(move |range| { + let (from, to) = range.into_byte_range(text); + let mut cursor = syntax.walk(); + cursor.reset_to_byte_range(from, to); + + while !cursor.goto_previous_sibling() { + if !cursor.goto_parent() { + return range; + } + } + + Range::from_node(cursor.node(), text, Direction::Backward) + }) } pub fn select_all_siblings(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { let mut cursor = syntax.walk(); selection.transform_iter(move |range| { let (from, to) = range.into_byte_range(text); - cursor.reset_to_byte_range(from as u32, to as u32); + cursor.reset_to_byte_range(from, to); if !cursor.goto_parent_with(|parent| parent.child_count() > 1) { return vec![range].into_iter(); @@ -70,7 +91,7 @@ pub fn select_all_children(syntax: &Syntax, text: RopeSlice, selection: Selectio let mut cursor = syntax.walk(); selection.transform_iter(move |range| { let (from, to) = range.into_byte_range(text); - cursor.reset_to_byte_range(from as u32, to as u32); + cursor.reset_to_byte_range(from, to); select_children(&mut cursor, text, range).into_iter() }) } @@ -88,47 +109,3 @@ fn select_children(cursor: &mut TreeCursor, text: RopeSlice, range: Range) -> Ve vec![range] } } - -pub fn select_prev_sibling(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { - select_node_impl( - syntax, - text, - selection, - |cursor| { - while !cursor.goto_previous_sibling() { - if !cursor.goto_parent() { - break; - } - } - }, - Some(Direction::Backward), - ) -} - -fn select_node_impl<F>( - syntax: &Syntax, - text: RopeSlice, - selection: Selection, - motion: F, - direction: Option<Direction>, -) -> Selection -where - F: Fn(&mut TreeCursor), -{ - let cursor = &mut syntax.walk(); - - selection.transform(|range| { - let from = text.char_to_byte(range.from()) as u32; - let to = text.char_to_byte(range.to()) as u32; - - cursor.reset_to_byte_range(from, to); - - motion(cursor); - - let node = cursor.node(); - let from = text.byte_to_char(node.start_byte() as usize); - let to = text.byte_to_char(node.end_byte() as usize); - - Range::new(from, to).with_direction(direction.unwrap_or_else(|| range.direction())) - }) -} |