
Initial runtimes UI panel. The main draw here is that all message subscription occurs with two background tasks that run for the life of the kernel. Follow on to #12062 * [x] Disable previous cmd-enter behavior only if runtimes are enabled in settings * [x] Only show the runtimes panel if it is enabled via settings * [x] Create clean UI for the current sessions ### Running Kernels UI <img width="205" alt="image" src="https://github.com/zed-industries/zed/assets/836375/814ae79b-0807-4e23-bc95-77ce64f9d732"> * [x] List running kernels * [x] Implement shutdown * [x] Delete connection file on `drop` of `RunningKernel` * [x] Implement interrupt #### Project-specific Kernel Settings - [x] Modify JupyterSettings to include a `kernel_selections` field (`HashMap<String, String>`). - [x] Implement saving and loading of kernel selections to/from `.zed/settings.json` (by default, rather than global settings?) #### Kernel Selection Persistence - [x] Save the selected kernel for each language when the user makes a choice. - [x] Load these selections when the RuntimePanel is initialized. #### Use Selected Kernels - [x] Modify kernel launch to use the selected kernel for the detected language. - [x] Fallback to default behavior if no selection is made. ### Empty states - [x] Create helpful UI for when the user has 0 kernels they can launch and/or 0 kernels running <img width="694" alt="image" src="https://github.com/zed-industries/zed/assets/836375/d6a75939-e4e4-40fb-80fe-014da041cc3c"> ## Future work ### Kernel Discovery - Improve the kernel discovery process to handle various installation methods (system, virtualenv, poetry, etc.). - Create a way to refresh the available kernels on demand ### Documentation: - Update documentation to explain how users can configure kernels for their projects. - Provide examples of .zed/settings.json configurations for kernel selection. ### Kernel Selection UI - Implement a new section in the RuntimePanel to display available kernels. - Group on the language name from the kernel specification - Create a dropdown for each language group to select the default kernel. Release Notes: - N/A --------- Co-authored-by: Kirill <kirill@zed.dev>
149 lines
4 KiB
Rust
149 lines
4 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use schemars::JsonSchema;
|
|
use serde::{Deserialize, Serialize};
|
|
use settings::{Settings, SettingsSources};
|
|
use ui::Pixels;
|
|
|
|
#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum JupyterDockPosition {
|
|
Left,
|
|
#[default]
|
|
Right,
|
|
Bottom,
|
|
}
|
|
|
|
#[derive(Debug, Default)]
|
|
pub struct JupyterSettings {
|
|
pub enabled: bool,
|
|
pub dock: JupyterDockPosition,
|
|
pub default_width: Pixels,
|
|
pub kernel_selections: HashMap<String, String>,
|
|
}
|
|
|
|
#[derive(Clone, Serialize, Deserialize, JsonSchema, Debug)]
|
|
pub struct JupyterSettingsContent {
|
|
/// Whether the Jupyter feature is enabled.
|
|
///
|
|
/// Default: `false`
|
|
enabled: Option<bool>,
|
|
/// Where to dock the Jupyter panel.
|
|
///
|
|
/// Default: `right`
|
|
dock: Option<JupyterDockPosition>,
|
|
/// Default width in pixels when the jupyter panel is docked to the left or right.
|
|
///
|
|
/// Default: 640
|
|
pub default_width: Option<f32>,
|
|
/// Default kernels to select for each language.
|
|
///
|
|
/// Default: `{}`
|
|
pub kernel_selections: Option<HashMap<String, String>>,
|
|
}
|
|
|
|
impl JupyterSettingsContent {
|
|
pub fn set_dock(&mut self, dock: JupyterDockPosition) {
|
|
self.dock = Some(dock);
|
|
}
|
|
}
|
|
|
|
impl Default for JupyterSettingsContent {
|
|
fn default() -> Self {
|
|
JupyterSettingsContent {
|
|
enabled: Some(false),
|
|
dock: Some(JupyterDockPosition::Right),
|
|
default_width: Some(640.0),
|
|
kernel_selections: Some(HashMap::new()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Settings for JupyterSettings {
|
|
const KEY: Option<&'static str> = Some("jupyter");
|
|
|
|
type FileContent = JupyterSettingsContent;
|
|
|
|
fn load(
|
|
sources: SettingsSources<Self::FileContent>,
|
|
_cx: &mut gpui::AppContext,
|
|
) -> anyhow::Result<Self>
|
|
where
|
|
Self: Sized,
|
|
{
|
|
let mut settings = JupyterSettings::default();
|
|
|
|
for value in sources.defaults_and_customizations() {
|
|
if let Some(enabled) = value.enabled {
|
|
settings.enabled = enabled;
|
|
}
|
|
if let Some(dock) = value.dock {
|
|
settings.dock = dock;
|
|
}
|
|
|
|
if let Some(default_width) = value.default_width {
|
|
settings.default_width = Pixels::from(default_width);
|
|
}
|
|
|
|
if let Some(source) = &value.kernel_selections {
|
|
for (k, v) in source {
|
|
settings.kernel_selections.insert(k.clone(), v.clone());
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(settings)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use gpui::{AppContext, UpdateGlobal};
|
|
use settings::SettingsStore;
|
|
|
|
use super::*;
|
|
|
|
#[gpui::test]
|
|
fn test_deserialize_jupyter_settings(cx: &mut AppContext) {
|
|
let store = settings::SettingsStore::test(cx);
|
|
cx.set_global(store);
|
|
|
|
JupyterSettings::register(cx);
|
|
|
|
assert_eq!(JupyterSettings::get_global(cx).enabled, false);
|
|
assert_eq!(
|
|
JupyterSettings::get_global(cx).dock,
|
|
JupyterDockPosition::Right
|
|
);
|
|
assert_eq!(
|
|
JupyterSettings::get_global(cx).default_width,
|
|
Pixels::from(640.0)
|
|
);
|
|
|
|
// Setting a custom setting through user settings
|
|
SettingsStore::update_global(cx, |store, cx| {
|
|
store
|
|
.set_user_settings(
|
|
r#"{
|
|
"jupyter": {
|
|
"enabled": true,
|
|
"dock": "left",
|
|
"default_width": 800.0
|
|
}
|
|
}"#,
|
|
cx,
|
|
)
|
|
.unwrap();
|
|
});
|
|
|
|
assert_eq!(JupyterSettings::get_global(cx).enabled, true);
|
|
assert_eq!(
|
|
JupyterSettings::get_global(cx).dock,
|
|
JupyterDockPosition::Left
|
|
);
|
|
assert_eq!(
|
|
JupyterSettings::get_global(cx).default_width,
|
|
Pixels::from(800.0)
|
|
);
|
|
}
|
|
}
|