toolchains: Use language-specific terms in UI (#20985)

Closes #ISSUE

Release Notes:

- N/A
This commit is contained in:
Piotr Osiewicz 2024-11-21 15:57:22 +01:00 committed by GitHub
parent 75c545aa1e
commit 0b373d43dc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 76 additions and 9 deletions

View file

@ -31,6 +31,8 @@ pub trait ToolchainLister: Send + Sync {
worktree_root: PathBuf, worktree_root: PathBuf,
project_env: Option<HashMap<String, String>>, project_env: Option<HashMap<String, String>>,
) -> ToolchainList; ) -> ToolchainList;
// Returns a term which we should use in UI to refer to a toolchain.
fn term(&self) -> SharedString;
} }
#[async_trait(?Send)] #[async_trait(?Send)]

View file

@ -2,8 +2,8 @@ use anyhow::ensure;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use async_trait::async_trait; use async_trait::async_trait;
use collections::HashMap; use collections::HashMap;
use gpui::AsyncAppContext;
use gpui::{AppContext, Task}; use gpui::{AppContext, Task};
use gpui::{AsyncAppContext, SharedString};
use language::language_settings::language_settings; use language::language_settings::language_settings;
use language::LanguageName; use language::LanguageName;
use language::LanguageToolchainStore; use language::LanguageToolchainStore;
@ -498,8 +498,17 @@ fn python_module_name_from_relative_path(relative_path: &str) -> String {
.to_string() .to_string()
} }
#[derive(Default)] pub(crate) struct PythonToolchainProvider {
pub(crate) struct PythonToolchainProvider {} term: SharedString,
}
impl Default for PythonToolchainProvider {
fn default() -> Self {
Self {
term: SharedString::new_static("Virtual Environment"),
}
}
}
static ENV_PRIORITY_LIST: &'static [PythonEnvironmentKind] = &[ static ENV_PRIORITY_LIST: &'static [PythonEnvironmentKind] = &[
// Prioritize non-Conda environments. // Prioritize non-Conda environments.
@ -604,6 +613,9 @@ impl ToolchainLister for PythonToolchainProvider {
groups: Default::default(), groups: Default::default(),
} }
} }
fn term(&self) -> SharedString {
self.term.clone()
}
} }
pub struct EnvironmentApi<'a> { pub struct EnvironmentApi<'a> {

View file

@ -425,6 +425,19 @@ impl<D: PickerDelegate> Picker<D> {
self.cancel(&menu::Cancel, cx); self.cancel(&menu::Cancel, cx);
} }
pub fn refresh_placeholder(&mut self, cx: &mut WindowContext<'_>) {
match &self.head {
Head::Editor(view) => {
let placeholder = self.delegate.placeholder_text(cx);
view.update(cx, |this, cx| {
this.set_placeholder_text(placeholder, cx);
cx.notify();
});
}
Head::Empty(_) => {}
}
}
pub fn refresh(&mut self, cx: &mut ViewContext<Self>) { pub fn refresh(&mut self, cx: &mut ViewContext<Self>) {
let query = self.query(cx); let query = self.query(cx);
self.update_matches(query, cx); self.update_matches(query, cx);

View file

@ -2464,6 +2464,19 @@ impl Project {
Task::ready(None) Task::ready(None)
} }
} }
pub async fn toolchain_term(
languages: Arc<LanguageRegistry>,
language_name: LanguageName,
) -> Option<SharedString> {
languages
.language_for_name(&language_name.0)
.await
.ok()?
.toolchain_lister()
.map(|lister| lister.term())
}
pub fn activate_toolchain( pub fn activate_toolchain(
&self, &self,
worktree_id: WorktreeId, worktree_id: WorktreeId,

View file

@ -4,14 +4,15 @@ use gpui::{
ViewContext, WeakModel, WeakView, ViewContext, WeakModel, WeakView,
}; };
use language::{Buffer, BufferEvent, LanguageName, Toolchain}; use language::{Buffer, BufferEvent, LanguageName, Toolchain};
use project::WorktreeId; use project::{Project, WorktreeId};
use ui::{Button, ButtonCommon, Clickable, FluentBuilder, LabelSize, Tooltip}; use ui::{Button, ButtonCommon, Clickable, FluentBuilder, LabelSize, SharedString, Tooltip};
use workspace::{item::ItemHandle, StatusItemView, Workspace}; use workspace::{item::ItemHandle, StatusItemView, Workspace};
use crate::ToolchainSelector; use crate::ToolchainSelector;
pub struct ActiveToolchain { pub struct ActiveToolchain {
active_toolchain: Option<Toolchain>, active_toolchain: Option<Toolchain>,
term: SharedString,
workspace: WeakView<Workspace>, workspace: WeakView<Workspace>,
active_buffer: Option<(WorktreeId, WeakModel<Buffer>, Subscription)>, active_buffer: Option<(WorktreeId, WeakModel<Buffer>, Subscription)>,
_update_toolchain_task: Task<Option<()>>, _update_toolchain_task: Task<Option<()>>,
@ -22,6 +23,7 @@ impl ActiveToolchain {
Self { Self {
active_toolchain: None, active_toolchain: None,
active_buffer: None, active_buffer: None,
term: SharedString::new_static("Toolchain"),
workspace: workspace.weak_handle(), workspace: workspace.weak_handle(),
_update_toolchain_task: Self::spawn_tracker_task(cx), _update_toolchain_task: Self::spawn_tracker_task(cx),
@ -44,7 +46,17 @@ impl ActiveToolchain {
.update(&mut cx, |this, _| Some(this.language()?.name())) .update(&mut cx, |this, _| Some(this.language()?.name()))
.ok() .ok()
.flatten()?; .flatten()?;
let term = workspace
.update(&mut cx, |workspace, cx| {
let languages = workspace.project().read(cx).languages();
Project::toolchain_term(languages.clone(), language_name.clone())
})
.ok()?
.await?;
let _ = this.update(&mut cx, |this, cx| {
this.term = term;
cx.notify();
});
let worktree_id = active_file let worktree_id = active_file
.update(&mut cx, |this, cx| Some(this.file()?.worktree_id(cx))) .update(&mut cx, |this, cx| Some(this.file()?.worktree_id(cx)))
.ok() .ok()
@ -133,6 +145,7 @@ impl ActiveToolchain {
impl Render for ActiveToolchain { impl Render for ActiveToolchain {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement { fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
div().when_some(self.active_toolchain.as_ref(), |el, active_toolchain| { div().when_some(self.active_toolchain.as_ref(), |el, active_toolchain| {
let term = self.term.clone();
el.child( el.child(
Button::new("change-toolchain", active_toolchain.name.clone()) Button::new("change-toolchain", active_toolchain.name.clone())
.label_size(LabelSize::Small) .label_size(LabelSize::Small)
@ -143,7 +156,7 @@ impl Render for ActiveToolchain {
}); });
} }
})) }))
.tooltip(|cx| Tooltip::text("Select Toolchain", cx)), .tooltip(move |cx| Tooltip::text(format!("Select {}", &term), cx)),
) )
}) })
} }

View file

@ -126,6 +126,7 @@ pub struct ToolchainSelectorDelegate {
workspace: WeakView<Workspace>, workspace: WeakView<Workspace>,
worktree_id: WorktreeId, worktree_id: WorktreeId,
worktree_abs_path_root: Arc<Path>, worktree_abs_path_root: Arc<Path>,
placeholder_text: Arc<str>,
_fetch_candidates_task: Task<Option<()>>, _fetch_candidates_task: Task<Option<()>>,
} }
@ -144,6 +145,17 @@ impl ToolchainSelectorDelegate {
let _fetch_candidates_task = cx.spawn({ let _fetch_candidates_task = cx.spawn({
let project = project.clone(); let project = project.clone();
move |this, mut cx| async move { move |this, mut cx| async move {
let term = project
.update(&mut cx, |this, _| {
Project::toolchain_term(this.languages().clone(), language_name.clone())
})
.ok()?
.await?;
let placeholder_text = format!("Select a {}", term.to_lowercase()).into();
let _ = this.update(&mut cx, move |this, cx| {
this.delegate.placeholder_text = placeholder_text;
this.refresh_placeholder(cx);
});
let available_toolchains = project let available_toolchains = project
.update(&mut cx, |this, cx| { .update(&mut cx, |this, cx| {
this.available_toolchains(worktree_id, language_name, cx) this.available_toolchains(worktree_id, language_name, cx)
@ -153,6 +165,7 @@ impl ToolchainSelectorDelegate {
let _ = this.update(&mut cx, move |this, cx| { let _ = this.update(&mut cx, move |this, cx| {
this.delegate.candidates = available_toolchains; this.delegate.candidates = available_toolchains;
if let Some(active_toolchain) = active_toolchain { if let Some(active_toolchain) = active_toolchain {
if let Some(position) = this if let Some(position) = this
.delegate .delegate
@ -170,7 +183,7 @@ impl ToolchainSelectorDelegate {
Some(()) Some(())
} }
}); });
let placeholder_text = "Select a toolchain…".to_string().into();
Self { Self {
toolchain_selector: language_selector, toolchain_selector: language_selector,
candidates: Default::default(), candidates: Default::default(),
@ -179,6 +192,7 @@ impl ToolchainSelectorDelegate {
workspace, workspace,
worktree_id, worktree_id,
worktree_abs_path_root, worktree_abs_path_root,
placeholder_text,
_fetch_candidates_task, _fetch_candidates_task,
} }
} }
@ -196,7 +210,7 @@ impl PickerDelegate for ToolchainSelectorDelegate {
type ListItem = ListItem; type ListItem = ListItem;
fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> { fn placeholder_text(&self, _cx: &mut WindowContext) -> Arc<str> {
"Select a toolchain...".into() self.placeholder_text.clone()
} }
fn match_count(&self) -> usize { fn match_count(&self) -> usize {