toolchains: Allow users to provide custom paths to toolchains (#37009)
- **toolchains: Add new state to toolchain selector** - **Use toolchain term for Add Toolchain button** - **Hoist out a meta function for toolchain listers** Closes #27332 Release Notes: - python: Users can now specify a custom path to their virtual environment from within the picker. --------- Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
This commit is contained in:
co-authored by
Danilo Leal
parent
59bdbf5a5d
commit
6a7b84eb87
@@ -5,19 +5,19 @@ use collections::HashMap;
|
||||
use futures::AsyncBufReadExt;
|
||||
use gpui::{App, Task};
|
||||
use gpui::{AsyncApp, SharedString};
|
||||
use language::Toolchain;
|
||||
use language::ToolchainList;
|
||||
use language::ToolchainLister;
|
||||
use language::language_settings::language_settings;
|
||||
use language::{ContextLocation, LanguageToolchainStore};
|
||||
use language::{ContextProvider, LspAdapter, LspAdapterDelegate};
|
||||
use language::{LanguageName, ManifestName, ManifestProvider, ManifestQuery};
|
||||
use language::{Toolchain, ToolchainMetadata};
|
||||
use lsp::LanguageServerBinary;
|
||||
use lsp::LanguageServerName;
|
||||
use node_runtime::{NodeRuntime, VersionStrategy};
|
||||
use pet_core::Configuration;
|
||||
use pet_core::os_environment::Environment;
|
||||
use pet_core::python_environment::PythonEnvironmentKind;
|
||||
use pet_core::python_environment::{PythonEnvironment, PythonEnvironmentKind};
|
||||
use project::Fs;
|
||||
use project::lsp_store::language_server_settings;
|
||||
use serde_json::{Value, json};
|
||||
@@ -688,17 +688,7 @@ fn python_env_kind_display(k: &PythonEnvironmentKind) -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct PythonToolchainProvider {
|
||||
term: SharedString,
|
||||
}
|
||||
|
||||
impl Default for PythonToolchainProvider {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
term: SharedString::new_static("Virtual Environment"),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub(crate) struct PythonToolchainProvider;
|
||||
|
||||
static ENV_PRIORITY_LIST: &[PythonEnvironmentKind] = &[
|
||||
// Prioritize non-Conda environments.
|
||||
@@ -744,9 +734,6 @@ async fn get_worktree_venv_declaration(worktree_root: &Path) -> Option<String> {
|
||||
|
||||
#[async_trait]
|
||||
impl ToolchainLister for PythonToolchainProvider {
|
||||
fn manifest_name(&self) -> language::ManifestName {
|
||||
ManifestName::from(SharedString::new_static("pyproject.toml"))
|
||||
}
|
||||
async fn list(
|
||||
&self,
|
||||
worktree_root: PathBuf,
|
||||
@@ -847,32 +834,7 @@ impl ToolchainLister for PythonToolchainProvider {
|
||||
|
||||
let mut toolchains: Vec<_> = toolchains
|
||||
.into_iter()
|
||||
.filter_map(|toolchain| {
|
||||
let mut name = String::from("Python");
|
||||
if let Some(version) = &toolchain.version {
|
||||
_ = write!(name, " {version}");
|
||||
}
|
||||
|
||||
let name_and_kind = match (&toolchain.name, &toolchain.kind) {
|
||||
(Some(name), Some(kind)) => {
|
||||
Some(format!("({name}; {})", python_env_kind_display(kind)))
|
||||
}
|
||||
(Some(name), None) => Some(format!("({name})")),
|
||||
(None, Some(kind)) => Some(format!("({})", python_env_kind_display(kind))),
|
||||
(None, None) => None,
|
||||
};
|
||||
|
||||
if let Some(nk) = name_and_kind {
|
||||
_ = write!(name, " {nk}");
|
||||
}
|
||||
|
||||
Some(Toolchain {
|
||||
name: name.into(),
|
||||
path: toolchain.executable.as_ref()?.to_str()?.to_owned().into(),
|
||||
language_name: LanguageName::new("Python"),
|
||||
as_json: serde_json::to_value(toolchain.clone()).ok()?,
|
||||
})
|
||||
})
|
||||
.filter_map(venv_to_toolchain)
|
||||
.collect();
|
||||
toolchains.dedup();
|
||||
ToolchainList {
|
||||
@@ -881,9 +843,34 @@ impl ToolchainLister for PythonToolchainProvider {
|
||||
groups: Default::default(),
|
||||
}
|
||||
}
|
||||
fn term(&self) -> SharedString {
|
||||
self.term.clone()
|
||||
fn meta(&self) -> ToolchainMetadata {
|
||||
ToolchainMetadata {
|
||||
term: SharedString::new_static("Virtual Environment"),
|
||||
new_toolchain_placeholder: SharedString::new_static(
|
||||
"A path to the python3 executable within a virtual environment, or path to virtual environment itself",
|
||||
),
|
||||
manifest_name: ManifestName::from(SharedString::new_static("pyproject.toml")),
|
||||
}
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
&self,
|
||||
path: PathBuf,
|
||||
env: Option<HashMap<String, String>>,
|
||||
) -> anyhow::Result<Toolchain> {
|
||||
let env = env.unwrap_or_default();
|
||||
let environment = EnvironmentApi::from_env(&env);
|
||||
let locators = pet::locators::create_locators(
|
||||
Arc::new(pet_conda::Conda::from(&environment)),
|
||||
Arc::new(pet_poetry::Poetry::from(&environment)),
|
||||
&environment,
|
||||
);
|
||||
let toolchain = pet::resolve::resolve_environment(&path, &locators, &environment)
|
||||
.context("Could not find a virtual environment in provided path")?;
|
||||
let venv = toolchain.resolved.unwrap_or(toolchain.discovered);
|
||||
venv_to_toolchain(venv).context("Could not convert a venv into a toolchain")
|
||||
}
|
||||
|
||||
async fn activation_script(
|
||||
&self,
|
||||
toolchain: &Toolchain,
|
||||
@@ -956,6 +943,31 @@ impl ToolchainLister for PythonToolchainProvider {
|
||||
}
|
||||
}
|
||||
|
||||
fn venv_to_toolchain(venv: PythonEnvironment) -> Option<Toolchain> {
|
||||
let mut name = String::from("Python");
|
||||
if let Some(ref version) = venv.version {
|
||||
_ = write!(name, " {version}");
|
||||
}
|
||||
|
||||
let name_and_kind = match (&venv.name, &venv.kind) {
|
||||
(Some(name), Some(kind)) => Some(format!("({name}; {})", python_env_kind_display(kind))),
|
||||
(Some(name), None) => Some(format!("({name})")),
|
||||
(None, Some(kind)) => Some(format!("({})", python_env_kind_display(kind))),
|
||||
(None, None) => None,
|
||||
};
|
||||
|
||||
if let Some(nk) = name_and_kind {
|
||||
_ = write!(name, " {nk}");
|
||||
}
|
||||
|
||||
Some(Toolchain {
|
||||
name: name.into(),
|
||||
path: venv.executable.as_ref()?.to_str()?.to_owned().into(),
|
||||
language_name: LanguageName::new("Python"),
|
||||
as_json: serde_json::to_value(venv).ok()?,
|
||||
})
|
||||
}
|
||||
|
||||
pub struct EnvironmentApi<'a> {
|
||||
global_search_locations: Arc<Mutex<Vec<PathBuf>>>,
|
||||
project_env: &'a HashMap<String, String>,
|
||||
|
||||
Reference in New Issue
Block a user