mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 03:14:56 +07:00
project_panel: Show Reveal in File Manager on wsl (#47288)
Assimilates https://github.com/zed-industries/zed/pull/46856 and adds support for reveal file manager in the project panel on wsl. Closes https://github.com/zed-industries/zed/pull/46856 Release Notes: - Fixed "Reveal in File Manager" not working for WSL remote connections on Windows. - Show "Reveal in File Manager" in the project panel context menu on WSL --------- Co-authored-by: Max Malkin <maxim_malkin@outlook.com>
This commit is contained in:
parent
071b3d92e8
commit
b082481a7a
7 changed files with 76 additions and 16 deletions
|
|
@ -22248,8 +22248,12 @@ impl Editor {
|
|||
_window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
if let Some(target) = self.target_file(cx) {
|
||||
cx.reveal_path(&target.abs_path(cx));
|
||||
if let Some(path) = self.target_file_abs_path(cx) {
|
||||
if let Some(project) = self.project() {
|
||||
project.update(cx, |project, cx| project.reveal_path(&path, cx));
|
||||
} else {
|
||||
cx.reveal_path(&path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -265,6 +265,8 @@ pub fn deploy_context_menu(
|
|||
!has_reveal_target,
|
||||
if cfg!(target_os = "macos") {
|
||||
"Reveal in Finder"
|
||||
} else if cfg!(target_os = "windows") {
|
||||
"Reveal in File Explorer"
|
||||
} else {
|
||||
"Reveal in File Manager"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1438,12 +1438,16 @@ impl OutlinePanel {
|
|||
|
||||
let context_menu = ContextMenu::build(window, cx, |menu, _, _| {
|
||||
menu.context(self.focus_handle.clone())
|
||||
.when(cfg!(target_os = "macos"), |menu| {
|
||||
menu.action("Reveal in Finder", Box::new(RevealInFileManager))
|
||||
})
|
||||
.when(cfg!(not(target_os = "macos")), |menu| {
|
||||
menu.action("Reveal in File Manager", Box::new(RevealInFileManager))
|
||||
})
|
||||
.action(
|
||||
if cfg!(target_os = "macos") {
|
||||
"Reveal in Finder"
|
||||
} else if cfg!(target_os = "windows") {
|
||||
"Reveal in File Explorer"
|
||||
} else {
|
||||
"Reveal in File Manager"
|
||||
},
|
||||
Box::new(RevealInFileManager),
|
||||
)
|
||||
.action("Open in Terminal", Box::new(OpenInTerminal))
|
||||
.when(is_unfoldable, |menu| {
|
||||
menu.action("Unfold Directory", Box::new(UnfoldDirectory))
|
||||
|
|
@ -2012,7 +2016,8 @@ impl OutlinePanel {
|
|||
.selected_entry()
|
||||
.and_then(|entry| self.abs_path(entry, cx))
|
||||
{
|
||||
cx.reveal_path(&abs_path);
|
||||
self.project
|
||||
.update(cx, |project, cx| project.reveal_path(&abs_path, cx));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -107,6 +107,8 @@ use node_runtime::NodeRuntime;
|
|||
use parking_lot::Mutex;
|
||||
pub use prettier_store::PrettierStore;
|
||||
use project_settings::{ProjectSettings, SettingsObserver, SettingsObserverEvent};
|
||||
#[cfg(target_os = "windows")]
|
||||
use remote::wsl_path_to_windows_path;
|
||||
use remote::{RemoteClient, RemoteConnectionOptions};
|
||||
use rpc::{
|
||||
AnyProtoClient, ErrorCode,
|
||||
|
|
@ -2136,6 +2138,27 @@ impl Project {
|
|||
.map(|remote| remote.read(cx).connection_options())
|
||||
}
|
||||
|
||||
/// Reveals the given path in the system file manager.
|
||||
///
|
||||
/// On Windows with a WSL remote connection, this converts the POSIX path
|
||||
/// to a Windows UNC path before revealing.
|
||||
pub fn reveal_path(&self, path: &Path, cx: &mut Context<Self>) {
|
||||
#[cfg(target_os = "windows")]
|
||||
if let Some(RemoteConnectionOptions::Wsl(wsl_options)) = self.remote_connection_options(cx)
|
||||
{
|
||||
let path = path.to_path_buf();
|
||||
cx.spawn(async move |_, cx| {
|
||||
wsl_path_to_windows_path(&wsl_options, &path)
|
||||
.await
|
||||
.map(|windows_path| cx.update(|cx| cx.reveal_path(&windows_path)))
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
return;
|
||||
}
|
||||
|
||||
cx.reveal_path(path);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn replica_id(&self) -> ReplicaId {
|
||||
match self.client_state {
|
||||
|
|
|
|||
|
|
@ -1088,7 +1088,7 @@ impl ProjectPanel {
|
|||
let is_read_only = project.is_read_only(cx);
|
||||
let is_remote = project.is_remote();
|
||||
let is_collab = project.is_via_collab();
|
||||
let is_local = project.is_local();
|
||||
let is_local = project.is_local() || project.is_via_wsl_with_host_interop(cx);
|
||||
|
||||
let settings = ProjectPanelSettings::get_global(cx);
|
||||
let visible_worktrees_count = project.visible_worktrees(cx).count();
|
||||
|
|
@ -1119,11 +1119,17 @@ impl ProjectPanel {
|
|||
menu.action("New File", Box::new(NewFile))
|
||||
.action("New Folder", Box::new(NewDirectory))
|
||||
.separator()
|
||||
.when(is_local && cfg!(target_os = "macos"), |menu| {
|
||||
menu.action("Reveal in Finder", Box::new(RevealInFileManager))
|
||||
})
|
||||
.when(is_local && cfg!(not(target_os = "macos")), |menu| {
|
||||
menu.action("Reveal in File Manager", Box::new(RevealInFileManager))
|
||||
.when(is_local, |menu| {
|
||||
menu.action(
|
||||
if cfg!(target_os = "macos") && !is_remote {
|
||||
"Reveal in Finder"
|
||||
} else if cfg!(target_os = "windows") && !is_remote {
|
||||
"Reveal in File Explorer"
|
||||
} else {
|
||||
"Reveal in File Manager"
|
||||
},
|
||||
Box::new(RevealInFileManager),
|
||||
)
|
||||
})
|
||||
.when(is_local, |menu| {
|
||||
menu.action("Open in Default App", Box::new(OpenWithSystem))
|
||||
|
|
@ -3077,7 +3083,9 @@ impl ProjectPanel {
|
|||
cx: &mut Context<Self>,
|
||||
) {
|
||||
if let Some((worktree, entry)) = self.selected_sub_entry(cx) {
|
||||
cx.reveal_path(&worktree.read(cx).absolutize(&entry.path));
|
||||
let path = worktree.read(cx).absolutize(&entry.path);
|
||||
self.project
|
||||
.update(cx, |project, cx| project.reveal_path(&path, cx));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ pub use remote_client::{
|
|||
pub use transport::docker::DockerConnectionOptions;
|
||||
pub use transport::ssh::{SshConnectionOptions, SshPortForwardOption};
|
||||
pub use transport::wsl::WslConnectionOptions;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use transport::wsl::wsl_path_to_windows_path;
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub use transport::mock::{
|
||||
|
|
|
|||
|
|
@ -579,6 +579,22 @@ async fn windows_path_to_wsl_path_impl(
|
|||
run_wsl_command_with_output_impl(options, "wslpath", &["-u", &source]).await
|
||||
}
|
||||
|
||||
/// Converts a WSL/POSIX path to a Windows path using `wslpath -w`.
|
||||
///
|
||||
/// For example, `/home/user/project` becomes `\\wsl.localhost\Ubuntu\home\user\project`
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn wsl_path_to_windows_path(
|
||||
options: &WslConnectionOptions,
|
||||
wsl_path: &Path,
|
||||
) -> impl Future<Output = Result<PathBuf>> + use<> {
|
||||
let wsl_path_str = wsl_path.to_string_lossy().to_string();
|
||||
let command = wsl_command_impl(options, "wslpath", &["-w", &wsl_path_str], true);
|
||||
async move {
|
||||
let windows_path = run_wsl_command_impl(command).await?;
|
||||
Ok(PathBuf::from(windows_path))
|
||||
}
|
||||
}
|
||||
|
||||
fn run_wsl_command_impl(mut command: process::Command) -> impl Future<Output = Result<String>> {
|
||||
async move {
|
||||
let output = command
|
||||
|
|
|
|||
Loading…
Reference in a new issue