From 1a8005f24a4b09770aec82d67dcadcdf334f0633 Mon Sep 17 00:00:00 2001 From: Bennet Bo Fenner Date: Thu, 5 Mar 2026 11:07:52 +0100 Subject: [PATCH] editor: Respect `read_only` in `newline_below` (#50804) Turns out `Editor::newline_below` was not respecting the `read_only` flag because it uses buffer.edit. `Editor::newline` and `Editor::newline_above` behaved correctly because they used `editor.edit` which ignores edits if `read_only` is true. Added an early return if the editor is read only, also added it to newline/newline_above for clarity. Release Notes: - Fixed an issue where newlines could be inserted into read-only editors --- crates/editor/src/editor.rs | 12 ++++++++++ crates/editor/src/editor_tests.rs | 40 +++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 3b18c9a447d8fb4569bbf331f1ba8e4602a555b9..94c7bb06eb98f56e05ff96bd3b64d96d2397730b 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -5088,6 +5088,10 @@ impl Editor { } pub fn newline(&mut self, _: &Newline, window: &mut Window, cx: &mut Context) { + if self.read_only(cx) { + return; + } + self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx); self.transact(window, cx, |this, window, cx| { let (edits_with_flags, selection_info): (Vec<_>, Vec<_>) = { @@ -5309,6 +5313,10 @@ impl Editor { } pub fn newline_above(&mut self, _: &NewlineAbove, window: &mut Window, cx: &mut Context) { + if self.read_only(cx) { + return; + } + self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx); let buffer = self.buffer.read(cx); @@ -5376,6 +5384,10 @@ impl Editor { } pub fn newline_below(&mut self, _: &NewlineBelow, window: &mut Window, cx: &mut Context) { + if self.read_only(cx) { + return; + } + self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx); let mut buffer_edits: HashMap, Vec)> = HashMap::default(); diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 199cb0d3785a048f6390070d67546394bd89ff68..e3d5e698153e39fd4de04893b50a804dc2105b99 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -3382,6 +3382,46 @@ async fn test_newline_below(cx: &mut TestAppContext) { "}); } +#[gpui::test] +fn test_newline_respects_read_only(cx: &mut TestAppContext) { + init_test(cx, |_| {}); + + let editor = cx.add_window(|window, cx| { + let buffer = MultiBuffer::build_simple("aaaa\nbbbb\n", cx); + build_editor(buffer, window, cx) + }); + + _ = editor.update(cx, |editor, window, cx| { + editor.set_read_only(true); + editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| { + s.select_display_ranges([ + DisplayPoint::new(DisplayRow(0), 2)..DisplayPoint::new(DisplayRow(0), 2) + ]) + }); + + editor.newline(&Newline, window, cx); + assert_eq!( + editor.text(cx), + "aaaa\nbbbb\n", + "newline should not modify a read-only editor" + ); + + editor.newline_above(&NewlineAbove, window, cx); + assert_eq!( + editor.text(cx), + "aaaa\nbbbb\n", + "newline_above should not modify a read-only editor" + ); + + editor.newline_below(&NewlineBelow, window, cx); + assert_eq!( + editor.text(cx), + "aaaa\nbbbb\n", + "newline_below should not modify a read-only editor" + ); + }); +} + #[gpui::test] fn test_newline_below_multibuffer(cx: &mut TestAppContext) { init_test(cx, |_| {});