on master help sign in
Add next paragraph
commite2a6e33b98ac6dd1d42be659706c7e0d248e8f5d authorIvan Tham <pickfire@riseup.net> dateMon 21 Feb 2022, 19:07 (5 years ago) parent8b02bf2
1 file changed+94−15
helix-core/src/movement.rs+94−15
helix-core/src/movement.rs+94−15
@@ -10,7 +10,7 @@ use crate::{
1010 next_grapheme_boundary, nth_next_grapheme_boundary, nth_prev_grapheme_boundary,
1111 prev_grapheme_boundary,
1212 },
13− line_ending::{rope_is_line_ending, str_is_line_ending},
13+ line_ending::rope_is_line_ending,
1414 pos_at_coords,
1515 syntax::LanguageConfiguration,
1616 textobject::TextObject,
@@ -188,9 +188,19 @@ pub fn move_prev_para(slice: RopeSlice, range: Range, count: usize, behavior: Mo
188188}
189189
190190pub fn move_next_para(slice: RopeSlice, range: Range, count: usize, behavior: Movement) -> Range {
191− let mut line = slice.char_to_line(range.head);
192− let lines = slice.lines_at(line);
193− let mut lines = lines.map(|l| l.chunks().all(str_is_line_ending)).peekable();
191+ let mut line = range.cursor_line(slice);
192+ let last_char =
193+ prev_grapheme_boundary(slice, slice.line_to_char(line + 1)) == range.cursor(slice);
194+ let curr_line_empty = rope_is_line_ending(slice.line(line));
195+ let next_line_empty = rope_is_line_ending(slice.line(line.saturating_sub(1)));
196+ let empty_to_line = curr_line_empty && !next_line_empty;
197+
198+ // iterate current line if first character after paragraph boundary
199+ if empty_to_line && last_char {
200+ line += 1;
201+ }
202+
203+ let mut lines = slice.lines_at(line).map(rope_is_line_ending).peekable();
194204 for _ in 0..count {
195205 while lines.next_if(|&e| !e).is_some() {
196206 line += 1;
@@ -199,12 +209,17 @@ pub fn move_next_para(slice: RopeSlice, range: Range, count: usize, behavior: Mo
199209 line += 1;
200210 }
201211 }
212+ let head = slice.line_to_char(line);
202213 let anchor = if behavior == Movement::Move {
203− range.cursor(slice)
214+ if empty_to_line && last_char {
215+ range.head
216+ } else {
217+ range.cursor(slice)
218+ }
204219 } else {
205− range.anchor
220+ range.put_cursor(slice, head, true).anchor
206221 };
207− Range::new(anchor, slice.line_to_char(line))
222+ Range::new(anchor, head)
208223}
209224
210225// ---- util ------------
@@ -1253,19 +1268,49 @@ mod test {
12531268 ),
12541269 ];
12551270
1256− for (actual, expected) in tests {
1257− let (s, selection) = crate::test::print(actual);
1271+ for (before, expected) in tests {
1272+ let (s, selection) = crate::test::print(before);
12581273 let text = Rope::from(s.as_str());
12591274 let selection =
12601275 selection.transform(|r| move_prev_para(text.slice(..), r, 1, Movement::Move));
12611276 let actual = crate::test::plain(&s, selection);
1262− assert_eq!(actual, expected);
1277+ assert_eq!(actual, expected, "\nbefore: `{before:?}`");
12631278 }
12641279 }
12651280
1266− #[ignore]
12671281 #[test]
1268− fn test_behaviour_when_moving_to_prev_paragraph_double() {}
1282+ fn test_behaviour_when_moving_to_prev_paragraph_double() {
1283+ let tests = [
1284+ ("on^e@\n\ntwo\n\nthree\n\n", "@one^\n\ntwo\n\nthree\n\n"),
1285+ ("one\n\ntwo\n\nth^r@ee\n\n", "one\n\n@two\n\nthr^ee\n\n"),
1286+ ];
1287+
1288+ for (before, expected) in tests {
1289+ let (s, selection) = crate::test::print(before);
1290+ let text = Rope::from(s.as_str());
1291+ let selection =
1292+ selection.transform(|r| move_prev_para(text.slice(..), r, 2, Movement::Move));
1293+ let actual = crate::test::plain(&s, selection);
1294+ assert_eq!(actual, expected, "\nbefore: `{before:?}`");
1295+ }
1296+ }
1297+
1298+ #[test]
1299+ fn test_behaviour_when_moving_to_prev_paragraph_extend() {
1300+ let tests = [
1301+ ("one\n\n@two\n\n^three\n\n", "@one\n\ntwo\n\n^three\n\n"),
1302+ ("@one\n\ntwo\n\n^three\n\n", "@one\n\ntwo\n\n^three\n\n"),
1303+ ];
1304+
1305+ for (before, expected) in tests {
1306+ let (s, selection) = crate::test::print(before);
1307+ let text = Rope::from(s.as_str());
1308+ let selection =
1309+ selection.transform(|r| move_prev_para(text.slice(..), r, 1, Movement::Extend));
1310+ let actual = crate::test::plain(&s, selection);
1311+ assert_eq!(actual, expected, "\nbefore: `{before:?}`");
1312+ }
1313+ }
12691314
12701315 #[test]
12711316 fn test_behaviour_when_moving_to_next_paragraph_single() {
@@ -1291,13 +1336,47 @@ mod test {
12911336 ),
12921337 ];
12931338
1294− for (actual, expected) in tests {
1295− let (s, selection) = crate::test::print(actual);
1339+ for (before, expected) in tests {
1340+ let (s, selection) = crate::test::print(before);
12961341 let text = Rope::from(s.as_str());
12971342 let selection =
12981343 selection.transform(|r| move_next_para(text.slice(..), r, 1, Movement::Move));
12991344 let actual = crate::test::plain(&s, selection);
1300− assert_eq!(actual, expected);
1345+ assert_eq!(actual, expected, "\nbefore: `{before:?}`");
1346+ }
1347+ }
1348+
1349+ #[test]
1350+ fn test_behaviour_when_moving_to_next_paragraph_double() {
1351+ let tests = [
1352+ ("one\n\ntwo\n\nth^r@ee\n\n", "one\n\ntwo\n\nth^ree\n\n@"),
1353+ ("on^e@\n\ntwo\n\nthree\n\n", "on^e\n\ntwo\n\n@three\n\n"),
1354+ ];
1355+
1356+ for (before, expected) in tests {
1357+ let (s, selection) = crate::test::print(before);
1358+ let text = Rope::from(s.as_str());
1359+ let selection =
1360+ selection.transform(|r| move_next_para(text.slice(..), r, 2, Movement::Move));
1361+ let actual = crate::test::plain(&s, selection);
1362+ assert_eq!(actual, expected, "\nbefore: `{before:?}`");
1363+ }
1364+ }
1365+
1366+ #[test]
1367+ fn test_behaviour_when_moving_to_next_paragraph_extend() {
1368+ let tests = [
1369+ ("one\n\n^two\n\n@three\n\n", "one\n\n^two\n\nthree\n\n@"),
1370+ ("one\n\n^two\n\nthree\n\n@", "one\n\n^two\n\nthree\n\n@"),
1371+ ];
1372+
1373+ for (before, expected) in tests {
1374+ let (s, selection) = crate::test::print(before);
1375+ let text = Rope::from(s.as_str());
1376+ let selection =
1377+ selection.transform(|r| move_next_para(text.slice(..), r, 1, Movement::Extend));
1378+ let actual = crate::test::plain(&s, selection);
1379+ assert_eq!(actual, expected, "\nbefore: `{before:?}`");
13011380 }
13021381 }
13031382}