aboutsummaryrefslogtreecommitdiff
path: root/helix-core/src/object.rs
diff options
context:
space:
mode:
Diffstat (limited to 'helix-core/src/object.rs')
-rw-r--r--helix-core/src/object.rs29
1 files changed, 27 insertions, 2 deletions
diff --git a/helix-core/src/object.rs b/helix-core/src/object.rs
index 717c5994..21fa24fb 100644
--- a/helix-core/src/object.rs
+++ b/helix-core/src/object.rs
@@ -1,7 +1,5 @@
use crate::{Range, RopeSlice, Selection, Syntax};
-// TODO: to contract_selection we'd need to store the previous ranges before expand.
-// Maybe just contract to the first child node?
pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: &Selection) -> Selection {
let tree = syntax.tree();
@@ -34,3 +32,30 @@ pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: &Selection)
}
})
}
+
+pub fn shrink_selection(syntax: &Syntax, text: RopeSlice, selection: &Selection) -> Selection {
+ let tree = syntax.tree();
+
+ selection.clone().transform(|range| {
+ let from = text.char_to_byte(range.from());
+ let to = text.char_to_byte(range.to());
+
+ let descendant = match tree.root_node().descendant_for_byte_range(from, to) {
+ // find first child, if not possible, fallback to the node that contains selection
+ Some(descendant) => match descendant.child(0) {
+ Some(child) => child,
+ None => descendant,
+ },
+ None => return range,
+ };
+
+ let from = text.byte_to_char(descendant.start_byte());
+ let to = text.byte_to_char(descendant.end_byte());
+
+ if range.head < range.anchor {
+ Range::new(to, from)
+ } else {
+ Range::new(from, to)
+ }
+ })
+}