specify direction for select_prev_sibling and select_next_sibling (#10542)

* specify direction for select_prev_sibling and select_next_sibling

* fix failing integration-test
This commit is contained in:
Krishan 2024-04-23 19:11:03 +05:30 committed by GitHub
parent e18b772654
commit 89a9f2be78
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 117 additions and 18 deletions

View file

@ -1,4 +1,4 @@
use crate::{syntax::TreeCursor, Range, RopeSlice, Selection, Syntax}; use crate::{movement::Direction, syntax::TreeCursor, Range, RopeSlice, Selection, Syntax};
pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
let cursor = &mut syntax.walk(); let cursor = &mut syntax.walk();
@ -25,19 +25,31 @@ pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: Selection)
} }
pub fn shrink_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { pub fn shrink_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
select_node_impl(syntax, text, selection, |cursor| { select_node_impl(
syntax,
text,
selection,
|cursor| {
cursor.goto_first_child(); cursor.goto_first_child();
}) },
None,
)
} }
pub fn select_next_sibling(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { pub fn select_next_sibling(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
select_node_impl(syntax, text, selection, |cursor| { select_node_impl(
syntax,
text,
selection,
|cursor| {
while !cursor.goto_next_sibling() { while !cursor.goto_next_sibling() {
if !cursor.goto_parent() { if !cursor.goto_parent() {
break; break;
} }
} }
}) },
Some(Direction::Forward),
)
} }
pub fn select_all_siblings(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { pub fn select_all_siblings(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
@ -81,13 +93,19 @@ fn select_children<'n>(
} }
pub fn select_prev_sibling(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { pub fn select_prev_sibling(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
select_node_impl(syntax, text, selection, |cursor| { select_node_impl(
syntax,
text,
selection,
|cursor| {
while !cursor.goto_prev_sibling() { while !cursor.goto_prev_sibling() {
if !cursor.goto_parent() { if !cursor.goto_parent() {
break; break;
} }
} }
}) },
Some(Direction::Backward),
)
} }
fn select_node_impl<F>( fn select_node_impl<F>(
@ -95,6 +113,7 @@ fn select_node_impl<F>(
text: RopeSlice, text: RopeSlice,
selection: Selection, selection: Selection,
motion: F, motion: F,
direction: Option<Direction>,
) -> Selection ) -> Selection
where where
F: Fn(&mut TreeCursor), F: Fn(&mut TreeCursor),
@ -113,6 +132,6 @@ where
let from = text.byte_to_char(node.start_byte()); let from = text.byte_to_char(node.start_byte());
let to = text.byte_to_char(node.end_byte()); let to = text.byte_to_char(node.end_byte());
Range::new(from, to).with_direction(range.direction()) Range::new(from, to).with_direction(direction.unwrap_or_else(|| range.direction()))
}) })
} }

View file

@ -726,3 +726,83 @@ async fn select_all_children() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[tokio::test(flavor = "multi_thread")]
async fn test_select_next_sibling() -> anyhow::Result<()> {
let tests = vec![
// basic test
(
indoc! {r##"
fn inc(x: usize) -> usize { x + 1 #[}|]#
fn dec(x: usize) -> usize { x - 1 }
fn ident(x: usize) -> usize { x }
"##},
"<A-n>",
indoc! {r##"
fn inc(x: usize) -> usize { x + 1 }
#[fn dec(x: usize) -> usize { x - 1 }|]#
fn ident(x: usize) -> usize { x }
"##},
),
// direction is not preserved and is always forward.
(
indoc! {r##"
fn inc(x: usize) -> usize { x + 1 #[}|]#
fn dec(x: usize) -> usize { x - 1 }
fn ident(x: usize) -> usize { x }
"##},
"<A-n><A-;><A-n>",
indoc! {r##"
fn inc(x: usize) -> usize { x + 1 }
fn dec(x: usize) -> usize { x - 1 }
#[fn ident(x: usize) -> usize { x }|]#
"##},
),
];
for test in tests {
test_with_config(AppBuilder::new().with_file("foo.rs", None), test).await?;
}
Ok(())
}
#[tokio::test(flavor = "multi_thread")]
async fn test_select_prev_sibling() -> anyhow::Result<()> {
let tests = vec![
// basic test
(
indoc! {r##"
fn inc(x: usize) -> usize { x + 1 }
fn dec(x: usize) -> usize { x - 1 }
#[|f]#n ident(x: usize) -> usize { x }
"##},
"<A-p>",
indoc! {r##"
fn inc(x: usize) -> usize { x + 1 }
#[|fn dec(x: usize) -> usize { x - 1 }]#
fn ident(x: usize) -> usize { x }
"##},
),
// direction is not preserved and is always backward.
(
indoc! {r##"
fn inc(x: usize) -> usize { x + 1 }
fn dec(x: usize) -> usize { x - 1 }
#[|f]#n ident(x: usize) -> usize { x }
"##},
"<A-p><A-;><A-p>",
indoc! {r##"
#[|fn inc(x: usize) -> usize { x + 1 }]#
fn dec(x: usize) -> usize { x - 1 }
fn ident(x: usize) -> usize { x }
"##},
),
];
for test in tests {
test_with_config(AppBuilder::new().with_file("foo.rs", None), test).await?;
}
Ok(())
}

View file

@ -666,7 +666,7 @@ async fn tree_sitter_motions_work_across_injections() -> anyhow::Result<()> {
( (
"<script>let #[|x]# = 1;</script>", "<script>let #[|x]# = 1;</script>",
"<A-n>", "<A-n>",
"<script>let x #[|=]# 1;</script>", "<script>let x #[=|]# 1;</script>",
), ),
) )
.await?; .await?;