Detailed changes
@@ -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