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:
Faizan Qureshi
2026-04-28 16:00:24 -07:00
committed by GitHub
co-authored by seemeroland
parent 389716a905
commit c0feac21db
2 changed files with 48 additions and 5 deletions
+8 -5
View File
@@ -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;
};