diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index b1027eeadd..84c1948a3a 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -3955,13 +3955,36 @@ impl Editor { } pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext) { - let cursor_position = self.selections.newest::(cx).head(); + let selection = self.selections.newest::(cx); let snapshot = self.buffer.read(cx).snapshot(cx); - let end_of_line = Point::new(cursor_position.row, snapshot.line_len(cursor_position.row)); - let start_of_next_line = end_of_line + Point::new(1, 0); - self.buffer.update(cx, |buffer, cx| { - buffer.edit([(end_of_line..start_of_next_line, " ")], None, cx) + let row_range = if selection.start.row == selection.end.row { + selection.start.row..selection.start.row + 1 + } else { + selection.start.row..selection.end.row + }; + + self.transact(cx, |this, cx| { + for (ix, row) in row_range.rev().enumerate() { + let end_of_line = Point::new(row, snapshot.line_len(row)); + let start_of_next_line = end_of_line + Point::new(1, 0); + + let replace = if snapshot.line_len(row + 1) > 0 { + " " + } else { + "" + }; + + this.buffer.update(cx, |buffer, cx| { + buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx) + }); + + if ix == 0 { + this.change_selections(Some(Autoscroll::fit()), cx, |s| { + s.select_ranges([end_of_line..end_of_line]) + }) + } + } }); } diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 1e9a745e9c..d11ddb5324 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -2332,8 +2332,8 @@ fn test_delete_line(cx: &mut TestAppContext) { fn test_join_lines(cx: &mut TestAppContext) { init_test(cx, |_| {}); - let (_, editor) = cx.add_window(|cx| { - let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx); + cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("aaa\nbbb\nccc\nddd\n\n", cx); let mut editor = build_editor(buffer.clone(), cx); let buffer = buffer.read(cx).as_singleton().unwrap(); @@ -2343,13 +2343,38 @@ fn test_join_lines(cx: &mut TestAppContext) { ); editor.join_lines(&JoinLines, cx); + assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd\n\n"); + assert_eq!( + editor.selections.ranges::(cx), + &[Point::new(0, 3)..Point::new(0, 3)] + ); - // assert_eq!( - // editor.selections.ranges::(cx), - // &[Point::new(0, 0), Point::new(0, 0)] - // ); + editor.change_selections(None, cx, |s| { + s.select_ranges([Point::new(0, 5)..Point::new(2, 2)]) + }); + editor.join_lines(&JoinLines, cx); + assert_eq!(buffer.read(cx).text(), "aaa bbb ccc ddd\n\n"); + assert_eq!( + editor.selections.ranges::(cx), + &[Point::new(0, 11)..Point::new(0, 11)] + ); - assert_eq!(buffer.read(cx).text(), "abc def\nghi\n"); + editor.undo(&Undo, cx); + assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd\n\n"); + assert_eq!( + editor.selections.ranges::(cx), + &[Point::new(0, 5)..Point::new(2, 2)] + ); + + editor.change_selections(None, cx, |s| { + s.select_ranges([Point::new(2, 1)..Point::new(2, 2)]) + }); + editor.join_lines(&JoinLines, cx); + assert_eq!(buffer.read(cx).text(), "aaa bbb\nccc\nddd\n"); + assert_eq!( + editor.selections.ranges::(cx), + [Point::new(2, 3)..Point::new(2, 3)] + ); editor });