on master help sign in
commands: Implement expand_selection.
6cfb1acBlaž Hrastnik
helix-core/src/lib.rs+1
@@ -5,6 +5,7 @@ pub mod graphemes;
5mod history;
5mod history;
6pub mod indent;
6pub mod indent;
7pub mod macros;
7pub mod macros;
8+pub mod object;
8mod position;
9mod position;
9pub mod register;
10pub mod register;
10pub mod selection;
11pub 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 @@
1use helix_core::{
1use helix_core::{
2 comment, graphemes,
2 comment, graphemes,
3 indent::TAB_WIDTH,
3 indent::TAB_WIDTH,
4+ object,
4 regex::{self, Regex},
5 regex::{self, Regex},
5 register, selection,
6 register, selection,
6 state::{Direction, Granularity, State},
7 state::{Direction, Granularity, State},
@@ -1023,3 +1024,15 @@ pub fn toggle_comments(cx: &mut Context) {
1023
1024
1024 doc.apply(&transaction);
1025 doc.apply(&transaction);
1025}
1026}
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 {
164 vec![alt!('s')] => commands::split_selection_on_newline,
164 vec![alt!('s')] => commands::split_selection_on_newline,
165 vec![shift!('S')] => commands::split_selection,
165 vec![shift!('S')] => commands::split_selection,
166 vec![key!(';')] => commands::collapse_selection,
166 vec![key!(';')] => commands::collapse_selection,
167− // TODO should be alt(;)
168 vec![alt!(';')] => commands::flip_selections,
167 vec![alt!(';')] => commands::flip_selections,
169 vec![key!('%')] => commands::select_all,
168 vec![key!('%')] => commands::select_all,
170 vec![key!('x')] => commands::select_line,
169 vec![key!('x')] => commands::select_line,
170+ // TODO: figure out what key to use
171+ vec![key!('[')] => commands::expand_selection,
171 vec![key!('/')] => commands::search,
172 vec![key!('/')] => commands::search,
172 vec![key!('n')] => commands::search_next,
173 vec![key!('n')] => commands::search_next,
173 vec![key!('*')] => commands::search_selection,
174 vec![key!('*')] => commands::search_selection,