diff options
author | Michael Davis | 2024-01-10 19:31:05 +0000 |
---|---|---|
committer | Blaž Hrastnik | 2024-03-23 06:32:34 +0000 |
commit | 68b21578ac4b5ded1a262469c6887794a689284f (patch) | |
tree | fbffe454d89c9502cd64a714b420b4115294535b /helix-term | |
parent | b1222f06640c02feb1b87b988d6bca53fdddb9c0 (diff) |
Reimplement tree motions in terms of syntax::TreeCursor
This uses the new TreeCursor type from the parent commit to reimplement
the tree-sitter motions (`A-p/o/i/n`). Other tree-sitter related
features like textobjects are not touched with this change and will
need a different, unrelated approach to solve.
Diffstat (limited to 'helix-term')
-rw-r--r-- | helix-term/src/commands.rs | 14 | ||||
-rw-r--r-- | helix-term/tests/test/movement.rs | 57 |
2 files changed, 63 insertions, 8 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 291ab1fe..ff72cee1 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -26,7 +26,6 @@ use helix_core::{ syntax::{BlockCommentToken, LanguageServerFeature}, text_annotations::TextAnnotations, textobject, - tree_sitter::Node, unicode::width::UnicodeWidthChar, visual_offset_from_block, Deletion, LineEnding, Position, Range, Rope, RopeGraphemes, RopeReader, RopeSlice, Selection, SmallVec, Tendril, Transaction, @@ -4775,18 +4774,17 @@ fn shrink_selection(cx: &mut Context) { cx.editor.apply_motion(motion); } -fn select_sibling_impl<F>(cx: &mut Context, sibling_fn: &'static F) +fn select_sibling_impl<F>(cx: &mut Context, sibling_fn: F) where - F: Fn(Node) -> Option<Node>, + F: Fn(&helix_core::Syntax, RopeSlice, Selection) -> Selection + 'static, { - let motion = |editor: &mut Editor| { + let motion = move |editor: &mut Editor| { let (view, doc) = current!(editor); if let Some(syntax) = doc.syntax() { let text = doc.text().slice(..); let current_selection = doc.selection(view.id); - let selection = - object::select_sibling(syntax, text, current_selection.clone(), sibling_fn); + let selection = sibling_fn(syntax, text, current_selection.clone()); doc.set_selection(view.id, selection); } }; @@ -4794,11 +4792,11 @@ where } fn select_next_sibling(cx: &mut Context) { - select_sibling_impl(cx, &|node| Node::next_sibling(&node)) + select_sibling_impl(cx, object::select_next_sibling) } fn select_prev_sibling(cx: &mut Context) { - select_sibling_impl(cx, &|node| Node::prev_sibling(&node)) + select_sibling_impl(cx, object::select_prev_sibling) } fn move_node_bound_impl(cx: &mut Context, dir: Direction, movement: Movement) { diff --git a/helix-term/tests/test/movement.rs b/helix-term/tests/test/movement.rs index 4ebaae85..1c25032c 100644 --- a/helix-term/tests/test/movement.rs +++ b/helix-term/tests/test/movement.rs @@ -635,3 +635,60 @@ async fn test_surround_delete() -> anyhow::Result<()> { Ok(()) } + +#[tokio::test(flavor = "multi_thread")] +async fn tree_sitter_motions_work_across_injections() -> anyhow::Result<()> { + test_with_config( + AppBuilder::new().with_file("foo.html", None), + ( + "<script>let #[|x]# = 1;</script>", + "<A-o>", + "<script>let #[|x = 1]#;</script>", + ), + ) + .await?; + + // When the full injected layer is selected, expand_selection jumps to + // a more shallow layer. + test_with_config( + AppBuilder::new().with_file("foo.html", None), + ( + "<script>#[|let x = 1;]#</script>", + "<A-o>", + "#[|<script>let x = 1;</script>]#", + ), + ) + .await?; + + test_with_config( + AppBuilder::new().with_file("foo.html", None), + ( + "<script>let #[|x = 1]#;</script>", + "<A-i>", + "<script>let #[|x]# = 1;</script>", + ), + ) + .await?; + + test_with_config( + AppBuilder::new().with_file("foo.html", None), + ( + "<script>let #[|x]# = 1;</script>", + "<A-n>", + "<script>let x #[|=]# 1;</script>", + ), + ) + .await?; + + test_with_config( + AppBuilder::new().with_file("foo.html", None), + ( + "<script>let #[|x]# = 1;</script>", + "<A-p>", + "<script>#[|let]# x = 1;</script>", + ), + ) + .await?; + + Ok(()) +} |