editor: Fix copy file actions not working in remote environments (#43362)

Closes #42500

Release Notes:

- Fixed all three editor actions not working in remote environments
  - `editor: copy file name`
  - `editor: copy file location`
  - `editor: copy file name without extension`

Here's the before/after:




https://github.com/user-attachments/assets/bfb03e99-2e1a-47a2-bd26-280180154fe3
This commit is contained in:
Mayank Verma
2025-11-24 21:45:12 +00:00
committed by GitHub
parent 769464762a
commit 9e69ac889c
2 changed files with 302 additions and 12 deletions
+285 -2
View File
@@ -7,8 +7,9 @@ use editor::{
DocumentColorsRenderMode, Editor, FETCH_COLORS_DEBOUNCE_TIMEOUT, MultiBufferOffset, RowInfo,
SelectionEffects,
actions::{
ConfirmCodeAction, ConfirmCompletion, ConfirmRename, ContextMenuFirst,
ExpandMacroRecursively, MoveToEnd, Redo, Rename, SelectAll, ToggleCodeActions, Undo,
ConfirmCodeAction, ConfirmCompletion, ConfirmRename, ContextMenuFirst, CopyFileLocation,
CopyFileName, CopyFileNameWithoutExtension, ExpandMacroRecursively, MoveToEnd, Redo,
Rename, SelectAll, ToggleCodeActions, Undo,
},
test::{
editor_test_context::{AssertionContextManager, EditorTestContext},
@@ -4269,6 +4270,288 @@ async fn test_client_can_query_lsp_ext(cx_a: &mut TestAppContext, cx_b: &mut Tes
});
}
#[gpui::test]
async fn test_copy_file_name_without_extension(
cx_a: &mut TestAppContext,
cx_b: &mut TestAppContext,
) {
let mut server = TestServer::start(cx_a.executor()).await;
let client_a = server.create_client(cx_a, "user_a").await;
let client_b = server.create_client(cx_b, "user_b").await;
server
.create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
.await;
cx_b.update(editor::init);
client_a
.fs()
.insert_tree(
path!("/root"),
json!({
"src": {
"main.rs": indoc! {"
fn main() {
println!(\"Hello, world!\");
}
"},
}
}),
)
.await;
let (project_a, worktree_id) = client_a.build_local_project(path!("/root"), cx_a).await;
let active_call_a = cx_a.read(ActiveCall::global);
let project_id = active_call_a
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
.await
.unwrap();
let project_b = client_b.join_remote_project(project_id, cx_b).await;
let (workspace_a, cx_a) = client_a.build_workspace(&project_a, cx_a);
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
let editor_a = workspace_a
.update_in(cx_a, |workspace, window, cx| {
workspace.open_path(
(worktree_id, rel_path("src/main.rs")),
None,
true,
window,
cx,
)
})
.await
.unwrap()
.downcast::<Editor>()
.unwrap();
let editor_b = workspace_b
.update_in(cx_b, |workspace, window, cx| {
workspace.open_path(
(worktree_id, rel_path("src/main.rs")),
None,
true,
window,
cx,
)
})
.await
.unwrap()
.downcast::<Editor>()
.unwrap();
cx_a.run_until_parked();
cx_b.run_until_parked();
editor_a.update_in(cx_a, |editor, window, cx| {
editor.copy_file_name_without_extension(&CopyFileNameWithoutExtension, window, cx);
});
assert_eq!(
cx_a.read_from_clipboard().and_then(|item| item.text()),
Some("main".to_string())
);
editor_b.update_in(cx_b, |editor, window, cx| {
editor.copy_file_name_without_extension(&CopyFileNameWithoutExtension, window, cx);
});
assert_eq!(
cx_b.read_from_clipboard().and_then(|item| item.text()),
Some("main".to_string())
);
}
#[gpui::test]
async fn test_copy_file_name(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
let mut server = TestServer::start(cx_a.executor()).await;
let client_a = server.create_client(cx_a, "user_a").await;
let client_b = server.create_client(cx_b, "user_b").await;
server
.create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
.await;
cx_b.update(editor::init);
client_a
.fs()
.insert_tree(
path!("/root"),
json!({
"src": {
"main.rs": indoc! {"
fn main() {
println!(\"Hello, world!\");
}
"},
}
}),
)
.await;
let (project_a, worktree_id) = client_a.build_local_project(path!("/root"), cx_a).await;
let active_call_a = cx_a.read(ActiveCall::global);
let project_id = active_call_a
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
.await
.unwrap();
let project_b = client_b.join_remote_project(project_id, cx_b).await;
let (workspace_a, cx_a) = client_a.build_workspace(&project_a, cx_a);
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
let editor_a = workspace_a
.update_in(cx_a, |workspace, window, cx| {
workspace.open_path(
(worktree_id, rel_path("src/main.rs")),
None,
true,
window,
cx,
)
})
.await
.unwrap()
.downcast::<Editor>()
.unwrap();
let editor_b = workspace_b
.update_in(cx_b, |workspace, window, cx| {
workspace.open_path(
(worktree_id, rel_path("src/main.rs")),
None,
true,
window,
cx,
)
})
.await
.unwrap()
.downcast::<Editor>()
.unwrap();
cx_a.run_until_parked();
cx_b.run_until_parked();
editor_a.update_in(cx_a, |editor, window, cx| {
editor.copy_file_name(&CopyFileName, window, cx);
});
assert_eq!(
cx_a.read_from_clipboard().and_then(|item| item.text()),
Some("main.rs".to_string())
);
editor_b.update_in(cx_b, |editor, window, cx| {
editor.copy_file_name(&CopyFileName, window, cx);
});
assert_eq!(
cx_b.read_from_clipboard().and_then(|item| item.text()),
Some("main.rs".to_string())
);
}
#[gpui::test]
async fn test_copy_file_location(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
let mut server = TestServer::start(cx_a.executor()).await;
let client_a = server.create_client(cx_a, "user_a").await;
let client_b = server.create_client(cx_b, "user_b").await;
server
.create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)])
.await;
cx_b.update(editor::init);
client_a
.fs()
.insert_tree(
path!("/root"),
json!({
"src": {
"main.rs": indoc! {"
fn main() {
println!(\"Hello, world!\");
}
"},
}
}),
)
.await;
let (project_a, worktree_id) = client_a.build_local_project(path!("/root"), cx_a).await;
let active_call_a = cx_a.read(ActiveCall::global);
let project_id = active_call_a
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
.await
.unwrap();
let project_b = client_b.join_remote_project(project_id, cx_b).await;
let (workspace_a, cx_a) = client_a.build_workspace(&project_a, cx_a);
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
let editor_a = workspace_a
.update_in(cx_a, |workspace, window, cx| {
workspace.open_path(
(worktree_id, rel_path("src/main.rs")),
None,
true,
window,
cx,
)
})
.await
.unwrap()
.downcast::<Editor>()
.unwrap();
let editor_b = workspace_b
.update_in(cx_b, |workspace, window, cx| {
workspace.open_path(
(worktree_id, rel_path("src/main.rs")),
None,
true,
window,
cx,
)
})
.await
.unwrap()
.downcast::<Editor>()
.unwrap();
cx_a.run_until_parked();
cx_b.run_until_parked();
editor_a.update_in(cx_a, |editor, window, cx| {
editor.change_selections(Default::default(), window, cx, |s| {
s.select_ranges([MultiBufferOffset(16)..MultiBufferOffset(16)]);
});
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(16)]);
});
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]
fn tab_undo_assert(
cx_a: &mut EditorTestContext,
+17 -10
View File
@@ -20234,18 +20234,20 @@ impl Editor {
_: &mut Window,
cx: &mut Context<Self>,
) {
if let Some(file) = self.target_file(cx)
&& let Some(file_stem) = file.path().file_stem()
{
if let Some(file_stem) = self.active_excerpt(cx).and_then(|(_, buffer, _)| {
let file = buffer.read(cx).file()?;
file.path().file_stem()
}) {
cx.write_to_clipboard(ClipboardItem::new_string(file_stem.to_string()));
}
}
pub fn copy_file_name(&mut self, _: &CopyFileName, _: &mut Window, cx: &mut Context<Self>) {
if let Some(file) = self.target_file(cx)
&& let Some(name) = file.path().file_name()
{
cx.write_to_clipboard(ClipboardItem::new_string(name.to_string()));
if let Some(file_name) = self.active_excerpt(cx).and_then(|(_, buffer, _)| {
let file = buffer.read(cx).file()?;
Some(file.file_name(cx))
}) {
cx.write_to_clipboard(ClipboardItem::new_string(file_name.to_string()));
}
}
@@ -20519,9 +20521,14 @@ impl Editor {
.start
.row
+ 1;
if let Some(file) = self.target_file(cx) {
let path = file.path().display(file.path_style(cx));
cx.write_to_clipboard(ClipboardItem::new_string(format!("{path}:{selection}")));
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}"))
}) {
cx.write_to_clipboard(ClipboardItem::new_string(file_location));
}
}