Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-core/src/textobject.rs')
-rw-r--r--helix-core/src/textobject.rs52
1 files changed, 19 insertions, 33 deletions
diff --git a/helix-core/src/textobject.rs b/helix-core/src/textobject.rs
index 008228f4..76c6d103 100644
--- a/helix-core/src/textobject.rs
+++ b/helix-core/src/textobject.rs
@@ -1,14 +1,15 @@
use std::fmt::Display;
use ropey::RopeSlice;
+use tree_sitter::{Node, QueryCursor};
use crate::chars::{categorize_char, char_is_whitespace, CharCategory};
use crate::graphemes::{next_grapheme_boundary, prev_grapheme_boundary};
use crate::line_ending::rope_is_line_ending;
use crate::movement::Direction;
-use crate::syntax;
+use crate::surround;
+use crate::syntax::LanguageConfiguration;
use crate::Range;
-use crate::{surround, Syntax};
fn find_word_boundary(slice: RopeSlice, mut pos: usize, direction: Direction, long: bool) -> usize {
use CharCategory::{Eol, Whitespace};
@@ -198,28 +199,25 @@ pub fn textobject_paragraph(
}
pub fn textobject_pair_surround(
- syntax: Option<&Syntax>,
slice: RopeSlice,
range: Range,
textobject: TextObject,
ch: char,
count: usize,
) -> Range {
- textobject_pair_surround_impl(syntax, slice, range, textobject, Some(ch), count)
+ textobject_pair_surround_impl(slice, range, textobject, Some(ch), count)
}
pub fn textobject_pair_surround_closest(
- syntax: Option<&Syntax>,
slice: RopeSlice,
range: Range,
textobject: TextObject,
count: usize,
) -> Range {
- textobject_pair_surround_impl(syntax, slice, range, textobject, None, count)
+ textobject_pair_surround_impl(slice, range, textobject, None, count)
}
fn textobject_pair_surround_impl(
- syntax: Option<&Syntax>,
slice: RopeSlice,
range: Range,
textobject: TextObject,
@@ -228,24 +226,13 @@ fn textobject_pair_surround_impl(
) -> Range {
let pair_pos = match ch {
Some(ch) => surround::find_nth_pairs_pos(slice, ch, range, count),
- None => surround::find_nth_closest_pairs_pos(syntax, slice, range, count),
+ // Automatically find the closest surround pairs
+ None => surround::find_nth_closest_pairs_pos(slice, range, count),
};
pair_pos
.map(|(anchor, head)| match textobject {
- TextObject::Inside => {
- if anchor < head {
- Range::new(next_grapheme_boundary(slice, anchor), head)
- } else {
- Range::new(anchor, next_grapheme_boundary(slice, head))
- }
- }
- TextObject::Around => {
- if anchor < head {
- Range::new(anchor, next_grapheme_boundary(slice, head))
- } else {
- Range::new(next_grapheme_boundary(slice, anchor), head)
- }
- }
+ TextObject::Inside => Range::new(next_grapheme_boundary(slice, anchor), head),
+ TextObject::Around => Range::new(anchor, next_grapheme_boundary(slice, head)),
TextObject::Movement => unreachable!(),
})
.unwrap_or(range)
@@ -259,18 +246,18 @@ pub fn textobject_treesitter(
range: Range,
textobject: TextObject,
object_name: &str,
- syntax: &Syntax,
- loader: &syntax::Loader,
+ slice_tree: Node,
+ lang_config: &LanguageConfiguration,
_count: usize,
) -> Range {
- let root = syntax.tree().root_node();
- let textobject_query = loader.textobject_query(syntax.root_language());
let get_range = move || -> Option<Range> {
let byte_pos = slice.char_to_byte(range.cursor(slice));
let capture_name = format!("{}.{}", object_name, textobject); // eg. function.inner
- let node = textobject_query?
- .capture_nodes(&capture_name, &root, slice)?
+ let mut cursor = QueryCursor::new();
+ let node = lang_config
+ .textobject_query()?
+ .capture_nodes(&capture_name, slice_tree, slice, &mut cursor)?
.filter(|node| node.byte_range().contains(&byte_pos))
.min_by_key(|node| node.byte_range().len())?;
@@ -438,7 +425,7 @@ mod test {
let text = Rope::from(s.as_str());
let selection = selection
.transform(|r| textobject_paragraph(text.slice(..), r, TextObject::Inside, 1));
- let actual = crate::test::plain(s.as_ref(), &selection);
+ let actual = crate::test::plain(&s, selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
@@ -461,7 +448,7 @@ mod test {
let text = Rope::from(s.as_str());
let selection = selection
.transform(|r| textobject_paragraph(text.slice(..), r, TextObject::Inside, 2));
- let actual = crate::test::plain(s.as_ref(), &selection);
+ let actual = crate::test::plain(&s, selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
@@ -492,7 +479,7 @@ mod test {
let text = Rope::from(s.as_str());
let selection = selection
.transform(|r| textobject_paragraph(text.slice(..), r, TextObject::Around, 1));
- let actual = crate::test::plain(s.as_ref(), &selection);
+ let actual = crate::test::plain(&s, selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
@@ -575,8 +562,7 @@ mod test {
let slice = doc.slice(..);
for &case in scenario {
let (pos, objtype, expected_range, ch, count) = case;
- let result =
- textobject_pair_surround(None, slice, Range::point(pos), objtype, ch, count);
+ let result = textobject_pair_surround(slice, Range::point(pos), objtype, ch, count);
assert_eq!(
result,
expected_range.into(),