Slowly disconnect venv handling from project/terminals.rs
This commit is contained in:
parent
b756853407
commit
dc0e81b13b
4 changed files with 117 additions and 138 deletions
|
@ -123,13 +123,86 @@ impl Project {
|
|||
cx.spawn(async move |project, cx| {
|
||||
let python_venv_directory = if let Some(path) = path {
|
||||
project
|
||||
.update(cx, |this, cx| this.python_venv_directory(path, venv, cx))?
|
||||
.update(cx, |this, cx| {
|
||||
this.python_venv_directory(path, venv.clone(), cx)
|
||||
})?
|
||||
.await
|
||||
.zip(Some(venv))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
project.update(cx, |project, cx| {
|
||||
project.create_terminal_with_venv(kind, python_venv_directory, cx)
|
||||
// todo lw: move all this out of here?
|
||||
let startup_script = move |shell: &_| {
|
||||
let Some((python_venv_directory, venv)) = &python_venv_directory else {
|
||||
return None;
|
||||
};
|
||||
// todo: If this returns `None` we may don't have a venv, but we may still have a python toolchiain
|
||||
// we should modify the PATH here still
|
||||
let venv_settings = venv.as_option()?;
|
||||
let script_kind = if venv_settings.activate_script
|
||||
== terminal_settings::ActivateScript::Default
|
||||
{
|
||||
match shell {
|
||||
Shell::Program(program) => Self::activate_script_kind(Some(program)),
|
||||
Shell::WithArguments {
|
||||
program,
|
||||
args: _,
|
||||
title_override: _,
|
||||
} => Self::activate_script_kind(Some(program)),
|
||||
Shell::System => Self::activate_script_kind(None),
|
||||
}
|
||||
} else {
|
||||
venv_settings.activate_script
|
||||
};
|
||||
|
||||
let activate_script_name = match script_kind {
|
||||
terminal_settings::ActivateScript::Default
|
||||
| terminal_settings::ActivateScript::Pyenv => "activate",
|
||||
terminal_settings::ActivateScript::Csh => "activate.csh",
|
||||
terminal_settings::ActivateScript::Fish => "activate.fish",
|
||||
terminal_settings::ActivateScript::Nushell => "activate.nu",
|
||||
terminal_settings::ActivateScript::PowerShell => "activate.ps1",
|
||||
};
|
||||
|
||||
let activate_keyword = match venv_settings.activate_script {
|
||||
terminal_settings::ActivateScript::Default => match std::env::consts::OS {
|
||||
"windows" => ".",
|
||||
_ => ".",
|
||||
},
|
||||
terminal_settings::ActivateScript::Nushell => "overlay use",
|
||||
terminal_settings::ActivateScript::PowerShell => ".",
|
||||
terminal_settings::ActivateScript::Pyenv => "pyenv",
|
||||
_ => "source",
|
||||
};
|
||||
|
||||
let line_ending = match std::env::consts::OS {
|
||||
"windows" => "\r",
|
||||
_ => "\n",
|
||||
};
|
||||
|
||||
if venv_settings.venv_name.is_empty() {
|
||||
let path = python_venv_directory
|
||||
.join(match std::env::consts::OS {
|
||||
"windows" => "Scripts",
|
||||
_ => "bin",
|
||||
})
|
||||
.join(activate_script_name)
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
let quoted = shlex::try_quote(&path).ok()?;
|
||||
Some(format!(
|
||||
"{} {} ; clear{}",
|
||||
activate_keyword, quoted, line_ending
|
||||
))
|
||||
} else {
|
||||
Some(format!(
|
||||
"{activate_keyword} {activate_script_name} {name}; clear{line_ending}",
|
||||
name = venv_settings.venv_name
|
||||
))
|
||||
}
|
||||
};
|
||||
project.create_terminal_with_startup(kind, startup_script, cx)
|
||||
})?
|
||||
})
|
||||
}
|
||||
|
@ -199,10 +272,30 @@ impl Project {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn create_terminal_with_venv(
|
||||
pub fn clone_terminal(
|
||||
&mut self,
|
||||
terminal: &Entity<Terminal>,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Result<Entity<Terminal>> {
|
||||
let terminal = terminal.read(cx);
|
||||
let working_directory = terminal
|
||||
.working_directory()
|
||||
.or_else(|| Some(self.active_project_directory(cx)?.to_path_buf()));
|
||||
let startup_script = terminal.startup_script.clone();
|
||||
self.create_terminal_with_startup(
|
||||
TerminalKind::Shell(working_directory),
|
||||
|_| {
|
||||
// The shell shouldn't change here
|
||||
startup_script
|
||||
},
|
||||
cx,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn create_terminal_with_startup(
|
||||
&mut self,
|
||||
kind: TerminalKind,
|
||||
python_venv_directory: Option<PathBuf>,
|
||||
startup_script: impl FnOnce(&Shell) -> Option<String> + 'static,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Result<Entity<Terminal>> {
|
||||
let this = &mut *self;
|
||||
|
@ -353,17 +446,10 @@ impl Project {
|
|||
}
|
||||
};
|
||||
|
||||
let python_venv_activate_command = if let Some(python_venv_directory) =
|
||||
&python_venv_directory
|
||||
{
|
||||
this.python_activate_command(python_venv_directory, &settings.detect_venv, &shell, cx)
|
||||
} else {
|
||||
Task::ready(None)
|
||||
};
|
||||
|
||||
let startup_script = startup_script(&shell);
|
||||
TerminalBuilder::new(
|
||||
local_path.map(|path| path.to_path_buf()),
|
||||
python_venv_directory,
|
||||
startup_script,
|
||||
spawn_task,
|
||||
shell,
|
||||
env,
|
||||
|
@ -396,12 +482,6 @@ impl Project {
|
|||
})
|
||||
.detach();
|
||||
|
||||
this.activate_python_virtual_environment(
|
||||
python_venv_activate_command,
|
||||
&terminal_handle,
|
||||
cx,
|
||||
);
|
||||
|
||||
terminal_handle
|
||||
})
|
||||
}
|
||||
|
@ -514,104 +594,6 @@ impl Project {
|
|||
}
|
||||
}
|
||||
|
||||
fn python_activate_command(
|
||||
&self,
|
||||
venv_base_directory: &Path,
|
||||
venv_settings: &VenvSettings,
|
||||
shell: &Shell,
|
||||
cx: &mut App,
|
||||
) -> Task<Option<String>> {
|
||||
let Some(venv_settings) = venv_settings.as_option() else {
|
||||
return Task::ready(None);
|
||||
};
|
||||
let activate_keyword = match venv_settings.activate_script {
|
||||
terminal_settings::ActivateScript::Default => match std::env::consts::OS {
|
||||
"windows" => ".",
|
||||
_ => ".",
|
||||
},
|
||||
terminal_settings::ActivateScript::Nushell => "overlay use",
|
||||
terminal_settings::ActivateScript::PowerShell => ".",
|
||||
terminal_settings::ActivateScript::Pyenv => "pyenv",
|
||||
_ => "source",
|
||||
};
|
||||
let script_kind =
|
||||
if venv_settings.activate_script == terminal_settings::ActivateScript::Default {
|
||||
match shell {
|
||||
Shell::Program(program) => Self::activate_script_kind(Some(program)),
|
||||
Shell::WithArguments {
|
||||
program,
|
||||
args: _,
|
||||
title_override: _,
|
||||
} => Self::activate_script_kind(Some(program)),
|
||||
Shell::System => Self::activate_script_kind(None),
|
||||
}
|
||||
} else {
|
||||
venv_settings.activate_script
|
||||
};
|
||||
|
||||
let activate_script_name = match script_kind {
|
||||
terminal_settings::ActivateScript::Default
|
||||
| terminal_settings::ActivateScript::Pyenv => "activate",
|
||||
terminal_settings::ActivateScript::Csh => "activate.csh",
|
||||
terminal_settings::ActivateScript::Fish => "activate.fish",
|
||||
terminal_settings::ActivateScript::Nushell => "activate.nu",
|
||||
terminal_settings::ActivateScript::PowerShell => "activate.ps1",
|
||||
};
|
||||
|
||||
let line_ending = match std::env::consts::OS {
|
||||
"windows" => "\r",
|
||||
_ => "\n",
|
||||
};
|
||||
|
||||
if venv_settings.venv_name.is_empty() {
|
||||
let path = venv_base_directory
|
||||
.join(match std::env::consts::OS {
|
||||
"windows" => "Scripts",
|
||||
_ => "bin",
|
||||
})
|
||||
.join(activate_script_name)
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
|
||||
let is_valid_path = self.resolve_abs_path(path.as_ref(), cx);
|
||||
cx.background_spawn(async move {
|
||||
let quoted = shlex::try_quote(&path).ok()?;
|
||||
if is_valid_path.await.is_some_and(|meta| meta.is_file()) {
|
||||
Some(format!(
|
||||
"{} {} ; clear{}",
|
||||
activate_keyword, quoted, line_ending
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
} else {
|
||||
Task::ready(Some(format!(
|
||||
"{activate_keyword} {activate_script_name} {name}; clear{line_ending}",
|
||||
name = venv_settings.venv_name
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
fn activate_python_virtual_environment(
|
||||
&self,
|
||||
command: Task<Option<String>>,
|
||||
terminal_handle: &Entity<Terminal>,
|
||||
cx: &mut App,
|
||||
) {
|
||||
terminal_handle.update(cx, |_, cx| {
|
||||
cx.spawn(async move |this, cx| {
|
||||
if let Some(command) = command.await {
|
||||
this.update(cx, |this, _| {
|
||||
this.input(command.into_bytes());
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.detach()
|
||||
});
|
||||
}
|
||||
|
||||
pub fn local_terminal_handles(&self) -> &Vec<WeakEntity<terminal::Terminal>> {
|
||||
&self.terminals.local_handles
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue