Refactor repl context menu (#14587)
This commit is contained in:
parent
cb6fc11abc
commit
8028e7f1b6
2 changed files with 112 additions and 88 deletions
|
@ -1,8 +1,9 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use gpui::{percentage, Animation, AnimationExt, AnyElement, Transformation};
|
||||
use gpui::{percentage, Animation, AnimationExt, AnyElement, Transformation, View};
|
||||
use repl::{
|
||||
ExecutionState, JupyterSettings, Kernel, KernelSpecification, RuntimePanel, SessionSupport,
|
||||
ExecutionState, JupyterSettings, Kernel, KernelSpecification, KernelStatus, RuntimePanel,
|
||||
Session, SessionSupport,
|
||||
};
|
||||
use ui::{
|
||||
prelude::*, ButtonLike, ContextMenu, IconWithIndicator, Indicator, IntoElement, PopoverMenu,
|
||||
|
@ -16,6 +17,22 @@ use crate::QuickActionBar;
|
|||
|
||||
const ZED_REPL_DOCUMENTATION: &str = "https://zed.dev/docs/repl";
|
||||
|
||||
struct ReplMenuState {
|
||||
tooltip: SharedString,
|
||||
icon: IconName,
|
||||
icon_color: Color,
|
||||
icon_is_animating: bool,
|
||||
popover_disabled: bool,
|
||||
indicator: Option<Indicator>,
|
||||
|
||||
status: KernelStatus,
|
||||
kernel_name: SharedString,
|
||||
kernel_language: SharedString,
|
||||
// TODO: Persist rotation state so the
|
||||
// icon doesn't reset on every state change
|
||||
// current_delta: Duration,
|
||||
}
|
||||
|
||||
impl QuickActionBar {
|
||||
pub fn render_repl_menu(&self, cx: &mut ViewContext<Self>) -> Option<AnyElement> {
|
||||
if !JupyterSettings::enabled(cx) {
|
||||
|
@ -50,7 +67,7 @@ impl QuickActionBar {
|
|||
});
|
||||
|
||||
let session = match session {
|
||||
SessionSupport::ActiveSession(session) => session.read(cx),
|
||||
SessionSupport::ActiveSession(session) => session,
|
||||
SessionSupport::Inactive(spec) => {
|
||||
let spec = *spec;
|
||||
return self.render_repl_launch_menu(spec, cx);
|
||||
|
@ -61,101 +78,25 @@ impl QuickActionBar {
|
|||
SessionSupport::Unsupported => return None,
|
||||
};
|
||||
|
||||
let kernel_name: SharedString = session.kernel_specification.name.clone().into();
|
||||
let kernel_language: SharedString = session
|
||||
.kernel_specification
|
||||
.kernelspec
|
||||
.language
|
||||
.clone()
|
||||
.into();
|
||||
|
||||
struct ReplMenuState {
|
||||
tooltip: SharedString,
|
||||
icon: IconName,
|
||||
icon_color: Color,
|
||||
icon_is_animating: bool,
|
||||
popover_disabled: bool,
|
||||
indicator: Option<Indicator>,
|
||||
// TODO: Persist rotation state so the
|
||||
// icon doesn't reset on every state change
|
||||
// current_delta: Duration,
|
||||
}
|
||||
|
||||
impl Default for ReplMenuState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
tooltip: "Nothing running".into(),
|
||||
icon: IconName::ReplNeutral,
|
||||
icon_color: Color::Default,
|
||||
icon_is_animating: false,
|
||||
popover_disabled: false,
|
||||
indicator: None,
|
||||
// current_delta: Duration::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let menu_state = match &session.kernel {
|
||||
Kernel::RunningKernel(kernel) => match &kernel.execution_state {
|
||||
ExecutionState::Idle => ReplMenuState {
|
||||
tooltip: format!("Run code on {} ({})", kernel_name, kernel_language).into(),
|
||||
indicator: Some(Indicator::dot().color(Color::Success)),
|
||||
..Default::default()
|
||||
},
|
||||
ExecutionState::Busy => ReplMenuState {
|
||||
tooltip: format!("Interrupt {} ({})", kernel_name, kernel_language).into(),
|
||||
icon_is_animating: true,
|
||||
popover_disabled: false,
|
||||
indicator: None,
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
Kernel::StartingKernel(_) => ReplMenuState {
|
||||
tooltip: format!("{} is starting", kernel_name).into(),
|
||||
icon_is_animating: true,
|
||||
popover_disabled: true,
|
||||
icon_color: Color::Muted,
|
||||
indicator: Some(Indicator::dot().color(Color::Muted)),
|
||||
..Default::default()
|
||||
},
|
||||
Kernel::ErroredLaunch(e) => ReplMenuState {
|
||||
tooltip: format!("Error with kernel {}: {}", kernel_name, e).into(),
|
||||
popover_disabled: false,
|
||||
indicator: Some(Indicator::dot().color(Color::Error)),
|
||||
..Default::default()
|
||||
},
|
||||
Kernel::ShuttingDown => ReplMenuState {
|
||||
tooltip: format!("{} is shutting down", kernel_name).into(),
|
||||
popover_disabled: true,
|
||||
icon_color: Color::Muted,
|
||||
indicator: Some(Indicator::dot().color(Color::Muted)),
|
||||
..Default::default()
|
||||
},
|
||||
Kernel::Shutdown => ReplMenuState::default(),
|
||||
};
|
||||
let menu_state = session_state(session.clone(), cx);
|
||||
|
||||
let id = "repl-menu".to_string();
|
||||
|
||||
let element_id = |suffix| ElementId::Name(format!("{}-{}", id, suffix).into());
|
||||
|
||||
let kernel = &session.kernel;
|
||||
let status_borrow = &kernel.status();
|
||||
let status = status_borrow.clone();
|
||||
let panel_clone = repl_panel.clone();
|
||||
let editor_clone = editor.downgrade();
|
||||
let dropdown_menu = PopoverMenu::new(element_id("menu"))
|
||||
.menu(move |cx| {
|
||||
let kernel_name = kernel_name.clone();
|
||||
let kernel_language = kernel_language.clone();
|
||||
let status = status.clone();
|
||||
let panel_clone = panel_clone.clone();
|
||||
let editor_clone = editor_clone.clone();
|
||||
ContextMenu::build(cx, move |menu, _cx| {
|
||||
let session = session.clone();
|
||||
ContextMenu::build(cx, move |menu, cx| {
|
||||
let menu_state = session_state(session, cx);
|
||||
let status = menu_state.status;
|
||||
let editor_clone = editor_clone.clone();
|
||||
let panel_clone = panel_clone.clone();
|
||||
let kernel_name = kernel_name.clone();
|
||||
let kernel_language = kernel_language.clone();
|
||||
let status = status.clone();
|
||||
|
||||
menu.when_else(
|
||||
status.is_connected(),
|
||||
|running| {
|
||||
|
@ -166,8 +107,8 @@ impl QuickActionBar {
|
|||
.child(
|
||||
Label::new(format!(
|
||||
"kernel: {} ({})",
|
||||
kernel_name.clone(),
|
||||
kernel_language.clone()
|
||||
menu_state.kernel_name.clone(),
|
||||
menu_state.kernel_language.clone()
|
||||
))
|
||||
.size(LabelSize::Small)
|
||||
.color(Color::Muted),
|
||||
|
@ -371,3 +312,86 @@ impl QuickActionBar {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn session_state(session: View<Session>, cx: &WindowContext) -> ReplMenuState {
|
||||
let session = session.read(cx);
|
||||
|
||||
let kernel_name: SharedString = session.kernel_specification.name.clone().into();
|
||||
let kernel_language: SharedString = session
|
||||
.kernel_specification
|
||||
.kernelspec
|
||||
.language
|
||||
.clone()
|
||||
.into();
|
||||
|
||||
let fill_fields = || {
|
||||
ReplMenuState {
|
||||
tooltip: "Nothing running".into(),
|
||||
icon: IconName::ReplNeutral,
|
||||
icon_color: Color::Default,
|
||||
icon_is_animating: false,
|
||||
popover_disabled: false,
|
||||
indicator: None,
|
||||
kernel_name: kernel_name.clone(),
|
||||
kernel_language: kernel_language.clone(),
|
||||
// todo!(): Technically not shutdown, but indeterminate
|
||||
status: KernelStatus::Shutdown,
|
||||
// current_delta: Duration::default(),
|
||||
}
|
||||
};
|
||||
|
||||
let menu_state = match &session.kernel {
|
||||
Kernel::RunningKernel(kernel) => match &kernel.execution_state {
|
||||
ExecutionState::Idle => ReplMenuState {
|
||||
tooltip: format!("Run code on {} ({})", kernel_name, kernel_language).into(),
|
||||
indicator: Some(Indicator::dot().color(Color::Success)),
|
||||
status: session.kernel.status(),
|
||||
..fill_fields()
|
||||
},
|
||||
ExecutionState::Busy => ReplMenuState {
|
||||
tooltip: format!("Interrupt {} ({})", kernel_name, kernel_language).into(),
|
||||
icon_is_animating: true,
|
||||
popover_disabled: false,
|
||||
indicator: None,
|
||||
status: session.kernel.status(),
|
||||
..fill_fields()
|
||||
},
|
||||
},
|
||||
Kernel::StartingKernel(_) => ReplMenuState {
|
||||
tooltip: format!("{} is starting", kernel_name).into(),
|
||||
icon_is_animating: true,
|
||||
popover_disabled: true,
|
||||
icon_color: Color::Muted,
|
||||
indicator: Some(Indicator::dot().color(Color::Muted)),
|
||||
status: session.kernel.status(),
|
||||
..fill_fields()
|
||||
},
|
||||
Kernel::ErroredLaunch(e) => ReplMenuState {
|
||||
tooltip: format!("Error with kernel {}: {}", kernel_name, e).into(),
|
||||
popover_disabled: false,
|
||||
indicator: Some(Indicator::dot().color(Color::Error)),
|
||||
status: session.kernel.status(),
|
||||
..fill_fields()
|
||||
},
|
||||
Kernel::ShuttingDown => ReplMenuState {
|
||||
tooltip: format!("{} is shutting down", kernel_name).into(),
|
||||
popover_disabled: true,
|
||||
icon_color: Color::Muted,
|
||||
indicator: Some(Indicator::dot().color(Color::Muted)),
|
||||
status: session.kernel.status(),
|
||||
..fill_fields()
|
||||
},
|
||||
Kernel::Shutdown => ReplMenuState {
|
||||
tooltip: "Nothing running".into(),
|
||||
icon: IconName::ReplNeutral,
|
||||
icon_color: Color::Default,
|
||||
icon_is_animating: false,
|
||||
popover_disabled: false,
|
||||
indicator: None,
|
||||
status: KernelStatus::Shutdown,
|
||||
..fill_fields()
|
||||
},
|
||||
};
|
||||
|
||||
menu_state
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ mod session;
|
|||
mod stdio;
|
||||
|
||||
pub use jupyter_settings::JupyterSettings;
|
||||
pub use kernels::{Kernel, KernelSpecification};
|
||||
pub use kernels::{Kernel, KernelSpecification, KernelStatus};
|
||||
pub use runtime_panel::{ClearOutputs, Interrupt, Run, Shutdown};
|
||||
pub use runtime_panel::{RuntimePanel, SessionSupport};
|
||||
pub use runtimelib::ExecutionState;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue