aboutsummaryrefslogtreecommitdiff
path: root/helix-core
diff options
context:
space:
mode:
authorIvan Tham2022-03-03 00:55:26 +0000
committerBlaž Hrastnik2022-04-02 15:46:53 +0000
commit45b76db5068791fe6163963976a6a9daf3e9bf9d (patch)
tree4f81d28c3f8cc33c9afc91029f7202935dc31a43 /helix-core
parent8350ee9a0ef38ff4e78bfa5dc30e874d6d2510ef (diff)
Change test mark from ^@ to #[|]#
Diffstat (limited to 'helix-core')
-rw-r--r--helix-core/src/movement.rs87
-rw-r--r--helix-core/src/test.rs145
-rw-r--r--helix-core/src/textobject.rs50
3 files changed, 185 insertions, 97 deletions
diff --git a/helix-core/src/movement.rs b/helix-core/src/movement.rs
index 970aff88..c09b3c33 100644
--- a/helix-core/src/movement.rs
+++ b/helix-core/src/movement.rs
@@ -1255,15 +1255,24 @@ mod test {
#[test]
fn test_behaviour_when_moving_to_prev_paragraph_single() {
let tests = [
- ("^@", "^@"),
- ("^s@tart at\nfirst char\n", "@s^tart at\nfirst char\n"),
- ("start at\nlast char^\n@", "@start at\nlast char\n^"),
- ("goto\nfirst\n\n^p@aragraph", "@goto\nfirst\n\n^paragraph"),
- ("goto\nfirst\n^\n@paragraph", "@goto\nfirst\n\n^paragraph"),
- ("goto\nsecond\n\np^a@ragraph", "goto\nsecond\n\n@pa^ragraph"),
+ ("#[|]#", "#[|]#"),
+ ("#[s|]#tart at\nfirst char\n", "#[|s]#tart at\nfirst char\n"),
+ ("start at\nlast char#[\n|]#", "#[|start at\nlast char\n]#"),
(
- "here\n\nhave\nmultiple\nparagraph\n\n\n\n\n^@",
- "here\n\n@have\nmultiple\nparagraph\n\n\n\n\n^",
+ "goto\nfirst\n\n#[p|]#aragraph",
+ "#[|goto\nfirst\n\n]#paragraph",
+ ),
+ (
+ "goto\nfirst\n#[\n|]#paragraph",
+ "#[|goto\nfirst\n\n]#paragraph",
+ ),
+ (
+ "goto\nsecond\n\np#[a|]#ragraph",
+ "goto\nsecond\n\n#[|pa]#ragraph",
+ ),
+ (
+ "here\n\nhave\nmultiple\nparagraph\n\n\n\n\n#[|]#",
+ "here\n\n#[|have\nmultiple\nparagraph\n\n\n\n\n]#",
),
];
@@ -1280,8 +1289,14 @@ mod test {
#[test]
fn test_behaviour_when_moving_to_prev_paragraph_double() {
let tests = [
- ("on^e@\n\ntwo\n\nthree\n\n", "@one^\n\ntwo\n\nthree\n\n"),
- ("one\n\ntwo\n\nth^r@ee\n\n", "one\n\n@two\n\nthr^ee\n\n"),
+ (
+ "on#[e|]#\n\ntwo\n\nthree\n\n",
+ "#[|one]#\n\ntwo\n\nthree\n\n",
+ ),
+ (
+ "one\n\ntwo\n\nth#[r|]#ee\n\n",
+ "one\n\n#[|two\n\nthr]#ee\n\n",
+ ),
];
for (before, expected) in tests {
@@ -1297,8 +1312,14 @@ mod test {
#[test]
fn test_behaviour_when_moving_to_prev_paragraph_extend() {
let tests = [
- ("one\n\n@two\n\n^three\n\n", "@one\n\ntwo\n\n^three\n\n"),
- ("@one\n\ntwo\n\n^three\n\n", "@one\n\ntwo\n\n^three\n\n"),
+ (
+ "one\n\n#[|two\n\n]#three\n\n",
+ "#[|one\n\ntwo\n\n]#three\n\n",
+ ),
+ (
+ "#[|one\n\ntwo\n\n]#three\n\n",
+ "#[|one\n\ntwo\n\n]#three\n\n",
+ ),
];
for (before, expected) in tests {
@@ -1314,24 +1335,24 @@ mod test {
#[test]
fn test_behaviour_when_moving_to_next_paragraph_single() {
let tests = [
- ("^@", "^@"),
- ("^s@tart at\nfirst char\n", "^start at\nfirst char\n@"),
- ("start at\nlast char^\n@", "start at\nlast char^\n@"),
+ ("#[|]#", "#[|]#"),
+ ("#[s|]#tart at\nfirst char\n", "#[start at\nfirst char\n|]#"),
+ ("start at\nlast char#[\n|]#", "start at\nlast char#[\n|]#"),
(
- "a\nb\n\n^g@oto\nthird\n\nparagraph",
- "a\nb\n\n^goto\nthird\n\n@paragraph",
+ "a\nb\n\n#[g|]#oto\nthird\n\nparagraph",
+ "a\nb\n\n#[goto\nthird\n\n|]#paragraph",
),
(
- "a\nb\n^\n@goto\nthird\n\nparagraph",
- "a\nb\n\n^goto\nthird\n\n@paragraph",
+ "a\nb\n#[\n|]#goto\nthird\n\nparagraph",
+ "a\nb\n\n#[goto\nthird\n\n|]#paragraph",
),
(
- "a\nb^\n@\ngoto\nsecond\n\nparagraph",
- "a\nb^\n\n@goto\nsecond\n\nparagraph",
+ "a\nb#[\n|]#\ngoto\nsecond\n\nparagraph",
+ "a\nb#[\n\n|]#goto\nsecond\n\nparagraph",
),
(
- "here\n\nhave\n^m@ultiple\nparagraph\n\n\n\n\n",
- "here\n\nhave\n^multiple\nparagraph\n\n\n\n\n@",
+ "here\n\nhave\n#[m|]#ultiple\nparagraph\n\n\n\n\n",
+ "here\n\nhave\n#[multiple\nparagraph\n\n\n\n\n|]#",
),
];
@@ -1348,8 +1369,14 @@ mod test {
#[test]
fn test_behaviour_when_moving_to_next_paragraph_double() {
let tests = [
- ("one\n\ntwo\n\nth^r@ee\n\n", "one\n\ntwo\n\nth^ree\n\n@"),
- ("on^e@\n\ntwo\n\nthree\n\n", "on^e\n\ntwo\n\n@three\n\n"),
+ (
+ "one\n\ntwo\n\nth#[r|]#ee\n\n",
+ "one\n\ntwo\n\nth#[ree\n\n|]#",
+ ),
+ (
+ "on#[e|]#\n\ntwo\n\nthree\n\n",
+ "on#[e\n\ntwo\n\n|]#three\n\n",
+ ),
];
for (before, expected) in tests {
@@ -1365,8 +1392,14 @@ mod test {
#[test]
fn test_behaviour_when_moving_to_next_paragraph_extend() {
let tests = [
- ("one\n\n^two\n\n@three\n\n", "one\n\n^two\n\nthree\n\n@"),
- ("one\n\n^two\n\nthree\n\n@", "one\n\n^two\n\nthree\n\n@"),
+ (
+ "one\n\n#[two\n\n|]#three\n\n",
+ "one\n\n#[two\n\nthree\n\n|]#",
+ ),
+ (
+ "one\n\n#[two\n\nthree\n\n|]#",
+ "one\n\n#[two\n\nthree\n\n|]#",
+ ),
];
for (before, expected) in tests {
diff --git a/helix-core/src/test.rs b/helix-core/src/test.rs
index da4f8fac..964a770a 100644
--- a/helix-core/src/test.rs
+++ b/helix-core/src/test.rs
@@ -5,8 +5,10 @@ use std::cmp::Reverse;
/// Convert annotated test string to test string and selection.
///
-/// `^` for `anchor` and `|` for head (`@` for primary), both must appear
-/// or otherwise it will panic.
+/// `#[|` for primary selection with head before anchor followed by `]#`.
+/// `#(|` for secondary selection with head before anchor followed by `)#`.
+/// `#[` for primary selection with head after anchor followed by `|]#`.
+/// `#(` for secondary selection with head after anchor followed by `|)#`.
///
/// # Examples
///
@@ -15,7 +17,7 @@ use std::cmp::Reverse;
/// use smallvec::smallvec;
///
/// assert_eq!(
-/// print("^a@b|c^"),
+/// print("#[a|]#b#(|c)#"),
/// ("abc".to_owned(), Selection::new(smallvec![Range::new(0, 1), Range::new(3, 2)], 0))
/// );
/// ```
@@ -26,56 +28,101 @@ use std::cmp::Reverse;
/// Panics when missing head or anchor.
/// Panics when head come after head or anchor come after anchor.
pub fn print(s: &str) -> (String, Selection) {
- let mut anchor = None;
- let mut head = None;
let mut primary = None;
let mut ranges = SmallVec::new();
- let mut i = 0;
- let s = s
- .chars()
- .filter(|c| {
- match c {
- '^' if anchor != None => panic!("anchor without head {s:?}"),
- '^' if head == None => anchor = Some(i),
- '^' => ranges.push(Range::new(i, head.take().unwrap())),
- '|' if head != None => panic!("head without anchor {s:?}"),
- '|' if anchor == None => head = Some(i),
- '|' => ranges.push(Range::new(anchor.take().unwrap(), i)),
- '@' if primary != None => panic!("head (primary) already appeared {s:?}"),
- '@' if head != None => panic!("head (primary) without anchor {s:?}"),
- '@' if anchor == None => {
- primary = Some(ranges.len());
- head = Some(i);
+ let mut iter = s.chars().peekable();
+ let mut left = String::with_capacity(s.len());
+ 'outer: while let Some(c) = iter.next() {
+ let start = left.len();
+ if c == '#' {
+ if iter.next_if_eq(&'[').is_some() {
+ if primary.is_some() {
+ panic!("primary `#[` already appeared {left:?} {s:?}");
}
- '@' => {
- primary = Some(ranges.len());
- ranges.push(Range::new(anchor.take().unwrap(), i));
+ if iter.next_if_eq(&'|').is_some() {
+ while let Some(c) = iter.next() {
+ if c == ']' && iter.next_if_eq(&'#').is_some() {
+ primary = Some(ranges.len());
+ ranges.push(Range::new(left.len(), start));
+ continue 'outer;
+ } else {
+ left.push(c);
+ }
+ }
+ panic!("missing primary end `]#` {left:?} {s:?}");
+ } else {
+ while let Some(c) = iter.next() {
+ if c == '|' {
+ if let Some(cc) = iter.next_if_eq(&']') {
+ if iter.next_if_eq(&'#').is_some() {
+ primary = Some(ranges.len());
+ ranges.push(Range::new(start, left.len()));
+ continue 'outer;
+ } else {
+ left.push(c);
+ left.push(cc);
+ }
+ } else {
+ left.push(c);
+ }
+ } else {
+ left.push(c);
+ }
+ }
+ panic!("missing primary end `|]#` {left:?} {s:?}");
}
- _ => {
- i += 1;
- return true;
+ } else if iter.next_if_eq(&'(').is_some() {
+ if iter.next_if_eq(&'|').is_some() {
+ while let Some(c) = iter.next() {
+ if c == ')' && iter.next_if_eq(&'#').is_some() {
+ ranges.push(Range::new(left.len(), start));
+ continue 'outer;
+ } else {
+ left.push(c);
+ }
+ }
+ panic!("missing end `)#` {left:?} {s:?}");
+ } else {
+ while let Some(c) = iter.next() {
+ if c == '|' {
+ if let Some(cc) = iter.next_if_eq(&')') {
+ if iter.next_if_eq(&'#').is_some() {
+ ranges.push(Range::new(start, left.len()));
+ continue 'outer;
+ } else {
+ left.push(c);
+ left.push(cc);
+ }
+ } else {
+ left.push(c);
+ }
+ } else {
+ left.push(c);
+ }
+ }
+ panic!("missing end `|)#` {left:?} {s:?}");
}
- };
- false
- })
- .collect();
- if head.is_some() {
- panic!("missing anchor (|) {s:?}");
- }
- if anchor.is_some() {
- panic!("missing head (^) {s:?}");
+ } else {
+ left.push(c);
+ }
+ } else {
+ left.push(c);
+ }
}
let primary = match primary {
Some(i) => i,
- None => panic!("missing primary (@) {s:?}"),
+ None => panic!("missing primary `#[|]#` {s:?}"),
};
let selection = Selection::new(ranges, primary);
- (s, selection)
+ (left, selection)
}
/// Convert test string and selection to annotated test string.
///
-/// `^` for `anchor` and `|` for head (`@` for primary).
+/// `#[|` for primary selection with head before anchor followed by `]#`.
+/// `#(|` for secondary selection with head before anchor followed by `)#`.
+/// `#[` for primary selection with head after anchor followed by `|]#`.
+/// `#(` for secondary selection with head after anchor followed by `|)#`.
///
/// # Examples
///
@@ -85,28 +132,30 @@ pub fn print(s: &str) -> (String, Selection) {
///
/// assert_eq!(
/// plain("abc", Selection::new(smallvec![Range::new(0, 1), Range::new(3, 2)], 0)),
-/// "^a@b|c^".to_owned()
+/// "#[a|]#b#(|c)#".to_owned()
/// );
/// ```
pub fn plain(s: &str, selection: Selection) -> String {
let primary = selection.primary_index();
- let mut out = String::with_capacity(s.len() + 2 * selection.len());
+ let mut out = String::with_capacity(s.len() + 5 * selection.len());
out.push_str(s);
let mut insertion: Vec<_> = selection
.iter()
.enumerate()
.flat_map(|(i, range)| {
- [
- // sort like this before reversed so anchor < head later
- (range.head, if i == primary { '@' } else { '|' }),
- (range.anchor, '^'),
- ]
+ // sort like this before reversed so anchor < head later
+ match (range.anchor < range.head, i == primary) {
+ (true, true) => [(range.anchor, "#["), (range.head, "|]#")],
+ (true, false) => [(range.anchor, "#("), (range.head, "|)#")],
+ (false, true) => [(range.anchor, "]#"), (range.head, "#[|")],
+ (false, false) => [(range.anchor, ")#"), (range.head, "#(|")],
+ }
})
.collect();
// insert in reverse order
insertion.sort_unstable_by_key(|k| Reverse(k.0));
- for (i, c) in insertion {
- out.insert(i, c);
+ for (i, s) in insertion {
+ out.insert_str(i, s);
}
out
}
diff --git a/helix-core/src/textobject.rs b/helix-core/src/textobject.rs
index fb6b7142..cc1e337c 100644
--- a/helix-core/src/textobject.rs
+++ b/helix-core/src/textobject.rs
@@ -357,18 +357,21 @@ mod test {
#[test]
fn test_textobject_paragraph_inside_single() {
let tests = [
- ("^@", "^@"),
- ("firs^t@\n\nparagraph\n\n", "^first\n@\nparagraph\n\n"),
- ("second\n\npa^r@agraph\n\n", "second\n\n^paragraph\n@\n"),
- ("^f@irst char\n\n", "^first char\n@\n"),
- ("last char\n^\n@", "last char\n\n^@"),
+ ("#[|]#", "#[|]#"),
+ ("firs#[t|]#\n\nparagraph\n\n", "#[first\n|]#\nparagraph\n\n"),
(
- "empty to line\n^\n@paragraph boundary\n\n",
- "empty to line\n\n^paragraph boundary\n@\n",
+ "second\n\npa#[r|]#agraph\n\n",
+ "second\n\n#[paragraph\n|]#\n",
),
+ ("#[f|]#irst char\n\n", "#[first char\n|]#\n"),
+ ("last char\n#[\n|]#", "last char\n\n#[|]#"),
(
- "line to empty\n\n^p@aragraph boundary\n\n",
- "line to empty\n\n^paragraph boundary\n@\n",
+ "empty to line\n#[\n|]#paragraph boundary\n\n",
+ "empty to line\n\n#[paragraph boundary\n|]#\n",
+ ),
+ (
+ "line to empty\n\n#[p|]#aragraph boundary\n\n",
+ "line to empty\n\n#[paragraph boundary\n|]#\n",
),
];
@@ -386,12 +389,12 @@ mod test {
fn test_textobject_paragraph_inside_double() {
let tests = [
(
- "last two\n\n^p@aragraph\n\nwithout whitespaces\n\n",
- "last two\n\n^paragraph\n\nwithout whitespaces\n@\n",
+ "last two\n\n#[p|]#aragraph\n\nwithout whitespaces\n\n",
+ "last two\n\n#[paragraph\n\nwithout whitespaces\n|]#\n",
),
(
- "last two\n^\n@paragraph\n\nwithout whitespaces\n\n",
- "last two\n\n^paragraph\n\nwithout whitespaces\n@\n",
+ "last two\n#[\n|]#paragraph\n\nwithout whitespaces\n\n",
+ "last two\n\n#[paragraph\n\nwithout whitespaces\n|]#\n",
),
];
@@ -408,18 +411,21 @@ mod test {
#[test]
fn test_textobject_paragraph_around_single() {
let tests = [
- ("^@", "^@"),
- ("firs^t@\n\nparagraph\n\n", "^first\n\n@paragraph\n\n"),
- ("second\n\npa^r@agraph\n\n", "second\n\n^paragraph\n\n@"),
- ("^f@irst char\n\n", "^first char\n\n@"),
- ("last char\n^\n@", "last char\n\n^@"),
+ ("#[|]#", "#[|]#"),
+ ("firs#[t|]#\n\nparagraph\n\n", "#[first\n\n|]#paragraph\n\n"),
+ (
+ "second\n\npa#[r|]#agraph\n\n",
+ "second\n\n#[paragraph\n\n|]#",
+ ),
+ ("#[f|]#irst char\n\n", "#[first char\n\n|]#"),
+ ("last char\n#[\n|]#", "last char\n\n#[|]#"),
(
- "empty to line\n^\n@paragraph boundary\n\n",
- "empty to line\n\n^paragraph boundary\n\n@",
+ "empty to line\n#[\n|]#paragraph boundary\n\n",
+ "empty to line\n\n#[paragraph boundary\n\n|]#",
),
(
- "line to empty\n\n^p@aragraph boundary\n\n",
- "line to empty\n\n^paragraph boundary\n\n@",
+ "line to empty\n\n#[p|]#aragraph boundary\n\n",
+ "line to empty\n\n#[paragraph boundary\n\n|]#",
),
];