Detailed changes
@@ -162,6 +162,12 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
+[[package]]
+name = "arrayvec"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd"
+
[[package]]
name = "ascii"
version = "1.0.0"
@@ -626,7 +632,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587"
dependencies = [
"arrayref",
- "arrayvec",
+ "arrayvec 0.5.2",
"constant_time_eq",
]
@@ -637,7 +643,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b64485778c4f16a6a5a9d335e80d449ac6c70cdd6a06d2af18a6f6f775a125b3"
dependencies = [
"arrayref",
- "arrayvec",
+ "arrayvec 0.5.2",
"cc",
"cfg-if 0.1.10",
"constant_time_eq",
@@ -2145,6 +2151,7 @@ name = "gpui"
version = "0.1.0"
dependencies = [
"anyhow",
+ "arrayvec 0.7.1",
"async-task",
"backtrace",
"bindgen",
@@ -2632,7 +2639,7 @@ version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e30b1df631d23875f230ed3ddd1a88c231f269a04b2044eb6ca87e763b5f4c42"
dependencies = [
- "arrayvec",
+ "arrayvec 0.5.2",
]
[[package]]
@@ -2665,7 +2672,7 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
dependencies = [
- "arrayvec",
+ "arrayvec 0.5.2",
"bitflags 1.2.1",
"cfg-if 1.0.0",
"ryu",
@@ -5164,7 +5171,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bf81f2900d2e235220e6f31ec9f63ade6a7f59090c556d74fe949bb3b15e9fe"
dependencies = [
"arrayref",
- "arrayvec",
+ "arrayvec 0.5.2",
"bytemuck",
"cfg-if 1.0.0",
"png 0.16.8",
@@ -5792,7 +5799,7 @@ name = "zed"
version = "0.1.0"
dependencies = [
"anyhow",
- "arrayvec",
+ "arrayvec 0.7.1",
"async-trait",
"async-tungstenite",
"cargo-bundle",
@@ -5,6 +5,7 @@ name = "gpui"
version = "0.1.0"
[dependencies]
+arrayvec = "0.7.1"
async-task = "4.0.3"
backtrace = "0.3"
ctor = "0.1"
@@ -7,6 +7,7 @@ mod event_handler;
mod flex;
mod label;
mod line_box;
+mod list;
mod mouse_event_handler;
mod stack;
mod svg;
@@ -22,6 +23,7 @@ pub use event_handler::*;
pub use flex::*;
pub use label::*;
pub use line_box::*;
+pub use list::*;
pub use mouse_event_handler::*;
pub use stack::*;
pub use svg::*;
@@ -0,0 +1,45 @@
+use crate::sum_tree::{self, SumTree};
+use parking_lot::Mutex;
+use std::sync::Arc;
+
+use crate::ElementBox;
+
+pub struct List {
+ state: ListState,
+}
+
+pub struct ListState(Arc<Mutex<StateInner>>);
+
+struct StateInner {
+ elements: Vec<ElementBox>,
+ element_heights: SumTree<ElementHeight>,
+}
+
+#[derive(Clone, Debug)]
+enum ElementHeight {
+ Pending,
+ Ready(f32),
+}
+
+#[derive(Clone, Debug, Default)]
+struct ElementHeightSummary {
+ pending_count: usize,
+ height: f32,
+}
+
+impl sum_tree::Item for ElementHeight {
+ type Summary = ElementHeightSummary;
+
+ fn summary(&self) -> Self::Summary {
+ todo!()
+ }
+}
+
+impl sum_tree::Summary for ElementHeightSummary {
+ type Context = ();
+
+ fn add_summary(&mut self, summary: &Self, cx: &Self::Context) {
+ self.pending_count += summary.pending_count;
+ self.height += summary.height;
+ }
+}
@@ -1,6 +1,7 @@
mod app;
pub use app::*;
mod assets;
+pub mod sum_tree;
#[cfg(test)]
mod test;
pub use assets::*;
@@ -1,6 +1,5 @@
mod cursor;
-use crate::util::Bias;
use arrayvec::ArrayVec;
pub use cursor::Cursor;
pub use cursor::FilterCursor;
@@ -47,6 +46,29 @@ impl<'a, S: Summary, T: Dimension<'a, S> + Ord> SeekDimension<'a, S> for T {
}
}
+#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
+pub enum Bias {
+ Left,
+ Right,
+}
+
+impl PartialOrd for Bias {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for Bias {
+ fn cmp(&self, other: &Self) -> Ordering {
+ match (self, other) {
+ (Self::Left, Self::Left) => Ordering::Equal,
+ (Self::Left, Self::Right) => Ordering::Less,
+ (Self::Right, Self::Right) => Ordering::Equal,
+ (Self::Right, Self::Left) => Ordering::Greater,
+ }
+ }
+}
+
#[derive(Debug, Clone)]
pub struct SumTree<T: Item>(Arc<Node<T>>);
@@ -253,8 +275,8 @@ impl<T: Item> SumTree<T> {
summary.add_summary(other_node.summary(), cx);
let height_delta = *height - other_node.height();
- let mut summaries_to_append = ArrayVec::<[T::Summary; 2 * TREE_BASE]>::new();
- let mut trees_to_append = ArrayVec::<[SumTree<T>; 2 * TREE_BASE]>::new();
+ let mut summaries_to_append = ArrayVec::<T::Summary, { 2 * TREE_BASE }>::new();
+ let mut trees_to_append = ArrayVec::<SumTree<T>, { 2 * TREE_BASE }>::new();
if height_delta == 0 {
summaries_to_append.extend(other_node.child_summaries().iter().cloned());
trees_to_append.extend(other_node.child_trees().iter().cloned());
@@ -277,8 +299,8 @@ impl<T: Item> SumTree<T> {
let child_count = child_trees.len() + trees_to_append.len();
if child_count > 2 * TREE_BASE {
- let left_summaries: ArrayVec<_>;
- let right_summaries: ArrayVec<_>;
+ let left_summaries: ArrayVec<_, { 2 * TREE_BASE }>;
+ let right_summaries: ArrayVec<_, { 2 * TREE_BASE }>;
let left_trees;
let right_trees;
@@ -323,7 +345,7 @@ impl<T: Item> SumTree<T> {
let left_items;
let right_items;
let left_summaries;
- let right_summaries: ArrayVec<[T::Summary; 2 * TREE_BASE]>;
+ let right_summaries: ArrayVec<T::Summary, { 2 * TREE_BASE }>;
let midpoint = (child_count + child_count % 2) / 2;
{
@@ -491,13 +513,13 @@ pub enum Node<T: Item> {
Internal {
height: u8,
summary: T::Summary,
- child_summaries: ArrayVec<[T::Summary; 2 * TREE_BASE]>,
- child_trees: ArrayVec<[SumTree<T>; 2 * TREE_BASE]>,
+ child_summaries: ArrayVec<T::Summary, { 2 * TREE_BASE }>,
+ child_trees: ArrayVec<SumTree<T>, { 2 * TREE_BASE }>,
},
Leaf {
summary: T::Summary,
- items: ArrayVec<[T; 2 * TREE_BASE]>,
- item_summaries: ArrayVec<[T::Summary; 2 * TREE_BASE]>,
+ items: ArrayVec<T, { 2 * TREE_BASE }>,
+ item_summaries: ArrayVec<T::Summary, { 2 * TREE_BASE }>,
},
}
@@ -532,14 +554,14 @@ impl<T: Item> Node<T> {
}
}
- fn child_trees(&self) -> &ArrayVec<[SumTree<T>; 2 * TREE_BASE]> {
+ fn child_trees(&self) -> &ArrayVec<SumTree<T>, { 2 * TREE_BASE }> {
match self {
Node::Internal { child_trees, .. } => child_trees,
Node::Leaf { .. } => panic!("Leaf nodes have no child trees"),
}
}
- fn items(&self) -> &ArrayVec<[T; 2 * TREE_BASE]> {
+ fn items(&self) -> &ArrayVec<T, { 2 * TREE_BASE }> {
match self {
Node::Leaf { items, .. } => items,
Node::Internal { .. } => panic!("Internal nodes have no items"),
@@ -603,7 +625,7 @@ mod tests {
);
}
- #[gpui::test(iterations = 100)]
+ #[crate::test(self, iterations = 100)]
fn test_random(mut rng: StdRng) {
let rng = &mut rng;
let mut tree = SumTree::<u8>::new();
@@ -13,7 +13,7 @@ struct StackEntry<'a, T: Item, S, U> {
#[derive(Clone)]
pub struct Cursor<'a, T: Item, S, U> {
tree: &'a SumTree<T>,
- stack: ArrayVec<[StackEntry<'a, T, S, U>; 16]>,
+ stack: ArrayVec<StackEntry<'a, T, S, U>, 16>,
seek_dimension: S,
sum_dimension: U,
did_seek: bool,
@@ -495,8 +495,8 @@ where
ref item_summaries,
..
} => {
- let mut slice_items = ArrayVec::<[T; 2 * TREE_BASE]>::new();
- let mut slice_item_summaries = ArrayVec::<[T::Summary; 2 * TREE_BASE]>::new();
+ let mut slice_items = ArrayVec::<T, { 2 * TREE_BASE }>::new();
+ let mut slice_item_summaries = ArrayVec::<T::Summary, { 2 * TREE_BASE }>::new();
let mut slice_items_summary = match aggregate {
SeekAggregate::Slice(_) => Some(T::Summary::default()),
_ => None,
@@ -18,8 +18,8 @@ test-support = ["tempdir", "zrpc/test-support"]
[dependencies]
anyhow = "1.0.38"
-arrayvec = "0.5.2"
async-trait = "0.1"
+arrayvec = "0.7.1"
async-tungstenite = { version = "0.14", features = ["async-tls"] }
crossbeam-channel = "0.5.0"
ctor = "0.1.20"
@@ -1,30 +1,30 @@
mod anchor;
+mod operation_queue;
mod point;
pub mod rope;
mod selection;
-pub use anchor::*;
-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},
};
+pub use anchor::*;
use anyhow::{anyhow, Result};
-use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task};
+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 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;
}
@@ -1,26 +1,27 @@
-use crate::{
- sum_tree::{Cursor, Dimension, Edit, Item, KeyedItem, SumTree, Summary},
- time,
-};
+use super::Operation;
+use crate::time;
+use gpui::sum_tree::{Cursor, Dimension, Edit, Item, KeyedItem, SumTree, Summary};
use std::{fmt::Debug, ops::Add};
-pub trait Operation: Clone + Debug + Eq {
- fn timestamp(&self) -> time::Lamport;
-}
-
#[derive(Clone, Debug)]
-pub struct OperationQueue<T: Operation>(SumTree<T>);
+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 {
- key: OperationKey,
- len: usize,
+ pub key: OperationKey,
+ pub len: usize,
+}
+
+impl OperationKey {
+ pub fn new(timestamp: time::Lamport) -> Self {
+ Self(timestamp)
+ }
}
-impl<T: Operation> OperationQueue<T> {
+impl OperationQueue {
pub fn new() -> Self {
OperationQueue(SumTree::new())
}
@@ -29,9 +30,9 @@ impl<T: Operation> OperationQueue<T> {
self.0.summary().len
}
- pub fn insert(&mut self, mut ops: Vec<T>) {
- ops.sort_by_key(|op| op.timestamp());
- ops.dedup_by_key(|op| op.timestamp());
+ 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(), &());
}
@@ -42,30 +43,11 @@ impl<T: Operation> OperationQueue<T> {
clone
}
- pub fn cursor(&self) -> Cursor<T, (), ()> {
+ pub fn cursor(&self) -> Cursor<Operation, (), ()> {
self.0.cursor()
}
}
-impl<T: Operation> Item for T {
- type Summary = OperationSummary;
-
- fn summary(&self) -> Self::Summary {
- OperationSummary {
- key: OperationKey(self.timestamp()),
- len: 1,
- }
- }
-}
-
-impl<T: Operation> KeyedItem for T {
- type Key = OperationKey;
-
- fn key(&self) -> Self::Key {
- OperationKey(self.timestamp())
- }
-}
-
impl Summary for OperationSummary {
type Context = ();
@@ -95,6 +77,25 @@ impl<'a> Dimension<'a, OperationSummary> for OperationKey {
}
}
+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::*;
@@ -107,27 +108,21 @@ mod tests {
assert_eq!(queue.len(), 0);
queue.insert(vec![
- TestOperation(clock.tick()),
- TestOperation(clock.tick()),
+ Operation::Test(clock.tick()),
+ Operation::Test(clock.tick()),
]);
assert_eq!(queue.len(), 2);
- queue.insert(vec![TestOperation(clock.tick())]);
+ queue.insert(vec![Operation::Test(clock.tick())]);
assert_eq!(queue.len(), 3);
drop(queue.drain());
assert_eq!(queue.len(), 0);
- queue.insert(vec![TestOperation(clock.tick())]);
+ queue.insert(vec![Operation::Test(clock.tick())]);
assert_eq!(queue.len(), 1);
}
#[derive(Clone, Debug, Eq, PartialEq)]
struct TestOperation(time::Lamport);
-
- impl Operation for TestOperation {
- fn timestamp(&self) -> time::Lamport {
- self.0
- }
- }
}
@@ -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| {
@@ -7,11 +7,9 @@ pub mod fs;
mod fuzzy;
pub mod language;
pub mod menus;
-mod operation_queue;
pub mod project_browser;
pub mod rpc;
pub mod settings;
-mod sum_tree;
#[cfg(any(test, feature = "test-support"))]
pub mod test;
pub mod theme;
@@ -1,30 +1,8 @@
use futures::Future;
+pub use gpui::sum_tree::Bias;
use rand::prelude::*;
use std::cmp::Ordering;
-#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
-pub enum Bias {
- Left,
- Right,
-}
-
-impl PartialOrd for Bias {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- Some(self.cmp(other))
- }
-}
-
-impl Ord for Bias {
- fn cmp(&self, other: &Self) -> Ordering {
- match (self, other) {
- (Self::Left, Self::Left) => Ordering::Equal,
- (Self::Left, Self::Right) => Ordering::Less,
- (Self::Right, Self::Right) => Ordering::Equal,
- (Self::Right, Self::Left) => Ordering::Greater,
- }
- }
-}
-
pub fn post_inc(value: &mut usize) -> usize {
let prev = *value;
*value += 1;
@@ -8,7 +8,6 @@ use crate::{
fuzzy::CharBag,
language::LanguageRegistry,
rpc::{self, proto},
- sum_tree::{self, Cursor, Edit, SumTree},
time::{self, ReplicaId},
util::{log_async_errors, Bias},
};
@@ -17,8 +16,10 @@ use anyhow::{anyhow, Result};
use futures::{Stream, StreamExt};
pub use fuzzy::{match_paths, PathMatch};
use gpui::{
- executor, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext,
- Task, UpgradeModelHandle, WeakModelHandle,
+ executor,
+ sum_tree::{self, Cursor, Edit, SumTree},
+ AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext, Task,
+ UpgradeModelHandle, WeakModelHandle,
};
use lazy_static::lazy_static;
use parking_lot::Mutex;