diff --git a/helix-core/src/surround.rs b/helix-core/src/surround.rs index b96cce5a0664d..0ca20e44bf5d6 100644 --- a/helix-core/src/surround.rs +++ b/helix-core/src/surround.rs @@ -1,4 +1,4 @@ -use std::fmt::Display; +use std::{cmp, fmt::Display}; use crate::{movement::Direction, search, Range, Selection}; use ropey::RopeSlice; @@ -52,6 +52,9 @@ pub fn get_pair(ch: char) -> (char, char) { .unwrap_or((ch, ch)) } +/// Find the position of surround pairs of any [`PAIRS`]. +/// +/// Be careful, the second position in return tuple can be to the left of the first position if the range is backward. pub fn find_nth_closest_pairs_pos( text: RopeSlice, range: Range, @@ -253,10 +256,18 @@ pub fn get_surround_pos( let mut change_pos = Vec::new(); for &range in selection { - let (open_pos, close_pos) = match ch { - Some(ch) => find_nth_pairs_pos(text, ch, range, skip)?, - None => find_nth_closest_pairs_pos(text, range, skip)?, + let (open_pos, close_pos) = { + let (lhs, rhs) = match ch { + Some(ch) => find_nth_pairs_pos(text, ch, range, skip)?, + None => find_nth_closest_pairs_pos(text, range, skip)?, + }; + // If the direction of the range is backward, the second value is to the left of the first. + (cmp::min(lhs, rhs), cmp::max(lhs, rhs)) }; + + // WARN this will not find overlaps when use `m` (None) as find character. + // E.g. "( < c ( > c ) )", c - cursor. Change_pos = [3, 11, 7, 15]. + // Overlaps occurs but this condition didn't find it because pairs have different open/close chars. if change_pos.contains(&open_pos) || change_pos.contains(&close_pos) { return Err(Error::CursorOverlap); } diff --git a/helix-term/tests/test/commands.rs b/helix-term/tests/test/commands.rs index b3e1355106323..f838f1ca9d620 100644 --- a/helix-term/tests/test/commands.rs +++ b/helix-term/tests/test/commands.rs @@ -480,3 +480,12 @@ fn bar() {#(\n|)#\ Ok(()) } + +#[tokio::test(flavor = "multi_thread")] +async fn surround_delete() -> anyhow::Result<()> { + // Test `surround_delete` when head < anchor + test(("(#[| ]#)", "mdm", "#[| ]#")).await?; + test(("(#[| ]#)", "md(", "#[| ]#")).await?; + + Ok(()) +}