WIP: Move sum_tree module into gpui so we can use it in List
This commit is contained in:
+28
-22
@@ -1,30 +1,30 @@
|
||||
mod anchor;
|
||||
mod operation_queue;
|
||||
mod point;
|
||||
pub mod rope;
|
||||
mod selection;
|
||||
|
||||
use crate::{
|
||||
language::{Language, Tree},
|
||||
settings::{HighlightId, HighlightMap},
|
||||
time::{self, ReplicaId},
|
||||
util::Bias,
|
||||
worktree::{File, Worktree},
|
||||
};
|
||||
pub use anchor::*;
|
||||
use anyhow::{anyhow, Result};
|
||||
use gpui::{
|
||||
sum_tree::{self, FilterCursor, SumTree},
|
||||
AppContext, Entity, ModelContext, ModelHandle, Task,
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use operation_queue::OperationQueue;
|
||||
use parking_lot::Mutex;
|
||||
pub use point::*;
|
||||
pub use rope::{Chunks, Rope, TextSummary};
|
||||
use seahash::SeaHasher;
|
||||
pub use selection::*;
|
||||
use similar::{ChangeTag, TextDiff};
|
||||
use tree_sitter::{InputEdit, Parser, QueryCursor};
|
||||
use zrpc::proto;
|
||||
|
||||
use crate::{
|
||||
language::{Language, Tree},
|
||||
operation_queue::{self, OperationQueue},
|
||||
settings::{HighlightId, HighlightMap},
|
||||
sum_tree::{self, FilterCursor, SumTree},
|
||||
time::{self, ReplicaId},
|
||||
util::Bias,
|
||||
worktree::{File, Worktree},
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task};
|
||||
use lazy_static::lazy_static;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
cmp,
|
||||
@@ -37,6 +37,8 @@ use std::{
|
||||
sync::Arc,
|
||||
time::{Duration, Instant, SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
use tree_sitter::{InputEdit, Parser, QueryCursor};
|
||||
use zrpc::proto;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct DeterministicState;
|
||||
@@ -120,7 +122,7 @@ pub struct Buffer {
|
||||
syntax_tree: Mutex<Option<SyntaxTree>>,
|
||||
is_parsing: bool,
|
||||
selections: HashMap<SelectionSetId, SelectionSet>,
|
||||
deferred_ops: OperationQueue<Operation>,
|
||||
deferred_ops: OperationQueue,
|
||||
deferred_replicas: HashSet<ReplicaId>,
|
||||
replica_id: ReplicaId,
|
||||
remote_id: u64,
|
||||
@@ -483,6 +485,8 @@ pub enum Operation {
|
||||
set_id: Option<SelectionSetId>,
|
||||
lamport_timestamp: time::Lamport,
|
||||
},
|
||||
#[cfg(test)]
|
||||
Test(time::Lamport),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
@@ -1390,6 +1394,8 @@ impl Buffer {
|
||||
}
|
||||
self.lamport_clock.observe(lamport_timestamp);
|
||||
}
|
||||
#[cfg(test)]
|
||||
Operation::Test(_) => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -1731,6 +1737,8 @@ impl Buffer {
|
||||
Operation::SetActiveSelections { set_id, .. } => {
|
||||
set_id.map_or(true, |set_id| self.selections.contains_key(&set_id))
|
||||
}
|
||||
#[cfg(test)]
|
||||
Operation::Test(_) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2564,6 +2572,8 @@ impl Operation {
|
||||
Operation::SetActiveSelections {
|
||||
lamport_timestamp, ..
|
||||
} => *lamport_timestamp,
|
||||
#[cfg(test)]
|
||||
Operation::Test(lamport_timestamp) => *lamport_timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2630,6 +2640,8 @@ impl<'a> Into<proto::Operation> for &'a Operation {
|
||||
lamport_timestamp: lamport_timestamp.value,
|
||||
},
|
||||
),
|
||||
#[cfg(test)]
|
||||
Operation::Test(_) => unimplemented!()
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -2834,12 +2846,6 @@ impl TryFrom<proto::Selection> for Selection {
|
||||
}
|
||||
}
|
||||
|
||||
impl operation_queue::Operation for Operation {
|
||||
fn timestamp(&self) -> time::Lamport {
|
||||
self.lamport_timestamp()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToOffset {
|
||||
fn to_offset<'a>(&self, content: impl Into<Content<'a>>) -> usize;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
use super::Operation;
|
||||
use crate::time;
|
||||
use gpui::sum_tree::{Cursor, Dimension, Edit, Item, KeyedItem, SumTree, Summary};
|
||||
use std::{fmt::Debug, ops::Add};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OperationQueue(SumTree<Operation>);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub struct OperationKey(time::Lamport);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
||||
pub struct OperationSummary {
|
||||
pub key: OperationKey,
|
||||
pub len: usize,
|
||||
}
|
||||
|
||||
impl OperationKey {
|
||||
pub fn new(timestamp: time::Lamport) -> Self {
|
||||
Self(timestamp)
|
||||
}
|
||||
}
|
||||
|
||||
impl OperationQueue {
|
||||
pub fn new() -> Self {
|
||||
OperationQueue(SumTree::new())
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.summary().len
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, mut ops: Vec<Operation>) {
|
||||
ops.sort_by_key(|op| op.lamport_timestamp());
|
||||
ops.dedup_by_key(|op| op.lamport_timestamp());
|
||||
self.0
|
||||
.edit(ops.into_iter().map(Edit::Insert).collect(), &());
|
||||
}
|
||||
|
||||
pub fn drain(&mut self) -> Self {
|
||||
let clone = self.clone();
|
||||
self.0 = SumTree::new();
|
||||
clone
|
||||
}
|
||||
|
||||
pub fn cursor(&self) -> Cursor<Operation, (), ()> {
|
||||
self.0.cursor()
|
||||
}
|
||||
}
|
||||
|
||||
impl Summary for OperationSummary {
|
||||
type Context = ();
|
||||
|
||||
fn add_summary(&mut self, other: &Self, _: &()) {
|
||||
assert!(self.key < other.key);
|
||||
self.key = other.key;
|
||||
self.len += other.len;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Add<&'a Self> for OperationSummary {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: &Self) -> Self {
|
||||
assert!(self.key < other.key);
|
||||
OperationSummary {
|
||||
key: other.key,
|
||||
len: self.len + other.len,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Dimension<'a, OperationSummary> for OperationKey {
|
||||
fn add_summary(&mut self, summary: &OperationSummary, _: &()) {
|
||||
assert!(*self <= summary.key);
|
||||
*self = summary.key;
|
||||
}
|
||||
}
|
||||
|
||||
impl Item for Operation {
|
||||
type Summary = OperationSummary;
|
||||
|
||||
fn summary(&self) -> Self::Summary {
|
||||
OperationSummary {
|
||||
key: OperationKey::new(self.lamport_timestamp()),
|
||||
len: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl KeyedItem for Operation {
|
||||
type Key = OperationKey;
|
||||
|
||||
fn key(&self) -> Self::Key {
|
||||
OperationKey::new(self.lamport_timestamp())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_len() {
|
||||
let mut clock = time::Lamport::new(0);
|
||||
|
||||
let mut queue = OperationQueue::new();
|
||||
assert_eq!(queue.len(), 0);
|
||||
|
||||
queue.insert(vec![
|
||||
Operation::Test(clock.tick()),
|
||||
Operation::Test(clock.tick()),
|
||||
]);
|
||||
assert_eq!(queue.len(), 2);
|
||||
|
||||
queue.insert(vec![Operation::Test(clock.tick())]);
|
||||
assert_eq!(queue.len(), 3);
|
||||
|
||||
drop(queue.drain());
|
||||
assert_eq!(queue.len(), 0);
|
||||
|
||||
queue.insert(vec![Operation::Test(clock.tick())]);
|
||||
assert_eq!(queue.len(), 1);
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
struct TestOperation(time::Lamport);
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
use super::Point;
|
||||
use crate::{
|
||||
sum_tree::{self, SumTree},
|
||||
util::Bias,
|
||||
};
|
||||
use crate::util::Bias;
|
||||
use arrayvec::ArrayString;
|
||||
use gpui::sum_tree::{self, SumTree};
|
||||
use smallvec::SmallVec;
|
||||
use std::{cmp, ops::Range, str};
|
||||
|
||||
@@ -61,7 +59,7 @@ impl Rope {
|
||||
if last_chunk.0.len() + first_new_chunk_ref.0.len() <= 2 * CHUNK_BASE {
|
||||
last_chunk.0.push_str(&first_new_chunk.take().unwrap().0);
|
||||
} else {
|
||||
let mut text = ArrayString::<[_; 4 * CHUNK_BASE]>::new();
|
||||
let mut text = ArrayString::<{ 4 * CHUNK_BASE }>::new();
|
||||
text.push_str(&last_chunk.0);
|
||||
text.push_str(&first_new_chunk_ref.0);
|
||||
let (left, right) = text.split_at(find_split_ix(&text));
|
||||
@@ -330,7 +328,7 @@ impl<'a> Iterator for Chunks<'a> {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct Chunk(ArrayString<[u8; 2 * CHUNK_BASE]>);
|
||||
struct Chunk(ArrayString<{ 2 * CHUNK_BASE }>);
|
||||
|
||||
impl Chunk {
|
||||
fn to_point(&self, target: usize) -> Point {
|
||||
|
||||
@@ -2,14 +2,11 @@ use super::{
|
||||
buffer::{AnchorRangeExt, TextSummary},
|
||||
Anchor, Buffer, Point, ToOffset,
|
||||
};
|
||||
use crate::{
|
||||
editor::buffer,
|
||||
settings::HighlightId,
|
||||
use crate::{editor::buffer, settings::HighlightId, time, util::Bias};
|
||||
use gpui::{
|
||||
sum_tree::{self, Cursor, FilterCursor, SumTree},
|
||||
time,
|
||||
util::Bias,
|
||||
AppContext, ModelHandle,
|
||||
};
|
||||
use gpui::{AppContext, ModelHandle};
|
||||
use parking_lot::Mutex;
|
||||
use std::{
|
||||
cmp::{self, Ordering},
|
||||
|
||||
@@ -3,14 +3,11 @@ use super::{
|
||||
line_wrapper::LineWrapper,
|
||||
tab_map::{self, Edit as TabEdit, Snapshot as TabSnapshot, TabPoint, TextSummary},
|
||||
};
|
||||
use crate::{
|
||||
editor::Point,
|
||||
settings::HighlightId,
|
||||
use crate::{editor::Point, settings::HighlightId, util::Bias, Settings};
|
||||
use gpui::{
|
||||
sum_tree::{self, Cursor, SumTree},
|
||||
util::Bias,
|
||||
Settings,
|
||||
Entity, ModelContext, Task,
|
||||
};
|
||||
use gpui::{Entity, ModelContext, Task};
|
||||
use lazy_static::lazy_static;
|
||||
use smol::future::yield_now;
|
||||
use std::{collections::VecDeque, ops::Range, time::Duration};
|
||||
@@ -816,8 +813,12 @@ fn push_isomorphic(transforms: &mut Vec<Transform>, summary: TextSummary) {
|
||||
transforms.push(Transform::isomorphic(summary));
|
||||
}
|
||||
|
||||
impl SumTree<Transform> {
|
||||
pub fn push_or_extend(&mut self, transform: Transform) {
|
||||
trait SumTreeExt {
|
||||
fn push_or_extend(&mut self, transform: Transform);
|
||||
}
|
||||
|
||||
impl SumTreeExt for SumTree<Transform> {
|
||||
fn push_or_extend(&mut self, transform: Transform) {
|
||||
let mut transform = Some(transform);
|
||||
self.update_last(
|
||||
|last_transform| {
|
||||
|
||||
Reference in New Issue
Block a user