repl_menu.rs

  1use gpui::AnyElement;
  2use repl::{
  3    ExecutionState, JupyterSettings, Kernel, KernelSpecification, RuntimePanel, Session,
  4    SessionSupport,
  5};
  6use ui::{prelude::*, ButtonLike, IconWithIndicator, IntoElement, Tooltip};
  7
  8use crate::QuickActionBar;
  9
 10const ZED_REPL_DOCUMENTATION: &str = "https://zed.dev/docs/repl";
 11
 12impl QuickActionBar {
 13    pub fn render_repl_menu(&self, cx: &mut ViewContext<Self>) -> Option<AnyElement> {
 14        if !JupyterSettings::enabled(cx) {
 15            return None;
 16        }
 17
 18        let workspace = self.workspace.upgrade()?.read(cx);
 19
 20        let (editor, repl_panel) = if let (Some(editor), Some(repl_panel)) =
 21            (self.active_editor(), workspace.panel::<RuntimePanel>(cx))
 22        {
 23            (editor, repl_panel)
 24        } else {
 25            return None;
 26        };
 27
 28        let session = repl_panel.update(cx, |repl_panel, cx| {
 29            repl_panel.session(editor.downgrade(), cx)
 30        });
 31
 32        let session = match session {
 33            SessionSupport::ActiveSession(session) => session.read(cx),
 34            SessionSupport::Inactive(spec) => {
 35                return self.render_repl_launch_menu(spec, cx);
 36            }
 37            SessionSupport::RequiresSetup(language) => {
 38                return self.render_repl_setup(&language, cx);
 39            }
 40            SessionSupport::Unsupported => return None,
 41        };
 42
 43        let kernel_name: SharedString = session.kernel_specification.name.clone().into();
 44        let kernel_language: SharedString = session
 45            .kernel_specification
 46            .kernelspec
 47            .language
 48            .clone()
 49            .into();
 50
 51        let tooltip = |session: &Session| match &session.kernel {
 52            Kernel::RunningKernel(kernel) => match &kernel.execution_state {
 53                ExecutionState::Idle => {
 54                    format!("Run code on {} ({})", kernel_name, kernel_language)
 55                }
 56                ExecutionState::Busy => format!("Interrupt {} ({})", kernel_name, kernel_language),
 57            },
 58            Kernel::StartingKernel(_) => format!("{} is starting", kernel_name),
 59            Kernel::ErroredLaunch(e) => format!("Error with kernel {}: {}", kernel_name, e),
 60            Kernel::ShuttingDown => format!("{} is shutting down", kernel_name),
 61            Kernel::Shutdown => "Nothing running".to_string(),
 62        };
 63
 64        let tooltip_text: SharedString = SharedString::from(tooltip(&session).clone());
 65
 66        let button = ButtonLike::new("toggle_repl_icon")
 67            .child(
 68                IconWithIndicator::new(Icon::new(IconName::Play), Some(session.kernel.dot()))
 69                    .indicator_border_color(Some(cx.theme().colors().border)),
 70            )
 71            .size(ButtonSize::Compact)
 72            .style(ButtonStyle::Subtle)
 73            .tooltip(move |cx| Tooltip::text(tooltip_text.clone(), cx))
 74            .on_click(|_, cx| cx.dispatch_action(Box::new(repl::Run {})))
 75            .on_click(|_, cx| cx.dispatch_action(Box::new(repl::Run {})))
 76            .into_any_element();
 77
 78        Some(button)
 79    }
 80
 81    pub fn render_repl_launch_menu(
 82        &self,
 83        kernel_specification: KernelSpecification,
 84        _cx: &mut ViewContext<Self>,
 85    ) -> Option<AnyElement> {
 86        let tooltip: SharedString =
 87            SharedString::from(format!("Start REPL for {}", kernel_specification.name));
 88
 89        Some(
 90            IconButton::new("toggle_repl_icon", IconName::Play)
 91                .size(ButtonSize::Compact)
 92                .icon_color(Color::Muted)
 93                .style(ButtonStyle::Subtle)
 94                .tooltip(move |cx| Tooltip::text(tooltip.clone(), cx))
 95                .on_click(|_, cx| cx.dispatch_action(Box::new(repl::Run {})))
 96                .into_any_element(),
 97        )
 98    }
 99
100    pub fn render_repl_setup(
101        &self,
102        language: &str,
103        _cx: &mut ViewContext<Self>,
104    ) -> Option<AnyElement> {
105        let tooltip: SharedString = SharedString::from(format!("Setup Zed REPL for {}", language));
106        Some(
107            IconButton::new("toggle_repl_icon", IconName::Play)
108                .size(ButtonSize::Compact)
109                .icon_color(Color::Muted)
110                .style(ButtonStyle::Subtle)
111                .tooltip(move |cx| Tooltip::text(tooltip.clone(), cx))
112                .on_click(|_, cx| cx.open_url(ZED_REPL_DOCUMENTATION))
113                .into_any_element(),
114        )
115    }
116}