From 4d5e25f4088025ee4f837c25c7832ac2fe9c7fad Mon Sep 17 00:00:00 2001 From: Shashank Suresh <52377159+shashank-suresh@users.noreply.github.com> Date: Thu, 12 Mar 2026 14:52:55 +0530 Subject: [PATCH] editor: Add line range support to editor::CopyFileLocation command (#51328) Closes #51309 Before you mark this PR as ready for review, make sure that you have: - [X] Added a solid test coverage and/or screenshots from doing manual testing - [X] Done a self-review taking into account security and performance aspects - [X] Aligned any UI changes with the [UI checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) Release Notes: - Improved `editor::CopyFileLocation` command to include the full selected line range (e.g. 'src/main.rs:12-18') when multiple lines are selected, rather than only the first line number. --- .../collab/tests/integration/editor_tests.rs | 48 +++++++++++++++++++ crates/editor/src/editor.rs | 24 +++++++--- 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/crates/collab/tests/integration/editor_tests.rs b/crates/collab/tests/integration/editor_tests.rs index 0d0569182d5a9ff235642d61c39f0b5bc15b6cb0..6b23780156e03d62543cf597e82959083685f0c0 100644 --- a/crates/collab/tests/integration/editor_tests.rs +++ b/crates/collab/tests/integration/editor_tests.rs @@ -4721,6 +4721,54 @@ async fn test_copy_file_location(cx_a: &mut TestAppContext, cx_b: &mut TestAppCo cx_b.read_from_clipboard().and_then(|item| item.text()), Some(format!("{}:2", path!("src/main.rs"))) ); + + editor_a.update_in(cx_a, |editor, window, cx| { + editor.change_selections(Default::default(), window, cx, |s| { + s.select_ranges([MultiBufferOffset(16)..MultiBufferOffset(44)]); + }); + editor.copy_file_location(&CopyFileLocation, window, cx); + }); + + assert_eq!( + cx_a.read_from_clipboard().and_then(|item| item.text()), + Some(format!("{}:2-3", path!("src/main.rs"))) + ); + + editor_b.update_in(cx_b, |editor, window, cx| { + editor.change_selections(Default::default(), window, cx, |s| { + s.select_ranges([MultiBufferOffset(16)..MultiBufferOffset(44)]); + }); + editor.copy_file_location(&CopyFileLocation, window, cx); + }); + + assert_eq!( + cx_b.read_from_clipboard().and_then(|item| item.text()), + Some(format!("{}:2-3", path!("src/main.rs"))) + ); + + editor_a.update_in(cx_a, |editor, window, cx| { + editor.change_selections(Default::default(), window, cx, |s| { + s.select_ranges([MultiBufferOffset(16)..MultiBufferOffset(43)]); + }); + editor.copy_file_location(&CopyFileLocation, window, cx); + }); + + assert_eq!( + cx_a.read_from_clipboard().and_then(|item| item.text()), + Some(format!("{}:2", path!("src/main.rs"))) + ); + + editor_b.update_in(cx_b, |editor, window, cx| { + editor.change_selections(Default::default(), window, cx, |s| { + s.select_ranges([MultiBufferOffset(16)..MultiBufferOffset(43)]); + }); + editor.copy_file_location(&CopyFileLocation, window, cx); + }); + + assert_eq!( + cx_b.read_from_clipboard().and_then(|item| item.text()), + Some(format!("{}:2", path!("src/main.rs"))) + ); } #[track_caller] diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index dc2696eb2ca83999934cab6cdee82e364657c70e..18a02e9773b3952d99b71f6d337f3c8950aff78e 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -22846,18 +22846,28 @@ impl Editor { _: &mut Window, cx: &mut Context, ) { - let selection = self - .selections - .newest::(&self.display_snapshot(cx)) - .start - .row - + 1; + let selection = self.selections.newest::(&self.display_snapshot(cx)); + + let start_line = selection.start.row + 1; + let end_line = selection.end.row + 1; + + let end_line = if selection.end.column == 0 && end_line > start_line { + end_line - 1 + } else { + end_line + }; + if let Some(file_location) = self.active_excerpt(cx).and_then(|(_, buffer, _)| { let project = self.project()?.read(cx); let file = buffer.read(cx).file()?; let path = file.path().display(project.path_style(cx)); - Some(format!("{path}:{selection}")) + let location = if start_line == end_line { + format!("{path}:{start_line}") + } else { + format!("{path}:{start_line}-{end_line}") + }; + Some(location) }) { cx.write_to_clipboard(ClipboardItem::new_string(file_location)); }