on master help sign in
commands: Implement expand_selection.
commit6cfb1acb9d1456e854a2c44ee8fc057f45b29ea9 authorBlaž Hrastnik <blaz@mxxn.io> dateMon 22 Feb 2021, 15:50 (6 years ago) parent33c67f1
4 files changed+48−1
helix-core/src/lib.rs+1 helix-core/src/object.rs+32 helix-term/src/commands.rs+13 helix-term/src/keymap.rs+2−1
helix-core/src/lib.rs+1
@@ -5,6 +5,7 @@ pub mod graphemes;
55mod history;
66pub mod indent;
77pub mod macros;
8+pub mod object;
89mod position;
910pub mod register;
1011pub mod selection;
helix-core/src/object.rsnew file+32
@@ -0,0 +1,32 @@
1+use crate::{Range, RopeSlice, Selection, Syntax};
2+use smallvec::smallvec;
3+
4+// TODO: to contract_selection we'd need to store the previous ranges before expand.
5+// Maybe just contract to the first child node?
6+pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: &Selection) -> Selection {
7+ let tree = syntax.root_layer.tree.as_ref().unwrap();
8+
9+ selection.transform(|range| {
10+ let from = text.char_to_byte(range.from());
11+ let to = text.char_to_byte(range.to());
12+
13+ // find parent of a descendant that matches the range
14+ let parent = match tree
15+ .root_node()
16+ .descendant_for_byte_range(from, to)
17+ .and_then(|node| node.parent())
18+ {
19+ Some(parent) => parent,
20+ None => return range,
21+ };
22+
23+ let from = text.byte_to_char(parent.start_byte());
24+ let to = text.byte_to_char(parent.end_byte());
25+
26+ if range.head < range.anchor {
27+ Range::new(to, from)
28+ } else {
29+ Range::new(from, to)
30+ }
31+ })
32+}
helix-term/src/commands.rs+13
@@ -1,6 +1,7 @@
11use helix_core::{
22 comment, graphemes,
33 indent::TAB_WIDTH,
4+ object,
45 regex::{self, Regex},
56 register, selection,
67 state::{Direction, Granularity, State},
@@ -1023,3 +1024,15 @@ pub fn toggle_comments(cx: &mut Context) {
10231024
10241025 doc.apply(&transaction);
10251026}
1027+
1028+// tree sitter node selection
1029+
1030+pub fn expand_selection(cx: &mut Context) {
1031+ let doc = cx.doc();
1032+
1033+ if let Some(syntax) = &doc.syntax {
1034+ let text = doc.text().slice(..);
1035+ let selection = object::expand_selection(syntax, text, doc.selection());
1036+ doc.set_selection(selection);
1037+ }
1038+}
helix-term/src/keymap.rs+2−1
@@ -164,10 +164,11 @@ pub fn default() -> Keymaps {
164164 vec![alt!('s')] => commands::split_selection_on_newline,
165165 vec![shift!('S')] => commands::split_selection,
166166 vec![key!(';')] => commands::collapse_selection,
167− // TODO should be alt(;)
168167 vec![alt!(';')] => commands::flip_selections,
169168 vec![key!('%')] => commands::select_all,
170169 vec![key!('x')] => commands::select_line,
170+ // TODO: figure out what key to use
171+ vec![key!('[')] => commands::expand_selection,
171172 vec![key!('/')] => commands::search,
172173 vec![key!('n')] => commands::search_next,
173174 vec![key!('*')] => commands::search_selection,