summaryrefslogtreecommitdiff
path: root/helix-core
diff options
context:
space:
mode:
Diffstat (limited to 'helix-core')
-rw-r--r--helix-core/src/surround.rs145
1 files changed, 116 insertions, 29 deletions
diff --git a/helix-core/src/surround.rs b/helix-core/src/surround.rs
index 64d48c13..f430aee8 100644
--- a/helix-core/src/surround.rs
+++ b/helix-core/src/surround.rs
@@ -275,51 +275,138 @@ mod test {
#[test]
fn test_get_surround_pos() {
- let doc = Rope::from("(some) (chars)\n(newline)");
- let slice = doc.slice(..);
- let selection = Selection::new(
- SmallVec::from_slice(&[Range::point(2), Range::point(9), Range::point(20)]),
- 0,
- );
+ #[rustfmt::skip]
+ let (doc, selection, expectations) =
+ rope_with_selections_and_expectations(
+ "(some) (chars)\n(newline)",
+ "_ ^ _ _ ^ _\n_ ^ _"
+ );
- // cursor on s[o]me, c[h]ars, newl[i]ne
assert_eq!(
- get_surround_pos(slice, &selection, Some('('), 1)
- .unwrap()
- .as_slice(),
- &[0, 5, 7, 13, 15, 23]
+ get_surround_pos(doc.slice(..), &selection, Some('('), 1).unwrap(),
+ expectations
);
}
#[test]
- fn test_get_surround_pos_bail() {
- let doc = Rope::from("[some]\n(chars)xx\n(newline)");
- let slice = doc.slice(..);
+ fn test_get_surround_pos_bail_different_surround_chars() {
+ #[rustfmt::skip]
+ let (doc, selection, _) =
+ rope_with_selections_and_expectations(
+ "[some]\n(chars)xx\n(newline)",
+ " ^ \n ^ \n "
+ );
- let selection =
- Selection::new(SmallVec::from_slice(&[Range::point(2), Range::point(9)]), 0);
- // cursor on s[o]me, c[h]ars
assert_eq!(
- get_surround_pos(slice, &selection, Some('('), 1),
- Err(Error::PairNotFound) // different surround chars
+ get_surround_pos(doc.slice(..), &selection, Some('('), 1),
+ Err(Error::PairNotFound)
);
+ }
+
+ #[test]
+ fn test_get_surround_pos_bail_overlapping_surround_chars() {
+ #[rustfmt::skip]
+ let (doc, selection, _) =
+ rope_with_selections_and_expectations(
+ "[some]\n(chars)xx\n(newline)",
+ " \n ^ \n ^ "
+ );
- let selection = Selection::new(
- SmallVec::from_slice(&[Range::point(14), Range::point(24)]),
- 0,
- );
- // cursor on [x]x, newli[n]e
assert_eq!(
- get_surround_pos(slice, &selection, Some('('), 1),
+ get_surround_pos(doc.slice(..), &selection, Some('('), 1),
Err(Error::PairNotFound) // overlapping surround chars
);
+ }
+
+ #[test]
+ fn test_get_surround_pos_bail_cursor_overlap() {
+ #[rustfmt::skip]
+ let (doc, selection, _) =
+ rope_with_selections_and_expectations(
+ "[some]\n(chars)xx\n(newline)",
+ " ^^ \n \n "
+ );
- let selection =
- Selection::new(SmallVec::from_slice(&[Range::point(2), Range::point(3)]), 0);
- // cursor on s[o][m]e
assert_eq!(
- get_surround_pos(slice, &selection, Some('['), 1),
+ get_surround_pos(doc.slice(..), &selection, Some('['), 1),
Err(Error::CursorOverlap)
);
}
+
+ #[test]
+ fn test_find_nth_pairs_pos_quote_success() {
+ #[rustfmt::skip]
+ let (doc, selection, expectations) =
+ rope_with_selections_and_expectations(
+ "some 'quoted text' on this 'line'\n'and this one'",
+ " _ ^ _ \n "
+ );
+
+ assert_eq!(2, expectations.len());
+ assert_eq!(
+ find_nth_pairs_pos(doc.slice(..), '\'', selection.primary(), 1)
+ .expect("find should succeed"),
+ (expectations[0], expectations[1])
+ )
+ }
+
+ #[test]
+ fn test_find_nth_pairs_pos_nested_quote_success() {
+ #[rustfmt::skip]
+ let (doc, selection, expectations) =
+ rope_with_selections_and_expectations(
+ "some 'nested 'quoted' text' on this 'line'\n'and this one'",
+ " _ ^ _ \n "
+ );
+
+ assert_eq!(2, expectations.len());
+ assert_eq!(
+ find_nth_pairs_pos(doc.slice(..), '\'', selection.primary(), 2)
+ .expect("find should succeed"),
+ (expectations[0], expectations[1])
+ )
+ }
+
+ #[test]
+ fn test_find_nth_pairs_pos_inside_quote_ambiguous() {
+ #[rustfmt::skip]
+ let (doc, selection, _) =
+ rope_with_selections_and_expectations(
+ "some 'nested 'quoted' text' on this 'line'\n'and this one'",
+ " ^ \n "
+ );
+
+ assert_eq!(
+ find_nth_pairs_pos(doc.slice(..), '\'', selection.primary(), 1),
+ Err(Error::CursorOnAmbiguousPair)
+ )
+ }
+
+ // Create a Rope and a matching Selection using a specification language.
+ // ^ is a single-point selection.
+ // _ is an expected index. These are returned as a Vec<usize> for use in assertions.
+ fn rope_with_selections_and_expectations(
+ text: &str,
+ spec: &str,
+ ) -> (Rope, Selection, Vec<usize>) {
+ if text.len() != spec.len() {
+ panic!("specification must match text length -- are newlines aligned?");
+ }
+
+ let rope = Rope::from(text);
+
+ let selections: SmallVec<[Range; 1]> = spec
+ .match_indices('^')
+ .into_iter()
+ .map(|(i, _)| Range::point(i))
+ .collect();
+
+ let expectations: Vec<usize> = spec
+ .match_indices('_')
+ .into_iter()
+ .map(|(i, _)| i)
+ .collect();
+
+ (rope, Selection::new(selections, 0), expectations)
+ }
}