repl: Make output buffer be readonly, never dirty (#17121)

Kyle Kelley created

Change summary

crates/editor/src/items.rs          |  8 +++++++-
crates/language/src/buffer.rs       | 13 +++++++------
crates/repl/src/outputs.rs          | 16 ++++++++++++++--
crates/repl/src/outputs/markdown.rs |  5 ++++-
crates/repl/src/outputs/plain.rs    |  6 +++++-
5 files changed, 37 insertions(+), 11 deletions(-)

Detailed changes

crates/editor/src/items.rs 🔗

@@ -844,7 +844,13 @@ impl Item for Editor {
                         .unwrap_or_default(),
                 )
                 .map(|path| path.to_string_lossy().to_string())
-                .unwrap_or_else(|| "untitled".to_string())
+                .unwrap_or_else(|| {
+                    if multibuffer.is_singleton() {
+                        multibuffer.title(cx).to_string()
+                    } else {
+                        "untitled".to_string()
+                    }
+                })
         });
 
         let settings = ThemeSettings::get_global(cx);

crates/language/src/buffer.rs 🔗

@@ -1591,12 +1591,13 @@ impl Buffer {
 
     /// Checks if the buffer has unsaved changes.
     pub fn is_dirty(&self) -> bool {
-        self.has_conflict
-            || self.has_unsaved_edits()
-            || self
-                .file
-                .as_ref()
-                .map_or(false, |file| file.is_deleted() || !file.is_created())
+        self.capability != Capability::ReadOnly
+            && (self.has_conflict
+                || self.has_unsaved_edits()
+                || self
+                    .file
+                    .as_ref()
+                    .map_or(false, |file| file.is_deleted() || !file.is_created()))
     }
 
     /// Checks if the buffer and its file have both changed since the buffer

crates/repl/src/outputs.rs 🔗

@@ -35,7 +35,7 @@
 
 use std::time::Duration;
 
-use editor::Editor;
+use editor::{Editor, MultiBuffer};
 use gpui::{
     percentage, Animation, AnimationExt, AnyElement, ClipboardItem, Model, Render, Transformation,
     View, WeakView,
@@ -176,7 +176,18 @@ impl Output {
                                 if let Some(buffer_content) = buffer_content.as_ref() {
                                     let buffer = buffer_content.clone();
                                     let editor = Box::new(cx.new_view(|cx| {
-                                        Editor::for_buffer(buffer.clone(), None, cx)
+                                        let multibuffer = cx.new_model(|cx| {
+                                            let mut multi_buffer =
+                                                MultiBuffer::singleton(buffer.clone(), cx);
+
+                                            multi_buffer.set_title("REPL Output".to_string(), cx);
+                                            multi_buffer
+                                        });
+
+                                        let editor =
+                                            Editor::for_multibuffer(multibuffer, None, false, cx);
+
+                                        editor
                                     }));
                                     workspace
                                         .update(cx, |workspace, cx| {
@@ -195,6 +206,7 @@ impl Output {
 
     fn render(
         &self,
+
         workspace: WeakView<Workspace>,
         cx: &mut ViewContext<ExecutionView>,
     ) -> impl IntoElement {

crates/repl/src/outputs/markdown.rs 🔗

@@ -58,7 +58,10 @@ impl OutputContent for MarkdownView {
     fn buffer_content(&mut self, cx: &mut WindowContext) -> Option<Model<Buffer>> {
         let buffer = cx.new_model(|cx| {
             // todo!(): Bring in the language registry so we can set the language to markdown
-            Buffer::local(self.raw_text.clone(), cx).with_language(language::PLAIN_TEXT.clone(), cx)
+            let mut buffer = Buffer::local(self.raw_text.clone(), cx)
+                .with_language(language::PLAIN_TEXT.clone(), cx);
+            buffer.set_capability(language::Capability::ReadOnly, cx);
+            buffer
         });
         Some(buffer)
     }

crates/repl/src/outputs/plain.rs 🔗

@@ -328,8 +328,12 @@ impl OutputContent for TerminalOutput {
         }
 
         let buffer = cx.new_model(|cx| {
-            Buffer::local(self.full_text(), cx).with_language(language::PLAIN_TEXT.clone(), cx)
+            let mut buffer =
+                Buffer::local(self.full_text(), cx).with_language(language::PLAIN_TEXT.clone(), cx);
+            buffer.set_capability(language::Capability::ReadOnly, cx);
+            buffer
         });
+
         self.full_buffer = Some(buffer.clone());
         Some(buffer)
     }