on master help sign in
Change test mark from ^@ to #[|]#
commit45b76db5068791fe6163963976a6a9daf3e9bf9d authorIvan Tham <pickfire@riseup.net> dateThu 3 Mar 2022, 08:55 (5 years ago) parent8350ee9
3 files changed+185−97
helix-core/src/movement.rs+60−27 helix-core/src/test.rs+97−48 helix-core/src/textobject.rs+28−22
helix-core/src/movement.rs+60−27
@@ -1255,15 +1255,24 @@ mod test {
12551255 #[test]
12561256 fn test_behaviour_when_moving_to_prev_paragraph_single() {
12571257 let tests = [
1258− ("^@", "^@"),
1259− ("^s@tart at\nfirst char\n", "@s^tart at\nfirst char\n"),
1260− ("start at\nlast char^\n@", "@start at\nlast char\n^"),
1261− ("goto\nfirst\n\n^p@aragraph", "@goto\nfirst\n\n^paragraph"),
1262− ("goto\nfirst\n^\n@paragraph", "@goto\nfirst\n\n^paragraph"),
1263− ("goto\nsecond\n\np^a@ragraph", "goto\nsecond\n\n@pa^ragraph"),
1258+ ("#[|]#", "#[|]#"),
1259+ ("#[s|]#tart at\nfirst char\n", "#[|s]#tart at\nfirst char\n"),
1260+ ("start at\nlast char#[\n|]#", "#[|start at\nlast char\n]#"),
12641261 (
1265− "here\n\nhave\nmultiple\nparagraph\n\n\n\n\n^@",
1266− "here\n\n@have\nmultiple\nparagraph\n\n\n\n\n^",
1262+ "goto\nfirst\n\n#[p|]#aragraph",
1263+ "#[|goto\nfirst\n\n]#paragraph",
1264+ ),
1265+ (
1266+ "goto\nfirst\n#[\n|]#paragraph",
1267+ "#[|goto\nfirst\n\n]#paragraph",
1268+ ),
1269+ (
1270+ "goto\nsecond\n\np#[a|]#ragraph",
1271+ "goto\nsecond\n\n#[|pa]#ragraph",
1272+ ),
1273+ (
1274+ "here\n\nhave\nmultiple\nparagraph\n\n\n\n\n#[|]#",
1275+ "here\n\n#[|have\nmultiple\nparagraph\n\n\n\n\n]#",
12671276 ),
12681277 ];
12691278
@@ -1280,8 +1289,14 @@ mod test {
12801289 #[test]
12811290 fn test_behaviour_when_moving_to_prev_paragraph_double() {
12821291 let tests = [
1283− ("on^e@\n\ntwo\n\nthree\n\n", "@one^\n\ntwo\n\nthree\n\n"),
1284− ("one\n\ntwo\n\nth^r@ee\n\n", "one\n\n@two\n\nthr^ee\n\n"),
1292+ (
1293+ "on#[e|]#\n\ntwo\n\nthree\n\n",
1294+ "#[|one]#\n\ntwo\n\nthree\n\n",
1295+ ),
1296+ (
1297+ "one\n\ntwo\n\nth#[r|]#ee\n\n",
1298+ "one\n\n#[|two\n\nthr]#ee\n\n",
1299+ ),
12851300 ];
12861301
12871302 for (before, expected) in tests {
@@ -1297,8 +1312,14 @@ mod test {
12971312 #[test]
12981313 fn test_behaviour_when_moving_to_prev_paragraph_extend() {
12991314 let tests = [
1300− ("one\n\n@two\n\n^three\n\n", "@one\n\ntwo\n\n^three\n\n"),
1301− ("@one\n\ntwo\n\n^three\n\n", "@one\n\ntwo\n\n^three\n\n"),
1315+ (
1316+ "one\n\n#[|two\n\n]#three\n\n",
1317+ "#[|one\n\ntwo\n\n]#three\n\n",
1318+ ),
1319+ (
1320+ "#[|one\n\ntwo\n\n]#three\n\n",
1321+ "#[|one\n\ntwo\n\n]#three\n\n",
1322+ ),
13021323 ];
13031324
13041325 for (before, expected) in tests {
@@ -1314,24 +1335,24 @@ mod test {
13141335 #[test]
13151336 fn test_behaviour_when_moving_to_next_paragraph_single() {
13161337 let tests = [
1317− ("^@", "^@"),
1318− ("^s@tart at\nfirst char\n", "^start at\nfirst char\n@"),
1319− ("start at\nlast char^\n@", "start at\nlast char^\n@"),
1338+ ("#[|]#", "#[|]#"),
1339+ ("#[s|]#tart at\nfirst char\n", "#[start at\nfirst char\n|]#"),
1340+ ("start at\nlast char#[\n|]#", "start at\nlast char#[\n|]#"),
13201341 (
1321− "a\nb\n\n^g@oto\nthird\n\nparagraph",
1322− "a\nb\n\n^goto\nthird\n\n@paragraph",
1342+ "a\nb\n\n#[g|]#oto\nthird\n\nparagraph",
1343+ "a\nb\n\n#[goto\nthird\n\n|]#paragraph",
13231344 ),
13241345 (
1325− "a\nb\n^\n@goto\nthird\n\nparagraph",
1326− "a\nb\n\n^goto\nthird\n\n@paragraph",
1346+ "a\nb\n#[\n|]#goto\nthird\n\nparagraph",
1347+ "a\nb\n\n#[goto\nthird\n\n|]#paragraph",
13271348 ),
13281349 (
1329− "a\nb^\n@\ngoto\nsecond\n\nparagraph",
1330− "a\nb^\n\n@goto\nsecond\n\nparagraph",
1350+ "a\nb#[\n|]#\ngoto\nsecond\n\nparagraph",
1351+ "a\nb#[\n\n|]#goto\nsecond\n\nparagraph",
13311352 ),
13321353 (
1333− "here\n\nhave\n^m@ultiple\nparagraph\n\n\n\n\n",
1334− "here\n\nhave\n^multiple\nparagraph\n\n\n\n\n@",
1354+ "here\n\nhave\n#[m|]#ultiple\nparagraph\n\n\n\n\n",
1355+ "here\n\nhave\n#[multiple\nparagraph\n\n\n\n\n|]#",
13351356 ),
13361357 ];
13371358
@@ -1348,8 +1369,14 @@ mod test {
13481369 #[test]
13491370 fn test_behaviour_when_moving_to_next_paragraph_double() {
13501371 let tests = [
1351− ("one\n\ntwo\n\nth^r@ee\n\n", "one\n\ntwo\n\nth^ree\n\n@"),
1352− ("on^e@\n\ntwo\n\nthree\n\n", "on^e\n\ntwo\n\n@three\n\n"),
1372+ (
1373+ "one\n\ntwo\n\nth#[r|]#ee\n\n",
1374+ "one\n\ntwo\n\nth#[ree\n\n|]#",
1375+ ),
1376+ (
1377+ "on#[e|]#\n\ntwo\n\nthree\n\n",
1378+ "on#[e\n\ntwo\n\n|]#three\n\n",
1379+ ),
13531380 ];
13541381
13551382 for (before, expected) in tests {
@@ -1365,8 +1392,14 @@ mod test {
13651392 #[test]
13661393 fn test_behaviour_when_moving_to_next_paragraph_extend() {
13671394 let tests = [
1368− ("one\n\n^two\n\n@three\n\n", "one\n\n^two\n\nthree\n\n@"),
1369− ("one\n\n^two\n\nthree\n\n@", "one\n\n^two\n\nthree\n\n@"),
1395+ (
1396+ "one\n\n#[two\n\n|]#three\n\n",
1397+ "one\n\n#[two\n\nthree\n\n|]#",
1398+ ),
1399+ (
1400+ "one\n\n#[two\n\nthree\n\n|]#",
1401+ "one\n\n#[two\n\nthree\n\n|]#",
1402+ ),
13701403 ];
13711404
13721405 for (before, expected) in tests {
helix-core/src/test.rs+97−48
@@ -5,8 +5,10 @@ use std::cmp::Reverse;
55
66/// Convert annotated test string to test string and selection.
77///
8−/// `^` for `anchor` and `|` for head (`@` for primary), both must appear
9−/// or otherwise it will panic.
8+/// `#[|` for primary selection with head before anchor followed by `]#`.
9+/// `#(|` for secondary selection with head before anchor followed by `)#`.
10+/// `#[` for primary selection with head after anchor followed by `|]#`.
11+/// `#(` for secondary selection with head after anchor followed by `|)#`.
1012///
1113/// # Examples
1214///
@@ -15,7 +17,7 @@ use std::cmp::Reverse;
1517/// use smallvec::smallvec;
1618///
1719/// assert_eq!(
18−/// print("^a@b|c^"),
20+/// print("#[a|]#b#(|c)#"),
1921/// ("abc".to_owned(), Selection::new(smallvec![Range::new(0, 1), Range::new(3, 2)], 0))
2022/// );
2123/// ```
@@ -26,56 +28,101 @@ use std::cmp::Reverse;
2628/// Panics when missing head or anchor.
2729/// Panics when head come after head or anchor come after anchor.
2830pub fn print(s: &str) -> (String, Selection) {
29− let mut anchor = None;
30− let mut head = None;
3131 let mut primary = None;
3232 let mut ranges = SmallVec::new();
33− let mut i = 0;
34− let s = s
35− .chars()
36− .filter(|c| {
37− match c {
38− '^' if anchor != None => panic!("anchor without head {s:?}"),
39− '^' if head == None => anchor = Some(i),
40− '^' => ranges.push(Range::new(i, head.take().unwrap())),
41− '|' if head != None => panic!("head without anchor {s:?}"),
42− '|' if anchor == None => head = Some(i),
43− '|' => ranges.push(Range::new(anchor.take().unwrap(), i)),
44− '@' if primary != None => panic!("head (primary) already appeared {s:?}"),
45− '@' if head != None => panic!("head (primary) without anchor {s:?}"),
46− '@' if anchor == None => {
47− primary = Some(ranges.len());
48− head = Some(i);
33+ let mut iter = s.chars().peekable();
34+ let mut left = String::with_capacity(s.len());
35+ 'outer: while let Some(c) = iter.next() {
36+ let start = left.len();
37+ if c == '#' {
38+ if iter.next_if_eq(&'[').is_some() {
39+ if primary.is_some() {
40+ panic!("primary `#[` already appeared {left:?} {s:?}");
4941 }
50− '@' => {
51− primary = Some(ranges.len());
52− ranges.push(Range::new(anchor.take().unwrap(), i));
42+ if iter.next_if_eq(&'|').is_some() {
43+ while let Some(c) = iter.next() {
44+ if c == ']' && iter.next_if_eq(&'#').is_some() {
45+ primary = Some(ranges.len());
46+ ranges.push(Range::new(left.len(), start));
47+ continue 'outer;
48+ } else {
49+ left.push(c);
50+ }
51+ }
52+ panic!("missing primary end `]#` {left:?} {s:?}");
53+ } else {
54+ while let Some(c) = iter.next() {
55+ if c == '|' {
56+ if let Some(cc) = iter.next_if_eq(&']') {
57+ if iter.next_if_eq(&'#').is_some() {
58+ primary = Some(ranges.len());
59+ ranges.push(Range::new(start, left.len()));
60+ continue 'outer;
61+ } else {
62+ left.push(c);
63+ left.push(cc);
64+ }
65+ } else {
66+ left.push(c);
67+ }
68+ } else {
69+ left.push(c);
70+ }
71+ }
72+ panic!("missing primary end `|]#` {left:?} {s:?}");
5373 }
54− _ => {
55− i += 1;
56− return true;
74+ } else if iter.next_if_eq(&'(').is_some() {
75+ if iter.next_if_eq(&'|').is_some() {
76+ while let Some(c) = iter.next() {
77+ if c == ')' && iter.next_if_eq(&'#').is_some() {
78+ ranges.push(Range::new(left.len(), start));
79+ continue 'outer;
80+ } else {
81+ left.push(c);
82+ }
83+ }
84+ panic!("missing end `)#` {left:?} {s:?}");
85+ } else {
86+ while let Some(c) = iter.next() {
87+ if c == '|' {
88+ if let Some(cc) = iter.next_if_eq(&')') {
89+ if iter.next_if_eq(&'#').is_some() {
90+ ranges.push(Range::new(start, left.len()));
91+ continue 'outer;
92+ } else {
93+ left.push(c);
94+ left.push(cc);
95+ }
96+ } else {
97+ left.push(c);
98+ }
99+ } else {
100+ left.push(c);
101+ }
102+ }
103+ panic!("missing end `|)#` {left:?} {s:?}");
57104 }
58− };
59− false
60− })
61− .collect();
62− if head.is_some() {
63− panic!("missing anchor (|) {s:?}");
64− }
65− if anchor.is_some() {
66− panic!("missing head (^) {s:?}");
105+ } else {
106+ left.push(c);
107+ }
108+ } else {
109+ left.push(c);
110+ }
67111 }
68112 let primary = match primary {
69113 Some(i) => i,
70− None => panic!("missing primary (@) {s:?}"),
114+ None => panic!("missing primary `#[|]#` {s:?}"),
71115 };
72116 let selection = Selection::new(ranges, primary);
73− (s, selection)
117+ (left, selection)
74118}
75119
76120/// Convert test string and selection to annotated test string.
77121///
78−/// `^` for `anchor` and `|` for head (`@` for primary).
122+/// `#[|` for primary selection with head before anchor followed by `]#`.
123+/// `#(|` for secondary selection with head before anchor followed by `)#`.
124+/// `#[` for primary selection with head after anchor followed by `|]#`.
125+/// `#(` for secondary selection with head after anchor followed by `|)#`.
79126///
80127/// # Examples
81128///
@@ -85,28 +132,30 @@ pub fn print(s: &str) -> (String, Selection) {
85132///
86133/// assert_eq!(
87134/// plain("abc", Selection::new(smallvec![Range::new(0, 1), Range::new(3, 2)], 0)),
88−/// "^a@b|c^".to_owned()
135+/// "#[a|]#b#(|c)#".to_owned()
89136/// );
90137/// ```
91138pub fn plain(s: &str, selection: Selection) -> String {
92139 let primary = selection.primary_index();
93− let mut out = String::with_capacity(s.len() + 2 * selection.len());
140+ let mut out = String::with_capacity(s.len() + 5 * selection.len());
94141 out.push_str(s);
95142 let mut insertion: Vec<_> = selection
96143 .iter()
97144 .enumerate()
98145 .flat_map(|(i, range)| {
99− [
100− // sort like this before reversed so anchor < head later
101− (range.head, if i == primary { '@' } else { '|' }),
102− (range.anchor, '^'),
103− ]
146+ // sort like this before reversed so anchor < head later
147+ match (range.anchor < range.head, i == primary) {
148+ (true, true) => [(range.anchor, "#["), (range.head, "|]#")],
149+ (true, false) => [(range.anchor, "#("), (range.head, "|)#")],
150+ (false, true) => [(range.anchor, "]#"), (range.head, "#[|")],
151+ (false, false) => [(range.anchor, ")#"), (range.head, "#(|")],
152+ }
104153 })
105154 .collect();
106155 // insert in reverse order
107156 insertion.sort_unstable_by_key(|k| Reverse(k.0));
108− for (i, c) in insertion {
109− out.insert(i, c);
157+ for (i, s) in insertion {
158+ out.insert_str(i, s);
110159 }
111160 out
112161}
helix-core/src/textobject.rs+28−22
@@ -357,18 +357,21 @@ mod test {
357357 #[test]
358358 fn test_textobject_paragraph_inside_single() {
359359 let tests = [
360− ("^@", "^@"),
361− ("firs^t@\n\nparagraph\n\n", "^first\n@\nparagraph\n\n"),
362− ("second\n\npa^r@agraph\n\n", "second\n\n^paragraph\n@\n"),
363− ("^f@irst char\n\n", "^first char\n@\n"),
364− ("last char\n^\n@", "last char\n\n^@"),
360+ ("#[|]#", "#[|]#"),
361+ ("firs#[t|]#\n\nparagraph\n\n", "#[first\n|]#\nparagraph\n\n"),
365362 (
366− "empty to line\n^\n@paragraph boundary\n\n",
367− "empty to line\n\n^paragraph boundary\n@\n",
363+ "second\n\npa#[r|]#agraph\n\n",
364+ "second\n\n#[paragraph\n|]#\n",
368365 ),
366+ ("#[f|]#irst char\n\n", "#[first char\n|]#\n"),
367+ ("last char\n#[\n|]#", "last char\n\n#[|]#"),
369368 (
370− "line to empty\n\n^p@aragraph boundary\n\n",
371− "line to empty\n\n^paragraph boundary\n@\n",
369+ "empty to line\n#[\n|]#paragraph boundary\n\n",
370+ "empty to line\n\n#[paragraph boundary\n|]#\n",
371+ ),
372+ (
373+ "line to empty\n\n#[p|]#aragraph boundary\n\n",
374+ "line to empty\n\n#[paragraph boundary\n|]#\n",
372375 ),
373376 ];
374377
@@ -386,12 +389,12 @@ mod test {
386389 fn test_textobject_paragraph_inside_double() {
387390 let tests = [
388391 (
389− "last two\n\n^p@aragraph\n\nwithout whitespaces\n\n",
390− "last two\n\n^paragraph\n\nwithout whitespaces\n@\n",
392+ "last two\n\n#[p|]#aragraph\n\nwithout whitespaces\n\n",
393+ "last two\n\n#[paragraph\n\nwithout whitespaces\n|]#\n",
391394 ),
392395 (
393− "last two\n^\n@paragraph\n\nwithout whitespaces\n\n",
394− "last two\n\n^paragraph\n\nwithout whitespaces\n@\n",
396+ "last two\n#[\n|]#paragraph\n\nwithout whitespaces\n\n",
397+ "last two\n\n#[paragraph\n\nwithout whitespaces\n|]#\n",
395398 ),
396399 ];
397400
@@ -408,18 +411,21 @@ mod test {
408411 #[test]
409412 fn test_textobject_paragraph_around_single() {
410413 let tests = [
411− ("^@", "^@"),
412− ("firs^t@\n\nparagraph\n\n", "^first\n\n@paragraph\n\n"),
413− ("second\n\npa^r@agraph\n\n", "second\n\n^paragraph\n\n@"),
414− ("^f@irst char\n\n", "^first char\n\n@"),
415− ("last char\n^\n@", "last char\n\n^@"),
414+ ("#[|]#", "#[|]#"),
415+ ("firs#[t|]#\n\nparagraph\n\n", "#[first\n\n|]#paragraph\n\n"),
416+ (
417+ "second\n\npa#[r|]#agraph\n\n",
418+ "second\n\n#[paragraph\n\n|]#",
419+ ),
420+ ("#[f|]#irst char\n\n", "#[first char\n\n|]#"),
421+ ("last char\n#[\n|]#", "last char\n\n#[|]#"),
416422 (
417− "empty to line\n^\n@paragraph boundary\n\n",
418− "empty to line\n\n^paragraph boundary\n\n@",
423+ "empty to line\n#[\n|]#paragraph boundary\n\n",
424+ "empty to line\n\n#[paragraph boundary\n\n|]#",
419425 ),
420426 (
421− "line to empty\n\n^p@aragraph boundary\n\n",
422− "line to empty\n\n^paragraph boundary\n\n@",
427+ "line to empty\n\n#[p|]#aragraph boundary\n\n",
428+ "line to empty\n\n#[paragraph boundary\n\n|]#",
423429 ),
424430 ];
425431