crates/repl/src/outputs.rs 🔗
@@ -38,7 +38,8 @@ use gpui::{AnyElement, ClipboardItem, Entity, Render, WeakEntity};
use language::Buffer;
use runtimelib::{ExecutionState, JupyterMessageContent, MimeBundle, MimeType};
use ui::{
- CommonAnimationExt, Context, IntoElement, Styled, Tooltip, Window, div, prelude::*, v_flex,
+ ButtonStyle, CommonAnimationExt, Context, IconButton, IconName, IntoElement, Styled, Tooltip,
+ Window, div, h_flex, prelude::*, v_flex,
};
mod image;
@@ -146,13 +147,13 @@ impl Output {
IconButton::new(ElementId::Name("copy-output".into()), IconName::Copy)
.style(ButtonStyle::Transparent)
.tooltip(Tooltip::text("Copy Output"))
- .on_click(cx.listener(move |_, _, window, cx| {
+ .on_click(move |_, window, cx| {
let clipboard_content = v.clipboard_content(window, cx);
if let Some(clipboard_content) = clipboard_content.as_ref() {
cx.write_to_clipboard(clipboard_content.clone());
}
- })),
+ }),
)
})
.when(v.has_buffer_content(window, cx), |el| {
@@ -164,10 +165,9 @@ impl Output {
)
.style(ButtonStyle::Transparent)
.tooltip(Tooltip::text("Open in Buffer"))
- .on_click(cx.listener({
+ .on_click({
let workspace = workspace.clone();
-
- move |_, _, window, cx| {
+ move |_, window, cx| {
let buffer_content =
v.update(cx, |item, cx| item.buffer_content(window, cx));
@@ -193,7 +193,7 @@ impl Output {
.ok();
}
}
- })),
+ }),
)
})
.into_any_element(),
@@ -237,7 +237,87 @@ impl Output {
Self::render_output_controls(content.clone(), workspace, window, cx)
}
Self::ErrorOutput(err) => {
- Self::render_output_controls(err.traceback.clone(), workspace, window, cx)
+ // Add buttons for the traceback section
+ Some(
+ h_flex()
+ .pl_1()
+ .child(
+ IconButton::new(
+ ElementId::Name("copy-full-error-traceback".into()),
+ IconName::Copy,
+ )
+ .style(ButtonStyle::Transparent)
+ .tooltip(Tooltip::text("Copy Full Error"))
+ .on_click({
+ let ename = err.ename.clone();
+ let evalue = err.evalue.clone();
+ let traceback = err.traceback.clone();
+ move |_, _window, cx| {
+ let traceback_text = traceback.read(cx).full_text();
+ let full_error =
+ format!("{}: {}\n{}", ename, evalue, traceback_text);
+ let clipboard_content =
+ ClipboardItem::new_string(full_error);
+ cx.write_to_clipboard(clipboard_content);
+ }
+ }),
+ )
+ .child(
+ IconButton::new(
+ ElementId::Name("open-full-error-in-buffer-traceback".into()),
+ IconName::FileTextOutlined,
+ )
+ .style(ButtonStyle::Transparent)
+ .tooltip(Tooltip::text("Open Full Error in Buffer"))
+ .on_click({
+ let ename = err.ename.clone();
+ let evalue = err.evalue.clone();
+ let traceback = err.traceback.clone();
+ move |_, window, cx| {
+ if let Some(workspace) = workspace.upgrade() {
+ let traceback_text = traceback.read(cx).full_text();
+ let full_error = format!(
+ "{}: {}\n{}",
+ ename, evalue, traceback_text
+ );
+ let buffer = cx.new(|cx| {
+ let mut buffer = Buffer::local(full_error, cx)
+ .with_language(
+ language::PLAIN_TEXT.clone(),
+ cx,
+ );
+ buffer.set_capability(
+ language::Capability::ReadOnly,
+ cx,
+ );
+ buffer
+ });
+ let editor = Box::new(cx.new(|cx| {
+ let multibuffer = cx.new(|cx| {
+ let mut multi_buffer =
+ MultiBuffer::singleton(buffer.clone(), cx);
+ multi_buffer
+ .set_title("Full Error".to_string(), cx);
+ multi_buffer
+ });
+ Editor::for_multibuffer(
+ multibuffer,
+ None,
+ window,
+ cx,
+ )
+ }));
+ workspace.update(cx, |workspace, cx| {
+ workspace.add_item_to_active_pane(
+ editor, None, true, window, cx,
+ );
+ });
+ }
+ }
+ }),
+ )
+ .into_any_element(),
+ )
}
Self::Message(_) => None,
Self::Table { content, .. } => {