@@ -35,7 +35,7 @@ use std::{
35
35
path:: { Path , PathBuf } ,
36
36
sync:: Arc ,
37
37
} ;
38
- use task:: { TaskTemplate , TaskTemplates , VariableName } ;
38
+ use task:: { ShellKind , TaskTemplate , TaskTemplates , VariableName } ;
39
39
use util:: ResultExt ;
40
40
41
41
pub ( crate ) struct PyprojectTomlManifestProvider ;
@@ -872,14 +872,17 @@ impl ToolchainLister for PythonToolchainProvider {
872
872
if let Some ( nk) = name_and_kind {
873
873
_ = write ! ( name, " {nk}" ) ;
874
874
}
875
-
876
875
Some ( Toolchain {
877
876
name : name. into ( ) ,
878
877
path : toolchain. executable . as_ref ( ) ?. to_str ( ) ?. to_owned ( ) . into ( ) ,
879
878
language_name : LanguageName :: new ( "Python" ) ,
880
879
as_json : serde_json:: to_value ( toolchain) . ok ( ) ?,
881
- startup_script : std:: iter:: once ( ( "fish" . to_owned ( ) , "test" . to_owned ( ) ) )
882
- . collect ( ) ,
880
+ activation_script : std:: iter:: once ( (
881
+ ShellKind :: Fish ,
882
+ "echo python recognized a venv and injected a fish startup command"
883
+ . to_owned ( ) ,
884
+ ) )
885
+ . collect ( ) ,
883
886
} )
884
887
} )
885
888
. collect ( ) ;
@@ -1691,3 +1694,180 @@ mod tests {
1691
1694
} ) ;
1692
1695
}
1693
1696
}
1697
+ /*
1698
+ fn python_venv_directory(
1699
+ abs_path: Arc<Path>,
1700
+ venv_settings: VenvSettings,
1701
+ cx: &Context<Project>,
1702
+ ) -> Task<Option<PathBuf>> {
1703
+ cx.spawn(async move |this, cx| {
1704
+ if let Some((worktree, relative_path)) = this
1705
+ .update(cx, |this, cx| this.find_worktree(&abs_path, cx))
1706
+ .ok()?
1707
+ {
1708
+ let toolchain = this
1709
+ .update(cx, |this, cx| {
1710
+ this.active_toolchain(
1711
+ ProjectPath {
1712
+ worktree_id: worktree.read(cx).id(),
1713
+ path: relative_path.into(),
1714
+ },
1715
+ LanguageName::new("Python"),
1716
+ cx,
1717
+ )
1718
+ })
1719
+ .ok()?
1720
+ .await;
1721
+
1722
+ if let Some(toolchain) = toolchain {
1723
+ let toolchain_path = Path::new(toolchain.path.as_ref());
1724
+ return Some(toolchain_path.parent()?.parent()?.to_path_buf());
1725
+ }
1726
+ }
1727
+ let venv_settings = venv_settings.as_option()?;
1728
+ this.update(cx, move |this, cx| {
1729
+ if let Some(path) = this.find_venv_in_worktree(&abs_path, &venv_settings, cx) {
1730
+ return Some(path);
1731
+ }
1732
+ this.find_venv_on_filesystem(&abs_path, &venv_settings, cx)
1733
+ })
1734
+ .ok()
1735
+ .flatten()
1736
+ })
1737
+ }
1738
+
1739
+ fn find_venv_in_worktree(
1740
+ &self,
1741
+ abs_path: &Path,
1742
+ venv_settings: &terminal_settings::VenvSettingsContent,
1743
+ cx: &App,
1744
+ ) -> Option<PathBuf> {
1745
+ venv_settings
1746
+ .directories
1747
+ .iter()
1748
+ .map(|name| abs_path.join(name))
1749
+ .find(|venv_path| {
1750
+ let bin_path = venv_path.join(PYTHON_VENV_BIN_DIR);
1751
+ self.find_worktree(&bin_path, cx)
1752
+ .and_then(|(worktree, relative_path)| {
1753
+ worktree.read(cx).entry_for_path(&relative_path)
1754
+ })
1755
+ .is_some_and(|entry| entry.is_dir())
1756
+ })
1757
+ }
1758
+
1759
+ fn find_venv_on_filesystem(
1760
+ &self,
1761
+ abs_path: &Path,
1762
+ venv_settings: &terminal_settings::VenvSettingsContent,
1763
+ cx: &App,
1764
+ ) -> Option<PathBuf> {
1765
+ let (worktree, _) = self.find_worktree(abs_path, cx)?;
1766
+ let fs = worktree.read(cx).as_local()?.fs();
1767
+ venv_settings
1768
+ .directories
1769
+ .iter()
1770
+ .map(|name| abs_path.join(name))
1771
+ .find(|venv_path| {
1772
+ let bin_path = venv_path.join(PYTHON_VENV_BIN_DIR);
1773
+ // One-time synchronous check is acceptable for terminal/task initialization
1774
+ smol::block_on(fs.metadata(&bin_path))
1775
+ .ok()
1776
+ .flatten()
1777
+ .map_or(false, |meta| meta.is_dir)
1778
+ })
1779
+ }
1780
+
1781
+ fn activate_script_kind(shell: Option<&str>) -> ActivateScript {
1782
+ let shell_env = std::env::var("SHELL").ok();
1783
+ let shell_path = shell.or_else(|| shell_env.as_deref());
1784
+ let shell = std::path::Path::new(shell_path.unwrap_or(""))
1785
+ .file_name()
1786
+ .and_then(|name| name.to_str())
1787
+ .unwrap_or("");
1788
+ match shell {
1789
+ "fish" => ActivateScript::Fish,
1790
+ "tcsh" => ActivateScript::Csh,
1791
+ "nu" => ActivateScript::Nushell,
1792
+ "powershell" | "pwsh" => ActivateScript::PowerShell,
1793
+ _ => ActivateScript::Default,
1794
+ }
1795
+ }
1796
+
1797
+ fn python_activate_command(
1798
+ &self,
1799
+ venv_base_directory: &Path,
1800
+ venv_settings: &VenvSettings,
1801
+ shell: &Shell,
1802
+ cx: &mut App,
1803
+ ) -> Task<Option<String>> {
1804
+ let Some(venv_settings) = venv_settings.as_option() else {
1805
+ return Task::ready(None);
1806
+ };
1807
+ let activate_keyword = match venv_settings.activate_script {
1808
+ terminal_settings::ActivateScript::Default => match std::env::consts::OS {
1809
+ "windows" => ".",
1810
+ _ => ".",
1811
+ },
1812
+ terminal_settings::ActivateScript::Nushell => "overlay use",
1813
+ terminal_settings::ActivateScript::PowerShell => ".",
1814
+ terminal_settings::ActivateScript::Pyenv => "pyenv",
1815
+ _ => "source",
1816
+ };
1817
+ let script_kind = if venv_settings.activate_script == terminal_settings::ActivateScript::Default
1818
+ {
1819
+ match shell {
1820
+ Shell::Program(program) => Self::activate_script_kind(Some(program)),
1821
+ Shell::WithArguments {
1822
+ program,
1823
+ args: _,
1824
+ title_override: _,
1825
+ } => Self::activate_script_kind(Some(program)),
1826
+ Shell::System => Self::activate_script_kind(None),
1827
+ }
1828
+ } else {
1829
+ venv_settings.activate_script
1830
+ };
1831
+
1832
+ let activate_script_name = match script_kind {
1833
+ terminal_settings::ActivateScript::Default | terminal_settings::ActivateScript::Pyenv => {
1834
+ "activate"
1835
+ }
1836
+ terminal_settings::ActivateScript::Csh => "activate.csh",
1837
+ terminal_settings::ActivateScript::Fish => "activate.fish",
1838
+ terminal_settings::ActivateScript::Nushell => "activate.nu",
1839
+ terminal_settings::ActivateScript::PowerShell => "activate.ps1",
1840
+ };
1841
+
1842
+ let line_ending = match std::env::consts::OS {
1843
+ "windows" => "\r",
1844
+ _ => "\n",
1845
+ };
1846
+
1847
+ if venv_settings.venv_name.is_empty() {
1848
+ let path = venv_base_directory
1849
+ .join(PYTHON_VENV_BIN_DIR)
1850
+ .join(activate_script_name)
1851
+ .to_string_lossy()
1852
+ .to_string();
1853
+
1854
+ let is_valid_path = self.resolve_abs_path(path.as_ref(), cx);
1855
+ cx.background_spawn(async move {
1856
+ let quoted = shlex::try_quote(&path).ok()?;
1857
+ if is_valid_path.await.is_some_and(|meta| meta.is_file()) {
1858
+ Some(format!(
1859
+ "{} {} ; clear{}",
1860
+ activate_keyword, quoted, line_ending
1861
+ ))
1862
+ } else {
1863
+ None
1864
+ }
1865
+ })
1866
+ } else {
1867
+ Task::ready(Some(format!(
1868
+ "{activate_keyword} {activate_script_name} {name}; clear{line_ending}",
1869
+ name = venv_settings.venv_name
1870
+ )))
1871
+ }
1872
+ }
1873
+ */
0 commit comments