aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSkyler Hawthorne2022-10-22 21:29:09 +0000
committerMichael Davis2023-03-20 23:34:40 +0000
commitd3b051d28ea62c313fc72583d04f2a897e8d6f40 (patch)
tree3a3ff15f7ba98190720850a4059298f3f0676e24
parent58ea1930544df165a4a1342932e4dd8cb93e14ea (diff)
fix test::plain
test::plain uses char indices when it should use byte indices
-rw-r--r--helix-core/src/movement.rs12
-rw-r--r--helix-core/src/test.rs102
-rw-r--r--helix-core/src/textobject.rs6
-rw-r--r--helix-term/tests/test/helpers.rs4
4 files changed, 109 insertions, 15 deletions
diff --git a/helix-core/src/movement.rs b/helix-core/src/movement.rs
index bbb37bf4..60af47e5 100644
--- a/helix-core/src/movement.rs
+++ b/helix-core/src/movement.rs
@@ -1474,7 +1474,7 @@ mod test {
let text = Rope::from(s.as_str());
let selection =
selection.transform(|r| move_prev_paragraph(text.slice(..), r, 1, Movement::Move));
- let actual = crate::test::plain(&s, &selection);
+ let actual = crate::test::plain(s.as_ref(), &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
@@ -1497,7 +1497,7 @@ mod test {
let text = Rope::from(s.as_str());
let selection =
selection.transform(|r| move_prev_paragraph(text.slice(..), r, 2, Movement::Move));
- let actual = crate::test::plain(&s, &selection);
+ let actual = crate::test::plain(s.as_ref(), &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
@@ -1520,7 +1520,7 @@ mod test {
let text = Rope::from(s.as_str());
let selection = selection
.transform(|r| move_prev_paragraph(text.slice(..), r, 1, Movement::Extend));
- let actual = crate::test::plain(&s, &selection);
+ let actual = crate::test::plain(s.as_ref(), &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
@@ -1562,7 +1562,7 @@ mod test {
let text = Rope::from(s.as_str());
let selection =
selection.transform(|r| move_next_paragraph(text.slice(..), r, 1, Movement::Move));
- let actual = crate::test::plain(&s, &selection);
+ let actual = crate::test::plain(s.as_ref(), &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
@@ -1585,7 +1585,7 @@ mod test {
let text = Rope::from(s.as_str());
let selection =
selection.transform(|r| move_next_paragraph(text.slice(..), r, 2, Movement::Move));
- let actual = crate::test::plain(&s, &selection);
+ let actual = crate::test::plain(s.as_ref(), &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
@@ -1608,7 +1608,7 @@ mod test {
let text = Rope::from(s.as_str());
let selection = selection
.transform(|r| move_next_paragraph(text.slice(..), r, 1, Movement::Extend));
- let actual = crate::test::plain(&s, &selection);
+ let actual = crate::test::plain(s.as_ref(), &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
diff --git a/helix-core/src/test.rs b/helix-core/src/test.rs
index 1d967f23..7183302c 100644
--- a/helix-core/src/test.rs
+++ b/helix-core/src/test.rs
@@ -1,5 +1,6 @@
//! Test helpers.
use crate::{Range, Selection};
+use ropey::Rope;
use smallvec::SmallVec;
use std::cmp::Reverse;
use unicode_segmentation::UnicodeSegmentation;
@@ -148,10 +149,12 @@ pub fn print(s: &str) -> (String, Selection) {
/// "#[a|]#b#(|c)#".to_owned()
/// );
/// ```
-pub fn plain(s: &str, selection: &Selection) -> String {
+pub fn plain<R: Into<Rope>>(s: R, selection: &Selection) -> String {
+ let s = s.into();
let primary = selection.primary_index();
- let mut out = String::with_capacity(s.len() + 5 * selection.len());
- out.push_str(s);
+ let mut out = String::with_capacity(s.len_bytes() + 5 * selection.len());
+ out.push_str(&s.to_string());
+
let mut insertion: Vec<_> = selection
.iter()
.enumerate()
@@ -164,7 +167,9 @@ pub fn plain(s: &str, selection: &Selection) -> String {
(false, false) => [(range.anchor, ")#"), (range.head, "#(|")],
}
})
+ .map(|(char_idx, marker)| (s.char_to_byte(char_idx), marker))
.collect();
+
// insert in reverse order
insertion.sort_unstable_by_key(|k| Reverse(k.0));
for (i, s) in insertion {
@@ -173,7 +178,6 @@ pub fn plain(s: &str, selection: &Selection) -> String {
out
}
-#[allow(clippy::module_inception)]
#[cfg(test)]
#[allow(clippy::module_inception)]
mod test {
@@ -289,4 +293,94 @@ mod test {
print("hello #[|πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦]# goodbye")
);
}
+
+ #[test]
+ fn plain_single() {
+ assert_eq!("#[|h]#ello", plain("hello", &Selection::single(1, 0)));
+ assert_eq!("#[h|]#ello", plain("hello", &Selection::single(0, 1)));
+ assert_eq!("#[|hell]#o", plain("hello", &Selection::single(4, 0)));
+ assert_eq!("#[hell|]#o", plain("hello", &Selection::single(0, 4)));
+ assert_eq!("#[|hello]#", plain("hello", &Selection::single(5, 0)));
+ assert_eq!("#[hello|]#", plain("hello", &Selection::single(0, 5)));
+ }
+
+ #[test]
+ fn plain_multi() {
+ assert_eq!(
+ plain(
+ "hello",
+ &Selection::new(
+ SmallVec::from_slice(&[Range::new(1, 0), Range::new(5, 4)]),
+ 0
+ )
+ ),
+ String::from("#[|h]#ell#(|o)#")
+ );
+ assert_eq!(
+ plain(
+ "hello",
+ &Selection::new(
+ SmallVec::from_slice(&[Range::new(0, 1), Range::new(4, 5)]),
+ 0
+ )
+ ),
+ String::from("#[h|]#ell#(o|)#")
+ );
+ assert_eq!(
+ plain(
+ "hello",
+ &Selection::new(
+ SmallVec::from_slice(&[Range::new(2, 0), Range::new(5, 3)]),
+ 0
+ )
+ ),
+ String::from("#[|he]#l#(|lo)#")
+ );
+ assert_eq!(
+ plain(
+ "hello\r\nhello\r\nhello\r\n",
+ &Selection::new(
+ SmallVec::from_slice(&[
+ Range::new(7, 5),
+ Range::new(21, 19),
+ Range::new(14, 12)
+ ]),
+ 0
+ )
+ ),
+ String::from("hello#[|\r\n]#hello#(|\r\n)#hello#(|\r\n)#")
+ );
+ }
+
+ #[test]
+ fn plain_multi_byte_code_point() {
+ assert_eq!(
+ plain("β€žβ€œ", &Selection::single(1, 0)),
+ String::from("#[|β€ž]#β€œ")
+ );
+ assert_eq!(
+ plain("β€žβ€œ", &Selection::single(2, 1)),
+ String::from("β€ž#[|β€œ]#")
+ );
+ assert_eq!(
+ plain("β€žβ€œ", &Selection::single(0, 1)),
+ String::from("#[β€ž|]#β€œ")
+ );
+ assert_eq!(
+ plain("β€žβ€œ", &Selection::single(1, 2)),
+ String::from("β€ž#[β€œ|]#")
+ );
+ assert_eq!(
+ plain("they said β€žhelloβ€œ", &Selection::single(11, 10)),
+ String::from("they said #[|β€ž]#helloβ€œ")
+ );
+ }
+
+ #[test]
+ fn plain_multi_code_point_grapheme() {
+ assert_eq!(
+ plain("hello πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦ goodbye", &Selection::single(13, 6)),
+ String::from("hello #[|πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦]# goodbye")
+ );
+ }
}
diff --git a/helix-core/src/textobject.rs b/helix-core/src/textobject.rs
index 6e3f18cf..bf00a458 100644
--- a/helix-core/src/textobject.rs
+++ b/helix-core/src/textobject.rs
@@ -437,7 +437,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, &selection);
+ let actual = crate::test::plain(s.as_ref(), &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
@@ -460,7 +460,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, &selection);
+ let actual = crate::test::plain(s.as_ref(), &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
@@ -491,7 +491,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, &selection);
+ let actual = crate::test::plain(s.as_ref(), &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
diff --git a/helix-term/tests/test/helpers.rs b/helix-term/tests/test/helpers.rs
index de81f758..77332fa5 100644
--- a/helix-term/tests/test/helpers.rs
+++ b/helix-term/tests/test/helpers.rs
@@ -65,7 +65,7 @@ pub async fn test_key_sequences(
for (i, (in_keys, test_fn)) in inputs.into_iter().enumerate() {
let (view, doc) = current_ref!(app.editor);
- let state = test::plain(&doc.text().to_string(), doc.selection(view.id));
+ let state = test::plain(doc.text().slice(..), doc.selection(view.id));
log::debug!("executing test with document state:\n\n-----\n\n{}", state);
@@ -81,7 +81,7 @@ pub async fn test_key_sequences(
if !app_exited {
let (view, doc) = current_ref!(app.editor);
- let state = test::plain(&doc.text().to_string(), doc.selection(view.id));
+ let state = test::plain(doc.text().slice(..), doc.selection(view.id));
log::debug!(
"finished running test with document state:\n\n-----\n\n{}",