diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index d8434ffa005569d903fba8b44b95e05bfe47c917..19c6ca50b364531602b328e76fd00d7f76e1d75f 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1644,7 +1644,15 @@ impl ClipboardSelection { project.absolute_path(&project_path, cx) }); - let line_range = file_path.as_ref().map(|_| range.start.row..=range.end.row); + let line_range = file_path.as_ref().and_then(|_| { + let (_, start_point, start_excerpt_id) = buffer.point_to_buffer_point(range.start)?; + let (_, end_point, end_excerpt_id) = buffer.point_to_buffer_point(range.end)?; + if start_excerpt_id == end_excerpt_id { + Some(start_point.row..=end_point.row) + } else { + None + } + }); Self { len, diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 0d0b1435325bca20f2dc330ad56190d9cad08c9b..7dc8a20a10191f716eb41f3a7686d1d3eff22871 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -7631,6 +7631,65 @@ async fn test_copy_trim_line_mode(cx: &mut TestAppContext) { ); } +#[gpui::test] +async fn test_clipboard_line_numbers_from_multibuffer(cx: &mut TestAppContext) { + init_test(cx, |_| {}); + + let fs = FakeFs::new(cx.executor()); + fs.insert_file( + path!("/file.txt"), + "first line\nsecond line\nthird line\nfourth line\nfifth line\n".into(), + ) + .await; + + let project = Project::test(fs, [path!("/file.txt").as_ref()], cx).await; + + let buffer = project + .update(cx, |project, cx| { + project.open_local_buffer(path!("/file.txt"), cx) + }) + .await + .unwrap(); + + let multibuffer = cx.new(|cx| { + let mut multibuffer = MultiBuffer::new(ReadWrite); + multibuffer.push_excerpts( + buffer.clone(), + [ExcerptRange::new(Point::new(2, 0)..Point::new(5, 0))], + cx, + ); + multibuffer + }); + + let (editor, cx) = cx.add_window_view(|window, cx| { + build_editor_with_project(project.clone(), multibuffer, window, cx) + }); + + editor.update_in(cx, |editor, window, cx| { + assert_eq!(editor.text(cx), "third line\nfourth line\nfifth line\n"); + + editor.select_all(&SelectAll, window, cx); + editor.copy(&Copy, window, cx); + }); + + let clipboard_selections: Option> = cx + .read_from_clipboard() + .and_then(|item| item.entries().first().cloned()) + .and_then(|entry| match entry { + gpui::ClipboardEntry::String(text) => text.metadata_json(), + _ => None, + }); + + let selections = clipboard_selections.expect("should have clipboard selections"); + assert_eq!(selections.len(), 1); + let selection = &selections[0]; + assert_eq!( + selection.line_range, + Some(2..=5), + "line range should be from original file (rows 2-5), not multibuffer rows (0-2)" + ); +} + #[gpui::test] async fn test_paste_multiline(cx: &mut TestAppContext) { init_test(cx, |_| {});