jupyter_settings.rs

  1use std::collections::HashMap;
  2
  3use editor::EditorSettings;
  4use gpui::AppContext;
  5use schemars::JsonSchema;
  6use serde::{Deserialize, Serialize};
  7use settings::{Settings, SettingsSources};
  8use ui::Pixels;
  9
 10#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
 11#[serde(rename_all = "snake_case")]
 12pub enum JupyterDockPosition {
 13    Left,
 14    #[default]
 15    Right,
 16    Bottom,
 17}
 18
 19#[derive(Debug, Default)]
 20pub struct JupyterSettings {
 21    pub dock: JupyterDockPosition,
 22    pub default_width: Pixels,
 23    pub kernel_selections: HashMap<String, String>,
 24}
 25
 26impl JupyterSettings {
 27    pub fn enabled(cx: &AppContext) -> bool {
 28        // In order to avoid a circular dependency between `editor` and `repl` crates,
 29        // we put the `enable` flag on its settings.
 30        // This allows the editor to set up context for key bindings/actions.
 31        EditorSettings::get_global(cx).jupyter.enabled
 32    }
 33}
 34
 35#[derive(Clone, Serialize, Deserialize, JsonSchema, Debug)]
 36pub struct JupyterSettingsContent {
 37    /// Where to dock the Jupyter panel.
 38    ///
 39    /// Default: `right`
 40    dock: Option<JupyterDockPosition>,
 41    /// Default width in pixels when the jupyter panel is docked to the left or right.
 42    ///
 43    /// Default: 640
 44    pub default_width: Option<f32>,
 45    /// Default kernels to select for each language.
 46    ///
 47    /// Default: `{}`
 48    pub kernel_selections: Option<HashMap<String, String>>,
 49}
 50
 51impl JupyterSettingsContent {
 52    pub fn set_dock(&mut self, dock: JupyterDockPosition) {
 53        self.dock = Some(dock);
 54    }
 55}
 56
 57impl Default for JupyterSettingsContent {
 58    fn default() -> Self {
 59        JupyterSettingsContent {
 60            dock: Some(JupyterDockPosition::Right),
 61            default_width: Some(640.0),
 62            kernel_selections: Some(HashMap::new()),
 63        }
 64    }
 65}
 66
 67impl Settings for JupyterSettings {
 68    const KEY: Option<&'static str> = Some("jupyter");
 69
 70    type FileContent = JupyterSettingsContent;
 71
 72    fn load(
 73        sources: SettingsSources<Self::FileContent>,
 74        _cx: &mut gpui::AppContext,
 75    ) -> anyhow::Result<Self>
 76    where
 77        Self: Sized,
 78    {
 79        let mut settings = JupyterSettings::default();
 80
 81        for value in sources.defaults_and_customizations() {
 82            if let Some(dock) = value.dock {
 83                settings.dock = dock;
 84            }
 85
 86            if let Some(default_width) = value.default_width {
 87                settings.default_width = Pixels::from(default_width);
 88            }
 89
 90            if let Some(source) = &value.kernel_selections {
 91                for (k, v) in source {
 92                    settings.kernel_selections.insert(k.clone(), v.clone());
 93                }
 94            }
 95        }
 96
 97        Ok(settings)
 98    }
 99}
100
101#[cfg(test)]
102mod tests {
103    use gpui::{AppContext, UpdateGlobal};
104    use settings::SettingsStore;
105
106    use super::*;
107
108    #[gpui::test]
109    fn test_deserialize_jupyter_settings(cx: &mut AppContext) {
110        let store = settings::SettingsStore::test(cx);
111        cx.set_global(store);
112
113        EditorSettings::register(cx);
114        JupyterSettings::register(cx);
115
116        assert_eq!(JupyterSettings::enabled(cx), false);
117        assert_eq!(
118            JupyterSettings::get_global(cx).dock,
119            JupyterDockPosition::Right
120        );
121        assert_eq!(
122            JupyterSettings::get_global(cx).default_width,
123            Pixels::from(640.0)
124        );
125
126        // Setting a custom setting through user settings
127        SettingsStore::update_global(cx, |store, cx| {
128            store
129                .set_user_settings(
130                    r#"{
131                        "jupyter": {
132                            "enabled": true,
133                            "dock": "left",
134                            "default_width": 800.0
135                        }
136                    }"#,
137                    cx,
138                )
139                .unwrap();
140        });
141
142        assert_eq!(JupyterSettings::enabled(cx), true);
143        assert_eq!(
144            JupyterSettings::get_global(cx).dock,
145            JupyterDockPosition::Left
146        );
147        assert_eq!(
148            JupyterSettings::get_global(cx).default_width,
149            Pixels::from(800.0)
150        );
151    }
152}