documents: one undo history; a block's own never runs
CI / platforms (windows-latest) (push) Failing after 8s
CI / site (push) Successful in 22s
CI / crate (push) Failing after 11m33s
CI / platforms (ubuntu-24.04) (push) Canceled after 0s

Undo or redo in an open block writes it back as one step and steps the
document, so redo survives mode switches and further undos.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-10-12 04:39:09 -04:00
1 parent a3d9f089a3
commit 639521e109
4 files changed
+35 -39

No files matched your search

+1 -8
View File
@@ -1,6 +1,6 @@
use std::ops::Range;
use gpui::{App, AppContext as _, Context, Focusable as _, Window};
use gpui::{AppContext as _, Context, Focusable as _, Window};
use super::{DocumentEvent, MarkdownDocument, Open};
use crate::{
@@ -31,13 +31,6 @@ impl MarkdownDocument {
}
}
/// The open block has no step left that way.
pub(super) fn at_edge_of_history(&self, redo: bool, cx: &App) -> bool {
self.open
.as_ref()
.is_some_and(|open| !open.input.read(cx).can_step(redo))
}
/// Undo or redo in the document's one history.
pub(super) fn history(&mut self, redo: bool, window: &mut Window, cx: &mut Context<Self>) {
self.commit(cx);
+29 -14
View File
@@ -1,6 +1,6 @@
use gpui::{Entity, Modifiers, TestAppContext, VisualTestContext};
use super::{MarkdownDocument, MarkdownMode, TEXT, open, opened, press, text};
use super::{MarkdownDocument, MarkdownMode, TEXT, open, press, text};
/// Focus on `document`'s own handle, as an owner gives it.
fn focus(document: &Entity<MarkdownDocument>, cx: &mut VisualTestContext) {
@@ -62,7 +62,7 @@ fn undo_in_an_untouched_block_steps_the_document(cx: &mut TestAppContext) {
}
#[gpui::test]
fn undo_in_a_typed_block_stays_in_the_block(cx: &mut TestAppContext) {
fn undo_takes_a_typed_block_back_as_one_step(cx: &mut TestAppContext) {
let (document, cx) = open("Seed", MarkdownMode::Source, cx);
document.update(cx, |document, cx| document.set_text(TEXT, cx));
mode(&document, MarkdownMode::Visual, cx);
@@ -70,34 +70,49 @@ fn undo_in_a_typed_block_stays_in_the_block(cx: &mut TestAppContext) {
cx.simulate_input(" x");
cx.simulate_keystrokes("secondary-z");
cx.run_until_parked();
assert_eq!(
text(&document, cx),
TEXT,
"the typing went, not the edit before"
);
assert_eq!(opened(&document, cx), "Blend toward white.", "still open");
assert_eq!(text(&document, cx), TEXT, "the edit before stays");
}
#[gpui::test]
fn redo_after_undo_stays_in_the_block(cx: &mut TestAppContext) {
fn redo_survives_a_switch_to_source(cx: &mut TestAppContext) {
let (document, cx) = open("", MarkdownMode::Visual, cx);
focus(&document, cx);
cx.simulate_input("Hi");
cx.simulate_keystrokes("secondary-z");
cx.run_until_parked();
assert_eq!(text(&document, cx), "");
mode(&document, MarkdownMode::Source, cx);
cx.simulate_keystrokes("secondary-shift-z");
assert_eq!(text(&document, cx), "Hi", "the block's own redo");
assert_eq!(opened(&document, cx), "Hi", "the block stays open");
assert_eq!(text(&document, cx), "Hi");
}
#[gpui::test]
fn redo_after_undo_in_a_written_block_stays_in_it(cx: &mut TestAppContext) {
fn redo_survives_preview_and_back(cx: &mut TestAppContext) {
let (document, cx) = open("Seed", MarkdownMode::Visual, cx);
press(0, Modifiers::none(), cx);
cx.simulate_input("!");
cx.simulate_keystrokes("secondary-z secondary-shift-z");
cx.simulate_keystrokes("secondary-z");
cx.run_until_parked();
assert_eq!(text(&document, cx), "Seed");
mode(&document, MarkdownMode::Preview, cx);
mode(&document, MarkdownMode::Visual, cx);
cx.simulate_keystrokes("secondary-shift-z");
cx.run_until_parked();
assert_eq!(text(&document, cx), "Seed!");
assert_eq!(opened(&document, cx), "Seed!", "the block stays open");
}
#[gpui::test]
fn redo_survives_a_second_undo(cx: &mut TestAppContext) {
let (document, cx) = open("", MarkdownMode::Visual, cx);
focus(&document, cx);
cx.simulate_input("Hi");
cx.simulate_keystrokes("secondary-z");
cx.run_until_parked();
cx.simulate_keystrokes("secondary-z");
cx.run_until_parked();
cx.simulate_keystrokes("secondary-shift-z");
cx.run_until_parked();
assert_eq!(text(&document, cx), "Hi");
}
#[gpui::test]
+5 -9
View File
@@ -164,18 +164,14 @@ impl Render for MarkdownDocument {
.on_action(cx.listener(|document, _: &Redo, window, cx| {
document.history(true, window, cx);
}))
// Past the block's own history, the document's.
// One history: a block's own never runs.
.capture_action(cx.listener(|document, _: &forms::Undo, window, cx| {
if document.at_edge_of_history(false, cx) {
cx.stop_propagation();
document.history(false, window, cx);
}
cx.stop_propagation();
document.history(false, window, cx);
}))
.capture_action(cx.listener(|document, _: &forms::Redo, window, cx| {
if document.at_edge_of_history(true, cx) {
cx.stop_propagation();
document.history(true, window, cx);
}
cx.stop_propagation();
document.history(true, window, cx);
}))
.capture_action(cx.listener(|document, _: &Up, window, cx| {
if document.step(false, window, cx) {
-8
View File
@@ -220,14 +220,6 @@ impl TextInput {
&self.label
}
/// A step left in that direction of its history.
pub(crate) fn can_step(&self, redo: bool) -> bool {
match redo {
true => self.history.can_redo(),
false => self.history.can_undo(),
}
}
pub fn selection(&self) -> Range<usize> {
self.selection.clone()
}