repl: Add clear output(s) command (#49631)

Closes #15947

This adds `repl:ClearCurrentOutput` and `repl:ClearOutputs` commands. No
keybindings are set for this. Just an action people can bind.

Release Notes:

- Added ability to clear outputs by action
This commit is contained in:
Kyle Kelley authored and GitHub committed 2026-02-20 08:56:29 +01:00
1 parent 19404e43df
commit a7df04c375
4 files changed
+81 -2

No files matched your search

+1 -1
View File
@@ -20,7 +20,7 @@ pub use crate::jupyter_settings::JupyterSettings;
pub use crate::kernels::{Kernel, KernelSpecification, KernelStatus, PythonEnvKernelSpecification};
pub use crate::repl_editor::*;
pub use crate::repl_sessions_ui::{
ClearOutputs, Interrupt, ReplSessionsPage, Restart, Run, Sessions, Shutdown,
ClearCurrentOutput, ClearOutputs, Interrupt, ReplSessionsPage, Restart, Run, Sessions, Shutdown,
};
pub use crate::repl_settings::ReplSettings;
pub use crate::repl_store::ReplStore;
+33 -1
View File
@@ -14,7 +14,8 @@ use crate::kernels::PythonEnvKernelSpecification;
use crate::repl_store::ReplStore;
use crate::session::SessionEvent;
use crate::{
ClearOutputs, Interrupt, JupyterSettings, KernelSpecification, Restart, Session, Shutdown,
ClearCurrentOutput, ClearOutputs, Interrupt, JupyterSettings, KernelSpecification, Restart,
Session, Shutdown,
};
pub fn assign_kernelspec(
@@ -349,6 +350,24 @@ pub fn clear_outputs(editor: WeakEntity<Editor>, cx: &mut App) {
});
}
pub fn clear_current_output(editor: WeakEntity<Editor>, cx: &mut App) {
let Some(editor_entity) = editor.upgrade() else {
return;
};
let store = ReplStore::global(cx);
let entity_id = editor.entity_id();
let Some(session) = store.read(cx).get_session(entity_id).cloned() else {
return;
};
let position = editor_entity.read(cx).selections.newest_anchor().head();
session.update(cx, |session, cx| {
session.clear_output_at_position(position, cx);
});
}
pub fn interrupt(editor: WeakEntity<Editor>, cx: &mut App) {
let store = ReplStore::global(cx);
let entity_id = editor.entity_id();
@@ -410,6 +429,19 @@ pub fn setup_editor_session_actions(editor: &mut Editor, editor_handle: WeakEnti
})
.detach();
editor
.register_action({
let editor_handle = editor_handle.clone();
move |_: &ClearCurrentOutput, _, cx| {
if !JupyterSettings::enabled(cx) {
return;
}
crate::clear_current_output(editor_handle.clone(), cx);
}
})
.detach();
editor
.register_action({
let editor_handle = editor_handle.clone();
+2
View File
@@ -21,6 +21,8 @@ actions!(
RunInPlace,
/// Clears all outputs in the REPL.
ClearOutputs,
/// Clears the output of the cell at the current cursor position.
ClearCurrentOutput,
/// Opens the REPL sessions panel.
Sessions,
/// Interrupts the currently running kernel.
+45
View File
@@ -514,6 +514,51 @@ impl Session {
self.result_inlays.clear();
}
pub fn clear_output_at_position(&mut self, position: Anchor, cx: &mut Context<Self>) {
let Some(editor) = self.editor.upgrade() else {
return;
};
let (block_id, code_range, msg_id) = {
let snapshot = editor.read(cx).buffer().read(cx).read(cx);
let pos_range = position..position;
let block_to_remove = self
.blocks
.iter()
.find(|(_, block)| block.code_range.includes(&pos_range, &snapshot));
let Some((msg_id, block)) = block_to_remove else {
return;
};
(block.block_id, block.code_range.clone(), msg_id.clone())
};
let inlay_to_remove = self.result_inlays.get(&msg_id).map(|(id, _, _)| *id);
self.blocks.remove(&msg_id);
if inlay_to_remove.is_some() {
self.result_inlays.remove(&msg_id);
}
self.editor
.update(cx, |editor, cx| {
let mut block_ids = HashSet::default();
block_ids.insert(block_id);
editor.remove_blocks(block_ids, None, cx);
if let Some(inlay_id) = inlay_to_remove {
editor.splice_inlays(&[inlay_id], vec![], cx);
}
editor.remove_gutter_highlights::<ReplExecutedRange>(vec![code_range], cx);
})
.ok();
cx.notify();
}
pub fn execute(
&mut self,
code: String,