Expand ~ in warp://action/new_tab?path= URLs (#9277)
## Description Fixes #9178. `warp://action/new_tab?path=~/foo` was opening the current directory instead of `~/foo`. The query value was being passed straight into `PathBuf::from_str`, which doesn't expand `~`, so the resulting literal `~/foo` couldn't be resolved by `open_file` and the new tab silently fell back to the current location. Routed the `path` query through `shellexpand::tilde` (already a workspace dependency) before constructing the `PathBuf`. The same call site serves both `/new_tab` and `/new_window`, so both URLs benefit. Absolute and relative paths are unchanged. ## Testing Added 6 unit tests in `app/src/uri/uri_test.rs`: - `~/Projects` expands to `$HOME/Projects` - URL-encoded `%7E%2FProjects` expands the same way - absolute path `/tmp/foo` unchanged - relative path `relative/dir` unchanged - missing `path=` returns `None` - bare `~` expands to `$HOME` Also verified the helper in a standalone harness against extra edge cases: empty value, non-leading `~` (unchanged, correct shell semantics), `~user/path` (unchanged, a shellexpand limitation), and URL-encoded spaces. Couldn't run the in-tree test suite locally because the Metal toolchain isn't installed, so relying on CI for the full clippy / nextest pass. ## Agent Mode - [ ] Warp Agent Mode - This PR was created via Warp's AI Agent Mode ## Changelog Entries for Stable CHANGELOG-BUG-FIX: `warp://action/new_tab?path=~/foo` (and `/new_window`) now expand `~` to your home directory. --------- Co-authored-by: seemeroland <roland@warp.dev>
This commit is contained in:
co-authored by
seemeroland
parent
389716a905
commit
c0feac21db
+8
-5
@@ -657,6 +657,13 @@ fn find_matching_config_name<'a>(
|
||||
.find(|&config| config.name.to_lowercase() == target_name_lower)
|
||||
}
|
||||
|
||||
/// Extract the `path` query parameter, expanding a leading `~` to the
|
||||
/// user's home directory.
|
||||
fn parse_tab_path(url: &Url) -> Option<PathBuf> {
|
||||
let raw = url.query_pairs().find(|(k, _)| k == "path")?.1;
|
||||
Some(PathBuf::from(shellexpand::tilde(&raw).into_owned()))
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Action {
|
||||
NewTab,
|
||||
@@ -706,11 +713,7 @@ impl Action {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let Some(Ok(path)) = url
|
||||
.query_pairs()
|
||||
.find(|(k, _v)| k == "path")
|
||||
.map(|(_, path)| PathBuf::from_str(&path))
|
||||
else {
|
||||
let Some(path) = parse_tab_path(url) else {
|
||||
log::warn!("Could not parse path to open a new tab/window");
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -533,3 +533,43 @@ fn validate_custom_uri_errors_do_not_leak_query_string() {
|
||||
assert!(!msg.contains("refresh_token"), "{msg}");
|
||||
assert!(!msg.contains("LEAKED"), "{msg}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_tab_path_expands_tilde() {
|
||||
let url = Url::parse("warp://action/new_tab?path=~/Projects").unwrap();
|
||||
let home = dirs::home_dir().expect("HOME must be set for this test");
|
||||
assert_eq!(parse_tab_path(&url), Some(home.join("Projects")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_tab_path_expands_url_encoded_tilde() {
|
||||
// `%7E` and `%2F` are URL-encoded `~` and `/`.
|
||||
let url = Url::parse("warp://action/new_tab?path=%7E%2FProjects").unwrap();
|
||||
let home = dirs::home_dir().expect("HOME must be set for this test");
|
||||
assert_eq!(parse_tab_path(&url), Some(home.join("Projects")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_tab_path_absolute_path_unchanged() {
|
||||
let url = Url::parse("warp://action/new_tab?path=/tmp/foo").unwrap();
|
||||
assert_eq!(parse_tab_path(&url), Some(PathBuf::from("/tmp/foo")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_tab_path_relative_path_unchanged() {
|
||||
let url = Url::parse("warp://action/new_tab?path=relative/dir").unwrap();
|
||||
assert_eq!(parse_tab_path(&url), Some(PathBuf::from("relative/dir")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_tab_path_missing_returns_none() {
|
||||
let url = Url::parse("warp://action/new_tab").unwrap();
|
||||
assert_eq!(parse_tab_path(&url), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_tab_path_bare_tilde() {
|
||||
let url = Url::parse("warp://action/new_tab?path=~").unwrap();
|
||||
let home = dirs::home_dir().expect("HOME must be set for this test");
|
||||
assert_eq!(parse_tab_path(&url), Some(home));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user