repl_store.rs

  1use std::sync::Arc;
  2
  3use anyhow::Result;
  4use client::telemetry::Telemetry;
  5use collections::HashMap;
  6use command_palette_hooks::CommandPaletteFilter;
  7use gpui::{
  8    prelude::*, AppContext, EntityId, Global, Model, ModelContext, Subscription, Task, View,
  9};
 10use project::Fs;
 11use settings::{Settings, SettingsStore};
 12
 13use crate::kernels::kernel_specifications;
 14use crate::{JupyterSettings, KernelSpecification, Session};
 15
 16struct GlobalReplStore(Model<ReplStore>);
 17
 18impl Global for GlobalReplStore {}
 19
 20pub struct ReplStore {
 21    fs: Arc<dyn Fs>,
 22    enabled: bool,
 23    sessions: HashMap<EntityId, View<Session>>,
 24    kernel_specifications: Vec<KernelSpecification>,
 25    telemetry: Arc<Telemetry>,
 26    _subscriptions: Vec<Subscription>,
 27}
 28
 29impl ReplStore {
 30    const NAMESPACE: &'static str = "repl";
 31
 32    pub(crate) fn init(fs: Arc<dyn Fs>, telemetry: Arc<Telemetry>, cx: &mut AppContext) {
 33        let store = cx.new_model(move |cx| Self::new(fs, telemetry, cx));
 34
 35        store
 36            .update(cx, |store, cx| store.refresh_kernelspecs(cx))
 37            .detach_and_log_err(cx);
 38
 39        cx.set_global(GlobalReplStore(store))
 40    }
 41
 42    pub fn global(cx: &AppContext) -> Model<Self> {
 43        cx.global::<GlobalReplStore>().0.clone()
 44    }
 45
 46    pub fn new(fs: Arc<dyn Fs>, telemetry: Arc<Telemetry>, cx: &mut ModelContext<Self>) -> Self {
 47        let subscriptions = vec![cx.observe_global::<SettingsStore>(move |this, cx| {
 48            this.set_enabled(JupyterSettings::enabled(cx), cx);
 49        })];
 50
 51        let this = Self {
 52            fs,
 53            telemetry,
 54            enabled: JupyterSettings::enabled(cx),
 55            sessions: HashMap::default(),
 56            kernel_specifications: Vec::new(),
 57            _subscriptions: subscriptions,
 58        };
 59        this.on_enabled_changed(cx);
 60        this
 61    }
 62
 63    pub fn fs(&self) -> &Arc<dyn Fs> {
 64        &self.fs
 65    }
 66
 67    pub fn telemetry(&self) -> &Arc<Telemetry> {
 68        &self.telemetry
 69    }
 70
 71    pub fn is_enabled(&self) -> bool {
 72        self.enabled
 73    }
 74
 75    pub fn kernel_specifications(&self) -> impl Iterator<Item = &KernelSpecification> {
 76        self.kernel_specifications.iter()
 77    }
 78
 79    pub fn sessions(&self) -> impl Iterator<Item = &View<Session>> {
 80        self.sessions.values()
 81    }
 82
 83    fn set_enabled(&mut self, enabled: bool, cx: &mut ModelContext<Self>) {
 84        if self.enabled == enabled {
 85            return;
 86        }
 87
 88        self.enabled = enabled;
 89        self.on_enabled_changed(cx);
 90    }
 91
 92    fn on_enabled_changed(&self, cx: &mut ModelContext<Self>) {
 93        if !self.enabled {
 94            CommandPaletteFilter::update_global(cx, |filter, _cx| {
 95                filter.hide_namespace(Self::NAMESPACE);
 96            });
 97
 98            return;
 99        }
100
101        CommandPaletteFilter::update_global(cx, |filter, _cx| {
102            filter.show_namespace(Self::NAMESPACE);
103        });
104
105        cx.notify();
106    }
107
108    pub fn refresh_kernelspecs(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
109        let kernel_specifications = kernel_specifications(self.fs.clone());
110        cx.spawn(|this, mut cx| async move {
111            let kernel_specifications = kernel_specifications.await?;
112
113            this.update(&mut cx, |this, cx| {
114                this.kernel_specifications = kernel_specifications;
115                cx.notify();
116            })
117        })
118    }
119
120    pub fn kernelspec(&self, language_name: &str, cx: &AppContext) -> Option<KernelSpecification> {
121        let settings = JupyterSettings::get_global(cx);
122        let selected_kernel = settings.kernel_selections.get(language_name);
123
124        let found_by_name = self
125            .kernel_specifications
126            .iter()
127            .find(|runtime_specification| {
128                if let Some(selected) = selected_kernel {
129                    // Top priority is the selected kernel
130                    return runtime_specification.name.to_lowercase() == selected.to_lowercase();
131                }
132                false
133            })
134            .cloned();
135
136        if let Some(found_by_name) = found_by_name {
137            return Some(found_by_name);
138        }
139
140        self.kernel_specifications
141            .iter()
142            .find(|runtime_specification| {
143                runtime_specification.kernelspec.language.to_lowercase()
144                    == language_name.to_lowercase()
145            })
146            .cloned()
147    }
148
149    pub fn get_session(&self, entity_id: EntityId) -> Option<&View<Session>> {
150        self.sessions.get(&entity_id)
151    }
152
153    pub fn insert_session(&mut self, entity_id: EntityId, session: View<Session>) {
154        self.sessions.insert(entity_id, session);
155    }
156
157    pub fn remove_session(&mut self, entity_id: EntityId) {
158        self.sessions.remove(&entity_id);
159    }
160}