mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-15 06:40:17 +00:00
repl: Refactor editor registration (#14819)
Cleans up action registration with the editors and also fixes a major bug where only one workspace's panel was getting session info (due to my not understanding that `cx.observe_new_views` is for the whole app). Release Notes: - N/A Co-authored-by: Conrad <conrad@zed.dev>
This commit is contained in:
parent
4c7f1032a4
commit
5467e18a5b
1 changed files with 96 additions and 106 deletions
|
@ -6,7 +6,6 @@ use crate::{
|
|||
use anyhow::{Context as _, Result};
|
||||
use collections::HashMap;
|
||||
use editor::{Anchor, Editor, RangeToAnchorExt};
|
||||
use futures::StreamExt as _;
|
||||
use gpui::{
|
||||
actions, prelude::*, AppContext, AsyncWindowContext, EntityId, EventEmitter, FocusHandle,
|
||||
FocusOutEvent, FocusableView, Subscription, Task, View, WeakView,
|
||||
|
@ -46,6 +45,102 @@ pub fn init(cx: &mut AppContext) {
|
|||
},
|
||||
)
|
||||
.detach();
|
||||
|
||||
cx.observe_new_views(move |editor: &mut Editor, cx: &mut ViewContext<Editor>| {
|
||||
// Only allow editors that support vim mode and are singleton buffers
|
||||
if !editor.use_modal_editing() || !editor.buffer().read(cx).is_singleton() {
|
||||
return;
|
||||
}
|
||||
|
||||
editor
|
||||
.register_action(cx.listener(
|
||||
move |editor: &mut Editor, _: &Run, cx: &mut ViewContext<Editor>| {
|
||||
if !JupyterSettings::enabled(cx) {
|
||||
return;
|
||||
}
|
||||
let Some(workspace) = editor.workspace() else {
|
||||
return;
|
||||
};
|
||||
let Some(panel) = workspace.read(cx).panel::<RuntimePanel>(cx) else {
|
||||
return;
|
||||
};
|
||||
let weak_editor = cx.view().downgrade();
|
||||
panel.update(cx, |_, cx| {
|
||||
cx.defer(|panel, cx| {
|
||||
panel.run(weak_editor, cx).log_err();
|
||||
});
|
||||
})
|
||||
},
|
||||
))
|
||||
.detach();
|
||||
|
||||
editor
|
||||
.register_action(cx.listener(
|
||||
move |editor: &mut Editor, _: &ClearOutputs, cx: &mut ViewContext<Editor>| {
|
||||
if !JupyterSettings::enabled(cx) {
|
||||
return;
|
||||
}
|
||||
let Some(workspace) = editor.workspace() else {
|
||||
return;
|
||||
};
|
||||
let Some(panel) = workspace.read(cx).panel::<RuntimePanel>(cx) else {
|
||||
return;
|
||||
};
|
||||
let weak_editor = cx.view().downgrade();
|
||||
panel.update(cx, |_, cx| {
|
||||
cx.defer(|panel, cx| {
|
||||
panel.clear_outputs(weak_editor, cx);
|
||||
});
|
||||
})
|
||||
},
|
||||
))
|
||||
.detach();
|
||||
|
||||
editor
|
||||
.register_action(cx.listener(
|
||||
move |editor: &mut Editor, _: &Interrupt, cx: &mut ViewContext<Editor>| {
|
||||
if !JupyterSettings::enabled(cx) {
|
||||
return;
|
||||
}
|
||||
let Some(workspace) = editor.workspace() else {
|
||||
return;
|
||||
};
|
||||
let Some(panel) = workspace.read(cx).panel::<RuntimePanel>(cx) else {
|
||||
return;
|
||||
};
|
||||
let weak_editor = cx.view().downgrade();
|
||||
panel.update(cx, |_, cx| {
|
||||
cx.defer(|panel, cx| {
|
||||
panel.interrupt(weak_editor, cx);
|
||||
});
|
||||
})
|
||||
},
|
||||
))
|
||||
.detach();
|
||||
|
||||
editor
|
||||
.register_action(cx.listener(
|
||||
move |editor: &mut Editor, _: &Shutdown, cx: &mut ViewContext<Editor>| {
|
||||
if !JupyterSettings::enabled(cx) {
|
||||
return;
|
||||
}
|
||||
let Some(workspace) = editor.workspace() else {
|
||||
return;
|
||||
};
|
||||
let Some(panel) = workspace.read(cx).panel::<RuntimePanel>(cx) else {
|
||||
return;
|
||||
};
|
||||
let weak_editor = cx.view().downgrade();
|
||||
panel.update(cx, |_, cx| {
|
||||
cx.defer(|panel, cx| {
|
||||
panel.shutdown(weak_editor, cx);
|
||||
});
|
||||
})
|
||||
},
|
||||
))
|
||||
.detach();
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
pub struct RuntimePanel {
|
||||
|
@ -56,14 +151,6 @@ pub struct RuntimePanel {
|
|||
sessions: HashMap<EntityId, View<Session>>,
|
||||
kernel_specifications: Vec<KernelSpecification>,
|
||||
_subscriptions: Vec<Subscription>,
|
||||
_editor_events_task: Task<()>,
|
||||
}
|
||||
|
||||
pub enum ReplEvent {
|
||||
Run(WeakView<Editor>),
|
||||
ClearOutputs(WeakView<Editor>),
|
||||
Interrupt(WeakView<Editor>),
|
||||
Shutdown(WeakView<Editor>),
|
||||
}
|
||||
|
||||
impl RuntimePanel {
|
||||
|
@ -78,110 +165,14 @@ impl RuntimePanel {
|
|||
|
||||
let fs = workspace.app_state().fs.clone();
|
||||
|
||||
// Make a channel that we receive editor events on (for repl::Run, repl::ClearOutputs)
|
||||
// This allows us to inject actions on the editor from the repl panel without requiring the editor to
|
||||
// depend on the `repl` crate.
|
||||
let (repl_editor_event_tx, mut repl_editor_event_rx) =
|
||||
futures::channel::mpsc::unbounded::<ReplEvent>();
|
||||
|
||||
let subscriptions = vec![
|
||||
cx.on_focus_in(&focus_handle, Self::focus_in),
|
||||
cx.on_focus_out(&focus_handle, Self::focus_out),
|
||||
cx.observe_global::<SettingsStore>(move |this, cx| {
|
||||
this.set_enabled(JupyterSettings::enabled(cx), cx);
|
||||
}),
|
||||
cx.observe_new_views(
|
||||
move |editor: &mut Editor, cx: &mut ViewContext<Editor>| {
|
||||
let editor_view = cx.view().downgrade();
|
||||
let run_event_tx = repl_editor_event_tx.clone();
|
||||
let clear_event_tx = repl_editor_event_tx.clone();
|
||||
editor
|
||||
.register_action(move |_: &Run, cx: &mut WindowContext| {
|
||||
if !JupyterSettings::enabled(cx) {
|
||||
return;
|
||||
}
|
||||
run_event_tx
|
||||
.unbounded_send(ReplEvent::Run(editor_view.clone()))
|
||||
.ok();
|
||||
})
|
||||
.detach();
|
||||
|
||||
let editor_view = cx.view().downgrade();
|
||||
editor
|
||||
.register_action(
|
||||
move |_: &ClearOutputs, cx: &mut WindowContext| {
|
||||
if !JupyterSettings::enabled(cx) {
|
||||
return;
|
||||
}
|
||||
clear_event_tx
|
||||
.unbounded_send(ReplEvent::ClearOutputs(
|
||||
editor_view.clone(),
|
||||
))
|
||||
.ok();
|
||||
},
|
||||
)
|
||||
.detach();
|
||||
|
||||
editor
|
||||
.register_action({
|
||||
let editor = cx.view().downgrade();
|
||||
let repl_editor_event_tx = repl_editor_event_tx.clone();
|
||||
|
||||
move |_: &Interrupt, cx: &mut WindowContext| {
|
||||
if !JupyterSettings::enabled(cx) {
|
||||
return;
|
||||
}
|
||||
repl_editor_event_tx
|
||||
.unbounded_send(ReplEvent::Interrupt(
|
||||
editor.clone(),
|
||||
))
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
editor
|
||||
.register_action({
|
||||
let editor = cx.view().downgrade();
|
||||
let repl_editor_event_tx = repl_editor_event_tx.clone();
|
||||
|
||||
move |_: &Shutdown, cx: &mut WindowContext| {
|
||||
if !JupyterSettings::enabled(cx) {
|
||||
return;
|
||||
}
|
||||
repl_editor_event_tx
|
||||
.unbounded_send(ReplEvent::Shutdown(editor.clone()))
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
},
|
||||
),
|
||||
];
|
||||
|
||||
// Listen for events from the editor on the `repl_editor_event_rx` channel
|
||||
let _editor_events_task = cx.spawn(
|
||||
move |this: WeakView<RuntimePanel>, mut cx: AsyncWindowContext| async move {
|
||||
while let Some(event) = repl_editor_event_rx.next().await {
|
||||
this.update(&mut cx, |runtime_panel, cx| match event {
|
||||
ReplEvent::Run(editor) => {
|
||||
runtime_panel.run(editor, cx).log_err();
|
||||
}
|
||||
ReplEvent::ClearOutputs(editor) => {
|
||||
runtime_panel.clear_outputs(editor, cx);
|
||||
}
|
||||
ReplEvent::Interrupt(editor) => {
|
||||
runtime_panel.interrupt(editor, cx);
|
||||
}
|
||||
ReplEvent::Shutdown(editor) => {
|
||||
runtime_panel.shutdown(editor, cx);
|
||||
}
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
let runtime_panel = Self {
|
||||
fs: fs.clone(),
|
||||
width: None,
|
||||
|
@ -190,7 +181,6 @@ impl RuntimePanel {
|
|||
sessions: Default::default(),
|
||||
_subscriptions: subscriptions,
|
||||
enabled: JupyterSettings::enabled(cx),
|
||||
_editor_events_task,
|
||||
};
|
||||
|
||||
runtime_panel
|
||||
|
|
Loading…
Reference in a new issue