on 376c19e help sign in
helix/helix-core/src/object.rs
76 lines 2.0 kB history raw
1use crate::{Range, RopeSlice, Selection, Syntax};
2use tree_sitter::Node;
4pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
5 select_node_impl(syntax, text, selection, |mut node, from, to| {
6 while node.start_byte() == from && node.end_byte() == to {
7 node = node.parent()?;
8 }
9 Some(node)
10 })
13pub fn shrink_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
14 select_node_impl(syntax, text, selection, |descendant, _from, _to| {
15 descendant.child(0).or(Some(descendant))
16 })
19pub fn select_sibling<F>(
20 syntax: &Syntax,
21 text: RopeSlice,
22 selection: Selection,
23 sibling_fn: &F,
24) -> Selection
25where
26 F: Fn(Node) -> Option<Node>,
28 select_node_impl(syntax, text, selection, |descendant, _from, _to| {
29 find_sibling_recursive(descendant, sibling_fn)
30 })
33fn find_sibling_recursive<F>(node: Node, sibling_fn: F) -> Option<Node>
34where
35 F: Fn(Node) -> Option<Node>,
37 sibling_fn(node).or_else(|| {
38 node.parent()
39 .and_then(|node| find_sibling_recursive(node, sibling_fn))
40 })
43fn select_node_impl<F>(
44 syntax: &Syntax,
45 text: RopeSlice,
46 selection: Selection,
47 select_fn: F,
48) -> Selection
49where
50 F: Fn(Node, usize, usize) -> Option<Node>,
52 let tree = syntax.tree();
54 selection.transform(|range| {
55 let from = text.char_to_byte(range.from());
56 let to = text.char_to_byte(range.to());
58 let node = match tree
59 .root_node()
60 .descendant_for_byte_range(from, to)
61 .and_then(|node| select_fn(node, from, to))
62 {
63 Some(node) => node,
64 None => return range,
65 };
67 let from = text.byte_to_char(node.start_byte());
68 let to = text.byte_to_char(node.end_byte());
70 if range.head < range.anchor {
71 Range::new(to, from)
72 } else {
73 Range::new(from, to)
74 }
75 })