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 anchor;
mod selection;
pub use anchor::{Anchor, AnchorRangeExt}; pub use anchor::{Anchor, AnchorRangeExt};
use anyhow::Result; use anyhow::Result;
@ -7,8 +6,8 @@ use clock::ReplicaId;
use collections::HashMap; use collections::HashMap;
use gpui::{AppContext, Entity, ModelContext, ModelHandle, MutableAppContext, Task}; use gpui::{AppContext, Entity, ModelContext, ModelHandle, MutableAppContext, Task};
use language::{ use language::{
Buffer, BufferChunks, BufferSnapshot, Chunk, DiagnosticEntry, Event, File, FromAnchor, Buffer, BufferChunks, BufferSnapshot, Chunk, DiagnosticEntry, Event, File, Language, Selection,
Language, Selection, ToOffset as _, ToPoint as _, TransactionId, ToOffset as _, ToPoint as _, TransactionId,
}; };
use std::{ use std::{
cell::{Ref, RefCell}, cell::{Ref, RefCell},
@ -16,7 +15,7 @@ use std::{
iter::Peekable, iter::Peekable,
ops::{Range, Sub}, ops::{Range, Sub},
sync::Arc, sync::Arc,
time::SystemTime, time::{Duration, Instant, SystemTime},
}; };
use sum_tree::{Bias, Cursor, SumTree}; use sum_tree::{Bias, Cursor, SumTree};
use text::{ use text::{
@ -40,11 +39,15 @@ pub struct MultiBuffer {
} }
pub trait ToOffset: 'static { pub trait ToOffset: 'static {
fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize; fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize;
} }
pub trait ToPoint: 'static { 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)] #[derive(Debug)]
@ -130,6 +133,13 @@ impl MultiBuffer {
self.replica_id 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 { pub fn snapshot(&self, cx: &AppContext) -> MultiBufferSnapshot {
self.sync(cx); self.sync(cx);
self.snapshot.borrow().clone() self.snapshot.borrow().clone()
@ -200,10 +210,18 @@ impl MultiBuffer {
} }
pub fn start_transaction(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> { 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 // TODO
self.as_singleton() self.as_singleton()
.unwrap() .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> { 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)) .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> { pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
// TODO // TODO
self.as_singleton() 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, vec,
}; };
use sum_tree::TreeMap; use sum_tree::TreeMap;
use text::{operation_queue::OperationQueue, rope::TextDimension}; use text::operation_queue::OperationQueue;
pub use text::{Buffer as TextBuffer, Operation as _, *}; pub use text::{Buffer as TextBuffer, Operation as _, *};
use theme::SyntaxTheme; use theme::SyntaxTheme;
use tree_sitter::{InputEdit, Parser, QueryCursor, Tree}; use tree_sitter::{InputEdit, Parser, QueryCursor, Tree};
@ -1062,7 +1062,7 @@ impl Buffer {
self.start_transaction_at(Instant::now()) 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) self.text.start_transaction_at(now)
} }
@ -1070,7 +1070,7 @@ impl Buffer {
self.end_transaction_at(Instant::now(), cx) self.end_transaction_at(Instant::now(), cx)
} }
pub(crate) fn end_transaction_at( pub fn end_transaction_at(
&mut self, &mut self,
now: Instant, now: Instant,
cx: &mut ModelContext<Self>, cx: &mut ModelContext<Self>,

View file

@ -511,6 +511,10 @@ impl Buffer {
self.deferred_ops.len() 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 pub fn edit<R, I, S, T>(&mut self, ranges: R, new_text: T) -> EditOperation
where where
R: IntoIterator<IntoIter = I>, R: IntoIterator<IntoIter = I>,