diff --git a/crates/project/src/terminals.rs b/crates/project/src/terminals.rs index 45b79a7a5c9c8d7e51eab2426921d4edd6a490ba..1320a883f3a0e17ba4de24c148f1b1da1a925fe9 100644 --- a/crates/project/src/terminals.rs +++ b/crates/project/src/terminals.rs @@ -276,6 +276,18 @@ impl Project { cx: &AppContext, ) -> Option { let venv_settings = settings.detect_venv.as_option()?; + if let Some(path) = self.find_venv_in_worktree(abs_path, &venv_settings, cx) { + return Some(path); + } + self.find_venv_on_filesystem(abs_path, &venv_settings, cx) + } + + fn find_venv_in_worktree( + &self, + abs_path: &Path, + venv_settings: &terminal_settings::VenvSettingsContent, + cx: &AppContext, + ) -> Option { let bin_dir_name = match std::env::consts::OS { "windows" => "Scripts", _ => "bin", @@ -283,7 +295,7 @@ impl Project { venv_settings .directories .iter() - .map(|virtual_environment_name| abs_path.join(virtual_environment_name)) + .map(|name| abs_path.join(name)) .find(|venv_path| { let bin_path = venv_path.join(bin_dir_name); self.find_worktree(&bin_path, cx) @@ -294,6 +306,32 @@ impl Project { }) } + fn find_venv_on_filesystem( + &self, + abs_path: &Path, + venv_settings: &terminal_settings::VenvSettingsContent, + cx: &AppContext, + ) -> Option { + let (worktree, _) = self.find_worktree(abs_path, cx)?; + let fs = worktree.read(cx).as_local()?.fs(); + let bin_dir_name = match std::env::consts::OS { + "windows" => "Scripts", + _ => "bin", + }; + venv_settings + .directories + .iter() + .map(|name| abs_path.join(name)) + .find(|venv_path| { + let bin_path = venv_path.join(bin_dir_name); + // One-time synchronous check is acceptable for terminal/task initialization + smol::block_on(fs.metadata(&bin_path)) + .ok() + .flatten() + .map_or(false, |meta| meta.is_dir) + }) + } + fn python_activate_command( &self, venv_base_directory: &Path,