diff --git a/src/documents/document/block.rs b/src/documents/document/block.rs index f300f2a..4900463 100644 --- a/src/documents/document/block.rs +++ b/src/documents/document/block.rs @@ -251,11 +251,19 @@ fn path<'a>(text: &str, root: &'a Node, at: usize) -> Vec<&'a Node> { path } +/// `at`, before the CR when it splits a CRLF. +fn settled(text: &str, at: usize) -> usize { + let split = text[..at].ends_with('\r') && text[at..].starts_with('\n'); + if split { at - 1 } else { at } +} + pub(super) fn line_start(text: &str, at: usize) -> usize { + let at = settled(text, at); text[..at].rfind(['\n', '\r']).map_or(0, |at| at + 1) } pub(super) fn line_end(text: &str, at: usize) -> usize { + let at = settled(text, at); at + text[at..].find(['\n', '\r']).unwrap_or(text.len() - at) } diff --git a/src/documents/document/tests/tools.rs b/src/documents/document/tests/tools.rs index 36daadc..b641158 100644 --- a/src/documents/document/tests/tools.rs +++ b/src/documents/document/tests/tools.rs @@ -69,6 +69,24 @@ fn a_new_table_goes_after_the_caret_line(cx: &mut TestAppContext) { ); } +#[gpui::test] +fn a_new_table_after_end_keeps_crlf(cx: &mut TestAppContext) { + let (document, cx) = open("Intro\r\nNext\r\n", MarkdownMode::Source, cx); + let editor = document.read_with(cx, |document, _| document.editor().clone()); + let focus = editor.read_with(cx, gpui::Focusable::focus_handle); + cx.update(|window, cx| window.focus(&focus, cx)); + cx.simulate_keystrokes("end"); + let caret = editor.read_with(cx, |editor, _| editor.primary().range().start); + assert_eq!(caret, 6, "End lands between CR and LF"); + document.update(cx, |document, cx| { + document.insert_table(cx).expect("inserted") + }); + assert_eq!( + text(&document, cx), + "Intro\r\n\r\n| | | |\r\n| ---- | ---- | ---- |\r\n| | | |\r\n| | | |\r\n\r\nNext\r\n" + ); +} + #[gpui::test] fn a_match_in_visual_opens_its_block_selected(cx: &mut TestAppContext) { let (document, cx) = open("# A\n\nfind me here\n", MarkdownMode::Visual, cx);