terminal_view: Fix terminal opening in root directory when editing single file corktree (#42953)

Fixes #42945

## Problem
When opening a single file via command line (e.g., `zed
~/Downloads/file.txt`), the terminal panel was opening in the root
directory (/) instead of the file's directory.

## Root Cause
The code only checked for active project directory, which returns None
when a single file is opened. Additionally, file worktrees weren't
handling parent directory lookup.

## Solution
Added fallback logic to use the first project directory when there's no
active entry, and made file worktrees return their parent directory
instead of None.

## Testing
- All existing tests pass
- Added test coverage for file worktree scenarios
- Manually tested with `zed ~/Downloads/file.txt` - terminal now opens
in correct directory

This improves the user experience for users who frequently open single
files from the command line.

## Release Notes

- Fixed terminal opening in root directory when editing single files
from the command line
This commit is contained in:
Engin Açıkgöz
2025-11-18 13:37:48 +01:00
committed by GitHub
parent c1d9dc369c
commit f17d2c92b6
+11 -7
View File
@@ -1556,7 +1556,8 @@ pub(crate) fn default_working_directory(workspace: &Workspace, cx: &App) -> Opti
.read(cx)
.active_project_directory(cx)
.as_deref()
.map(Path::to_path_buf),
.map(Path::to_path_buf)
.or_else(|| first_project_directory(workspace, cx)),
WorkingDirectory::FirstProjectDirectory => first_project_directory(workspace, cx),
WorkingDirectory::AlwaysHome => None,
WorkingDirectory::Always { directory } => {
@@ -1570,10 +1571,13 @@ pub(crate) fn default_working_directory(workspace: &Workspace, cx: &App) -> Opti
///Gets the first project's home directory, or the home directory
fn first_project_directory(workspace: &Workspace, cx: &App) -> Option<PathBuf> {
let worktree = workspace.worktrees(cx).next()?.read(cx);
if !worktree.root_entry()?.is_dir() {
return None;
let worktree_path = worktree.abs_path();
if worktree.root_entry()?.is_dir() {
Some(worktree_path.to_path_buf())
} else {
// If worktree is a file, return its parent directory
worktree_path.parent().map(|p| p.to_path_buf())
}
Some(worktree.abs_path().to_path_buf())
}
#[cfg(test)]
@@ -1606,7 +1610,7 @@ mod tests {
});
}
// No active entry, but a worktree, worktree is a file -> home_dir()
// No active entry, but a worktree, worktree is a file -> parent directory
#[gpui::test]
async fn no_active_entry_worktree_is_file(cx: &mut TestAppContext) {
let (project, workspace) = init_test(cx).await;
@@ -1621,9 +1625,9 @@ mod tests {
assert!(workspace.worktrees(cx).next().is_some());
let res = default_working_directory(workspace, cx);
assert_eq!(res, None);
assert_eq!(res, Some(Path::new("/").to_path_buf()));
let res = first_project_directory(workspace, cx);
assert_eq!(res, None);
assert_eq!(res, Some(Path::new("/").to_path_buf()));
});
}