MarkdownDocument: one caret for every mode, pressed blocks kept across write-backs, preview read only, keyboard reach, history capped on every path
CI / site (push) Successful in 25s
CI / platforms (windows-latest) (push) Successful in 4m37s
CI / crate (push) Failing after 26m50s
CI / platforms (ubuntu-24.04) (push) Canceled after 0s

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 01:14:06 -04:00
1 parent 2b6f5513aa
commit fc181b44c2
13 files changed
+590 -242

No files matched your search

+2
View File
@@ -336,6 +336,7 @@ impl CodeEditor {
}
if let Some(previous) = self.history.undo(self.snapshot()) {
self.restore(previous, cx);
self.cap_history();
}
}
@@ -345,6 +346,7 @@ impl CodeEditor {
}
if let Some(next) = self.history.redo(self.snapshot()) {
self.restore(next, cx);
self.cap_history();
}
}
+1
View File
@@ -67,6 +67,7 @@ impl CodeEditor {
&& start.text != self.buffer.text()
{
self.history.record(start, false);
self.cap_history();
}
}
+10
View File
@@ -46,6 +46,16 @@ impl CodeEditor {
self.restart_blink(cx);
}
/// Keeps undo within its byte budget, logging what went.
pub(crate) fn cap_history(&mut self) {
let dropped = self
.history
.trim(self.history_bytes, |step| step.text.len());
if dropped > 0 {
log::info!("code editor: {dropped} far undo steps dropped");
}
}
/// A line's colors, as the owner or as code.
pub(crate) fn line_colors(&self, text: &str, cx: &App) -> Vec<(Range<usize>, HighlightStyle)> {
let Some(LineHighlighter(highlight)) = &self.options.highlighter else {
+4 -6
View File
@@ -103,6 +103,8 @@ pub struct CodeEditor {
pub(crate) buffer: Buffer,
pub(crate) selections: Vec<Selection>,
pub(crate) history: History<Snapshot>,
/// Undo keeps at most this many bytes of text.
pub(crate) history_bytes: usize,
pub(crate) focus: FocusHandle,
pub(crate) scroll: UniformListScrollHandle,
pub(crate) folded: BTreeSet<usize>,
@@ -172,6 +174,7 @@ impl CodeEditor {
buffer: Buffer::new(text),
selections: vec![Selection::caret(0)],
history: History::default(),
history_bytes: super::prose::HISTORY_BYTES,
focus,
scroll: UniformListScrollHandle::new(),
folded: BTreeSet::new(),
@@ -432,12 +435,7 @@ impl CodeEditor {
if before.text != self.buffer.text() {
if self.composing.is_none() {
self.history.record(before, typing);
let dropped = self
.history
.trim(super::prose::HISTORY_BYTES, |step| step.text.len());
if dropped > 0 {
log::info!("code editor: {dropped} oldest undo steps dropped");
}
self.cap_history();
}
self.marks.ghost = None;
self.folded.retain(|line| *line < self.buffer.lines());
+34
View File
@@ -0,0 +1,34 @@
use gpui::{EntityInputHandler, TestAppContext};
use super::editor;
/// Bytes of text all undo and redo steps hold.
fn held(editor: &super::CodeEditor) -> usize {
editor.history.held(|step| step.text.len())
}
#[gpui::test]
fn compositions_keep_undo_within_its_budget(cx: &mut TestAppContext) {
let (editor, cx) = editor(&"x".repeat(100), cx);
editor.update_in(cx, |editor, window, cx| {
editor.history_bytes = 250;
for word in ["a", "b", "c", "d"] {
editor.replace_and_mark_text_in_range(None, word, None, window, cx);
editor.unmark_text(window, cx);
}
assert!(held(editor) <= 250, "{} bytes held", held(editor));
assert!(editor.history.can_undo(), "the nearest steps stay");
});
}
#[gpui::test]
fn undo_keeps_redo_within_its_budget(cx: &mut TestAppContext) {
let (editor, cx) = editor("small", cx);
editor.update(cx, |editor, cx| {
editor.history_bytes = 50;
editor.edit([(0..5, "y".repeat(80))], cx);
editor.undo(cx);
assert_eq!(editor.text(), "small");
assert!(!editor.history.can_redo(), "a redo past the budget went");
});
}
+1
View File
@@ -1,3 +1,4 @@
mod history;
mod stale;
use std::{cell::Cell, rc::Rc, time::Duration};