Test undo/redo at editor layer, including selection restoration

This commit is contained in:
Nathan Sobo 2021-12-12 15:04:19 -07:00
parent 44cd0be068
commit cdbcbdfe6d
5 changed files with 325 additions and 180 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
mod anchor;
mod selection;
pub use anchor::{Anchor, AnchorRangeExt};
use anyhow::Result;
@ -7,8 +6,8 @@ use clock::ReplicaId;
use collections::HashMap;
use gpui::{AppContext, Entity, ModelContext, ModelHandle, MutableAppContext, Task};
use language::{
Buffer, BufferChunks, BufferSnapshot, Chunk, DiagnosticEntry, Event, File, FromAnchor,
Language, Selection, ToOffset as _, ToPoint as _, TransactionId,
Buffer, BufferChunks, BufferSnapshot, Chunk, DiagnosticEntry, Event, File, Language, Selection,
ToOffset as _, ToPoint as _, TransactionId,
};
use std::{
cell::{Ref, RefCell},
@ -16,7 +15,7 @@ use std::{
iter::Peekable,
ops::{Range, Sub},
sync::Arc,
time::SystemTime,
time::{Duration, Instant, SystemTime},
};
use sum_tree::{Bias, Cursor, SumTree};
use text::{
@ -40,11 +39,15 @@ pub struct MultiBuffer {
}
pub trait ToOffset: 'static {
fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize;
fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize;
}
pub trait ToPoint: 'static {
fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point;
fn to_point(&self, snapshot: &MultiBufferSnapshot) -> Point;
}
pub trait FromAnchor: 'static {
fn from_anchor(anchor: &Anchor, snapshot: &MultiBufferSnapshot) -> Self;
}
#[derive(Debug)]
@ -130,6 +133,13 @@ impl MultiBuffer {
self.replica_id
}
pub fn transaction_group_interval(&self, cx: &AppContext) -> Duration {
self.as_singleton()
.unwrap()
.read(cx)
.transaction_group_interval()
}
pub fn snapshot(&self, cx: &AppContext) -> MultiBufferSnapshot {
self.sync(cx);
self.snapshot.borrow().clone()
@ -200,10 +210,18 @@ impl MultiBuffer {
}
pub fn start_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
self.start_transaction_at(Instant::now(), cx)
}
pub(crate) fn start_transaction_at(
&mut self,
now: Instant,
cx: &mut ModelContext<Self>,
) -> Option<TransactionId> {
// TODO
self.as_singleton()
.unwrap()
.update(cx, |buffer, _| buffer.start_transaction())
.update(cx, |buffer, _| buffer.start_transaction_at(now))
}
pub fn end_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
@ -213,6 +231,17 @@ impl MultiBuffer {
.update(cx, |buffer, cx| buffer.end_transaction(cx))
}
pub(crate) fn end_transaction_at(
&mut self,
now: Instant,
cx: &mut ModelContext<Self>,
) -> Option<TransactionId> {
// TODO
self.as_singleton()
.unwrap()
.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
}
pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
// TODO
self.as_singleton()

View File

@ -1,42 +0,0 @@
use super::{Anchor, MultiBufferSnapshot};
use std::ops::Sub;
use text::{rope::TextDimension, Selection};
fn resolve_selection<'a, D>(
selection: &'a Selection<Anchor>,
snapshot: &'a MultiBufferSnapshot,
) -> Selection<D>
where
D: TextDimension + Ord + Sub<D, Output = D>,
{
Selection {
id: selection.id,
start: selection.start.summary::<D>(snapshot),
end: selection.end.summary::<D>(snapshot),
reversed: selection.reversed,
goal: selection.goal,
}
}
fn resolve_selections<'a, D>(
selections: &'a [Selection<Anchor>],
snapshot: &'a MultiBufferSnapshot,
) -> impl 'a + Iterator<Item = Selection<D>>
where
D: TextDimension + Ord + Sub<D, Output = D>,
{
let mut summaries = snapshot
.summaries_for_anchors::<D, _>(
selections
.iter()
.flat_map(|selection| [&selection.start, &selection.end]),
)
.into_iter();
selections.iter().map(move |selection| Selection {
id: selection.id,
start: summaries.next().unwrap(),
end: summaries.next().unwrap(),
reversed: selection.reversed,
goal: selection.goal,
})
}

View File

@ -31,7 +31,7 @@ use std::{
vec,
};
use sum_tree::TreeMap;
use text::{operation_queue::OperationQueue, rope::TextDimension};
use text::operation_queue::OperationQueue;
pub use text::{Buffer as TextBuffer, Operation as _, *};
use theme::SyntaxTheme;
use tree_sitter::{InputEdit, Parser, QueryCursor, Tree};
@ -1062,7 +1062,7 @@ impl Buffer {
self.start_transaction_at(Instant::now())
}
pub(crate) fn start_transaction_at(&mut self, now: Instant) -> Option<TransactionId> {
pub fn start_transaction_at(&mut self, now: Instant) -> Option<TransactionId> {
self.text.start_transaction_at(now)
}
@ -1070,7 +1070,7 @@ impl Buffer {
self.end_transaction_at(Instant::now(), cx)
}
pub(crate) fn end_transaction_at(
pub fn end_transaction_at(
&mut self,
now: Instant,
cx: &mut ModelContext<Self>,

View File

@ -511,6 +511,10 @@ impl Buffer {
self.deferred_ops.len()
}
pub fn transaction_group_interval(&self) -> Duration {
self.history.group_interval
}
pub fn edit<R, I, S, T>(&mut self, ranges: R, new_text: T) -> EditOperation
where
R: IntoIterator<IntoIter = I>,