on 6c11708 help sign in
helix/helix-core/src/object.rs
77 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, |descendant, from, to| {
6 if descendant.start_byte() == from && descendant.end_byte() == to {
7 descendant.parent()
8 } else {
9 Some(descendant)
10 }
11 })
14pub fn shrink_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
15 select_node_impl(syntax, text, selection, |descendant, _from, _to| {
16 descendant.child(0).or(Some(descendant))
17 })
20pub fn select_sibling<F>(
21 syntax: &Syntax,
22 text: RopeSlice,
23 selection: Selection,
24 sibling_fn: &F,
25) -> Selection
26where
27 F: Fn(Node) -> Option<Node>,
29 select_node_impl(syntax, text, selection, |descendant, _from, _to| {
30 find_sibling_recursive(descendant, sibling_fn)
31 })
34fn find_sibling_recursive<F>(node: Node, sibling_fn: F) -> Option<Node>
35where
36 F: Fn(Node) -> Option<Node>,
38 sibling_fn(node).or_else(|| {
39 node.parent()
40 .and_then(|node| find_sibling_recursive(node, sibling_fn))
41 })
44fn select_node_impl<F>(
45 syntax: &Syntax,
46 text: RopeSlice,
47 selection: Selection,
48 select_fn: F,
49) -> Selection
50where
51 F: Fn(Node, usize, usize) -> Option<Node>,
53 let tree = syntax.tree();
55 selection.transform(|range| {
56 let from = text.char_to_byte(range.from());
57 let to = text.char_to_byte(range.to());
59 let node = match tree
60 .root_node()
61 .descendant_for_byte_range(from, to)
62 .and_then(|node| select_fn(node, from, to))
63 {
64 Some(node) => node,
65 None => return range,
66 };
68 let from = text.byte_to_char(node.start_byte());
69 let to = text.byte_to_char(node.end_byte());
71 if range.head < range.anchor {
72 Range::new(to, from)
73 } else {
74 Range::new(from, to)
75 }
76 })