Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integration test helper improvements #6156

Merged
merged 7 commits into from
Mar 20, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Allow explicit newlines in test DSL
The current test DSL currently has no way to express being at the end of
a line, save for putting an explicit LF or CRLF inside the `#[|]#`. The
problem with this approach is that it can add unintended extra new lines
if used in conjunction with raw strings, which insert newlines for you.

This is a simple attempt to mitigate this problem. If there is an
explicit newline character at the end of the selection, and then it
is immediately followed by the same newline character at the right end
of the selection, this following newline is removed. This way, one can
express a cursor at the end of a line explicitly.
  • Loading branch information
dead10ck committed Mar 19, 2023
commit 4cb06ce1d2015c10d013359b8854663ca42d90cb
53 changes: 30 additions & 23 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions helix-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,4 @@ textwrap = "0.16.0"

[dev-dependencies]
quickcheck = { version = "1", default-features = false }
indoc = "1.0.6"
14 changes: 7 additions & 7 deletions helix-core/src/movement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
Expand All @@ -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, &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
Expand All @@ -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, &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
Expand All @@ -1540,7 +1540,7 @@ mod test {
"a\nb\n\n#[goto\nthird\n\n|]#paragraph",
),
(
"a\nb#[\n|]#\ngoto\nsecond\n\nparagraph",
"a\nb#[\n|]#\n\ngoto\nsecond\n\nparagraph",
"a\nb#[\n\n|]#goto\nsecond\n\nparagraph",
),
(
Expand All @@ -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, &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
Expand All @@ -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, &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
Expand All @@ -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, &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
Expand Down
59 changes: 43 additions & 16 deletions helix-core/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use crate::{Range, Selection};
use smallvec::SmallVec;
use std::cmp::Reverse;
use unicode_segmentation::UnicodeSegmentation;

/// Convert annotated test string to test string and selection.
///
Expand All @@ -10,6 +11,10 @@ use std::cmp::Reverse;
/// `#[` for primary selection with head after anchor followed by `|]#`.
/// `#(` for secondary selection with head after anchor followed by `|)#`.
///
/// If the selection contains any LF or CRLF sequences, which are immediately
/// followed by the same grapheme, then the subsequent one is removed. This is
/// to allow representing having the cursor over the end of the line.
///
/// # Examples
///
/// ```
Expand All @@ -30,23 +35,23 @@ use std::cmp::Reverse;
pub fn print(s: &str) -> (String, Selection) {
let mut primary_idx = None;
let mut ranges = SmallVec::new();
let mut iter = s.chars().peekable();
let mut iter = UnicodeSegmentation::graphemes(s, true).peekable();
let mut left = String::with_capacity(s.len());

'outer: while let Some(c) = iter.next() {
let start = left.chars().count();

if c != '#' {
left.push(c);
if c != "#" {
left.push_str(c);
continue;
}

let (is_primary, close_pair) = match iter.next() {
Some('[') => (true, ']'),
Some('(') => (false, ')'),
Some("[") => (true, "]"),
Some("(") => (false, ")"),
Some(ch) => {
left.push('#');
left.push(ch);
left.push_str(ch);
continue;
}
None => break,
Expand All @@ -56,24 +61,45 @@ pub fn print(s: &str) -> (String, Selection) {
panic!("primary `#[` already appeared {:?} {:?}", left, s);
}

let head_at_beg = iter.next_if_eq(&'|').is_some();
let head_at_beg = iter.next_if_eq(&"|").is_some();
let last_grapheme = |s: &str| {
UnicodeSegmentation::graphemes(s, true)
.last()
.map(String::from)
};

while let Some(c) = iter.next() {
if !(c == close_pair && iter.peek() == Some(&'#')) {
left.push(c);
let next = iter.peek();
let mut prev = last_grapheme(left.as_str());

if !(c == close_pair && next == Some(&"#")) {
left.push_str(c);
continue;
}

if !head_at_beg {
let prev = left.pop().unwrap();
if prev != '|' {
left.push(prev);
left.push(c);
continue;
match &prev {
Some(p) if p != "|" => {
left.push_str(c);
continue;
}
Some(p) if p == "|" => {
left.pop().unwrap(); // pop the |
prev = last_grapheme(left.as_str());
}
_ => (),
}
}

iter.next(); // skip "#"
let next = iter.peek();

// skip explicit line end inside selection
if (prev == Some(String::from("\r\n")) || prev == Some(String::from("\n")))
&& next.map(|n| String::from(*n)) == prev
{
iter.next();
}

if is_primary {
primary_idx = Some(ranges.len());
Expand Down Expand Up @@ -118,11 +144,11 @@ pub fn print(s: &str) -> (String, Selection) {
/// use smallvec::smallvec;
///
/// assert_eq!(
/// plain("abc", Selection::new(smallvec![Range::new(0, 1), Range::new(3, 2)], 0)),
/// plain("abc", &Selection::new(smallvec![Range::new(0, 1), Range::new(3, 2)], 0)),
/// "#[a|]#b#(|c)#".to_owned()
/// );
/// ```
pub fn plain(s: &str, selection: Selection) -> String {
pub fn plain(s: &str, selection: &Selection) -> String {
let primary = selection.primary_index();
let mut out = String::with_capacity(s.len() + 5 * selection.len());
out.push_str(s);
Expand All @@ -147,6 +173,7 @@ pub fn plain(s: &str, selection: Selection) -> String {
out
}

#[allow(clippy::module_inception)]
#[cfg(test)]
#[allow(clippy::module_inception)]
dead10ck marked this conversation as resolved.
Show resolved Hide resolved
mod test {
Expand Down
6 changes: 3 additions & 3 deletions helix-core/src/textobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
Expand All @@ -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, &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
Expand Down Expand Up @@ -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, &selection);
assert_eq!(actual, expected, "\nbefore: `{:?}`", before);
}
}
Expand Down
Loading