python: Fix flickering in the status bar (#36039)

- **util: Have maybe! use async closures instead of async blocks**
- **python: Fix flickering of virtual environment indicator in status
bar**

Closes #30723

Release Notes:

- Python: Fixed flickering of the status bar virtual environment
indicator

---------

Co-authored-by: Lukas Wirth <lukas@zed.dev>
This commit is contained in:
Piotr Osiewicz 2025-08-12 15:36:28 +02:00 committed by GitHub
parent 44953375cc
commit 360d4db87c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 66 additions and 43 deletions

View file

@ -8,6 +8,7 @@ use gpui::{
use language::{Buffer, BufferEvent, LanguageName, Toolchain};
use project::{Project, ProjectPath, WorktreeId, toolchain_store::ToolchainStoreEvent};
use ui::{Button, ButtonCommon, Clickable, FluentBuilder, LabelSize, SharedString, Tooltip};
use util::maybe;
use workspace::{StatusItemView, Workspace, item::ItemHandle};
use crate::ToolchainSelector;
@ -55,49 +56,61 @@ impl ActiveToolchain {
}
fn spawn_tracker_task(window: &mut Window, cx: &mut Context<Self>) -> Task<Option<()>> {
cx.spawn_in(window, async move |this, cx| {
let active_file = this
.read_with(cx, |this, _| {
this.active_buffer
.as_ref()
.map(|(_, buffer, _)| buffer.clone())
})
.ok()
.flatten()?;
let workspace = this.read_with(cx, |this, _| this.workspace.clone()).ok()?;
let language_name = active_file
.read_with(cx, |this, _| Some(this.language()?.name()))
.ok()
.flatten()?;
let term = workspace
.update(cx, |workspace, cx| {
let languages = workspace.project().read(cx).languages();
Project::toolchain_term(languages.clone(), language_name.clone())
})
.ok()?
.await?;
let _ = this.update(cx, |this, cx| {
this.term = term;
cx.notify();
});
let (worktree_id, path) = active_file
.update(cx, |this, cx| {
this.file().and_then(|file| {
Some((
file.worktree_id(cx),
Arc::<Path>::from(file.path().parent()?),
))
let did_set_toolchain = maybe!(async {
let active_file = this
.read_with(cx, |this, _| {
this.active_buffer
.as_ref()
.map(|(_, buffer, _)| buffer.clone())
})
.ok()
.flatten()?;
let workspace = this.read_with(cx, |this, _| this.workspace.clone()).ok()?;
let language_name = active_file
.read_with(cx, |this, _| Some(this.language()?.name()))
.ok()
.flatten()?;
let term = workspace
.update(cx, |workspace, cx| {
let languages = workspace.project().read(cx).languages();
Project::toolchain_term(languages.clone(), language_name.clone())
})
.ok()?
.await?;
let _ = this.update(cx, |this, cx| {
this.term = term;
cx.notify();
});
let (worktree_id, path) = active_file
.update(cx, |this, cx| {
this.file().and_then(|file| {
Some((
file.worktree_id(cx),
Arc::<Path>::from(file.path().parent()?),
))
})
})
.ok()
.flatten()?;
let toolchain =
Self::active_toolchain(workspace, worktree_id, path, language_name, cx).await?;
this.update(cx, |this, cx| {
this.active_toolchain = Some(toolchain);
cx.notify();
})
.ok()
.flatten()?;
let toolchain =
Self::active_toolchain(workspace, worktree_id, path, language_name, cx).await?;
let _ = this.update(cx, |this, cx| {
this.active_toolchain = Some(toolchain);
cx.notify();
});
Some(())
})
.await
.is_some();
if !did_set_toolchain {
this.update(cx, |this, cx| {
this.active_toolchain = None;
cx.notify();
})
.ok();
}
did_set_toolchain.then_some(())
})
}
@ -110,6 +123,17 @@ impl ActiveToolchain {
let editor = editor.read(cx);
if let Some((_, buffer, _)) = editor.active_excerpt(cx) {
if let Some(worktree_id) = buffer.read(cx).file().map(|file| file.worktree_id(cx)) {
if self
.active_buffer
.as_ref()
.is_some_and(|(old_worktree_id, old_buffer, _)| {
(old_worktree_id, old_buffer.entity_id())
== (&worktree_id, buffer.entity_id())
})
{
return;
}
let subscription = cx.subscribe_in(
&buffer,
window,
@ -231,7 +255,6 @@ impl StatusItemView for ActiveToolchain {
cx: &mut Context<Self>,
) {
if let Some(editor) = active_pane_item.and_then(|item| item.downcast::<Editor>()) {
self.active_toolchain.take();
self.update_lister(editor, window, cx);
}
cx.notify();

View file

@ -887,10 +887,10 @@ macro_rules! maybe {
(|| $block)()
};
(async $block:block) => {
(|| async $block)()
(async || $block)()
};
(async move $block:block) => {
(|| async move $block)()
(async move || $block)()
};
}