diff --git a/Cargo.lock b/Cargo.lock index a97219e06..6868f1553 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4885,6 +4885,7 @@ dependencies = [ "open", "ordered-float", "palette", + "percent-encoding", "portable-pty", "pretty_env_logger", "promise", @@ -4972,6 +4973,7 @@ dependencies = [ "lazy_static", "log", "mux", + "percent-encoding", "portable-pty", "promise", "rangeset", diff --git a/wezterm-gui/Cargo.toml b/wezterm-gui/Cargo.toml index 211d918cb..f1557badc 100644 --- a/wezterm-gui/Cargo.toml +++ b/wezterm-gui/Cargo.toml @@ -40,6 +40,7 @@ mux = { path = "../mux" } open = "1.4" ordered-float = "2.1" palette = "0.5" +percent-encoding = "2" portable-pty = { path = "../pty", features = ["serde_support", "ssh"]} promise = { path = "../promise" } pulldown-cmark = "0.8" diff --git a/wezterm-gui/src/termwindow/spawn.rs b/wezterm-gui/src/termwindow/spawn.rs index 1307ec149..42861f058 100644 --- a/wezterm-gui/src/termwindow/spawn.rs +++ b/wezterm-gui/src/termwindow/spawn.rs @@ -5,6 +5,7 @@ use mux::activity::Activity; use mux::domain::DomainState; use mux::tab::SplitDirection; use mux::Mux; +use percent_encoding::percent_decode_str; use portable_pty::{CommandBuilder, PtySize}; use std::sync::Arc; @@ -127,15 +128,19 @@ impl super::TermWindow { } else { match cwd { Some(url) if url.scheme() == "file" => { - let path = url.path().to_string(); - // On Windows the file URI can produce a path like: - // `/C:\Users` which is valid in a file URI, but the leading slash - // is not liked by the windows file APIs, so we strip it off here. - let bytes = path.as_bytes(); - if bytes.len() > 2 && bytes[0] == b'/' && bytes[2] == b':' { - Some(path[1..].to_owned()) + if let Ok(path) = percent_decode_str(url.path()).decode_utf8() { + let path = path.into_owned(); + // On Windows the file URI can produce a path like: + // `/C:\Users` which is valid in a file URI, but the leading slash + // is not liked by the windows file APIs, so we strip it off here. + let bytes = path.as_bytes(); + if bytes.len() > 2 && bytes[0] == b'/' && bytes[2] == b':' { + Some(path[1..].to_owned()) + } else { + Some(path) + } } else { - Some(path) + None } } Some(_) | None => None, diff --git a/wezterm-mux-server-impl/Cargo.toml b/wezterm-mux-server-impl/Cargo.toml index c0a6cb424..f892ae77f 100644 --- a/wezterm-mux-server-impl/Cargo.toml +++ b/wezterm-mux-server-impl/Cargo.toml @@ -16,6 +16,7 @@ hostname = "0.3" lazy_static = "1.4" log = "0.4" mux = { path = "../mux" } +percent-encoding = "2" portable-pty = { path = "../pty", features = ["serde_support"]} promise = { path = "../promise" } rangeset = { path = "../rangeset" } diff --git a/wezterm-mux-server-impl/src/sessionhandler.rs b/wezterm-mux-server-impl/src/sessionhandler.rs index 511a79030..9cd458b20 100644 --- a/wezterm-mux-server-impl/src/sessionhandler.rs +++ b/wezterm-mux-server-impl/src/sessionhandler.rs @@ -6,6 +6,7 @@ use mux::pane::{Pane, PaneId}; use mux::renderable::{RenderableDimensions, StableCursorPosition}; use mux::tab::TabId; use mux::Mux; +use percent_encoding::percent_decode_str; use portable_pty::PtySize; use promise::spawn::spawn_into_main_thread; use rangeset::RangeSet; @@ -611,8 +612,13 @@ async fn split_pane(split: SplitPane, sender: PduSender) -> anyhow::Result let cwd = split.command_dir.or_else(|| { mux.get_pane(pane_id) .and_then(|pane| pane.get_current_working_dir()) - .map(|url| { - let path = url.path().to_string(); + .and_then(|url| { + percent_decode_str(url.path()) + .decode_utf8() + .ok() + .map(|path| path.into_owned()) + }) + .map(|path| { // On Windows the file URI can produce a path like: // `/C:\Users` which is valid in a file URI, but the leading slash // is not liked by the windows file APIs, so we strip it off here.