diff --git a/Cargo.toml b/Cargo.toml index 80fbb251e5..bf2d5c8143 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,6 @@ core-graphics = {git = "https://github.com/servo/core-foundation-rs", rev = "025 [profile.dev] split-debuginfo = "unpacked" + +[profile.release] +debug = true diff --git a/zed/src/editor/buffer/mod.rs b/zed/src/editor/buffer/mod.rs index 72ead904d2..e4a06bfda9 100644 --- a/zed/src/editor/buffer/mod.rs +++ b/zed/src/editor/buffer/mod.rs @@ -393,39 +393,48 @@ impl Buffer { insertion_splits.insert( base_insertion.id, - SumTree::from_item(InsertionSplit { - fragment_id: FragmentId::min_value().clone(), - extent: 0, - }), + SumTree::from_item( + InsertionSplit { + fragment_id: FragmentId::min_value().clone(), + extent: 0, + }, + &(), + ), + ); + fragments.push( + Fragment { + id: FragmentId::min_value().clone(), + insertion: base_insertion.clone(), + text: base_insertion.text.slice(0..0), + deletions: Default::default(), + max_undos: Default::default(), + visible: true, + }, + &(), ); - fragments.push(Fragment { - id: FragmentId::min_value().clone(), - insertion: base_insertion.clone(), - text: base_insertion.text.slice(0..0), - deletions: Default::default(), - max_undos: Default::default(), - visible: true, - }); if base_insertion.text.len() > 0 { let base_fragment_id = FragmentId::between(&FragmentId::min_value(), &FragmentId::max_value()); - insertion_splits - .get_mut(&base_insertion.id) - .unwrap() - .push(InsertionSplit { + insertion_splits.get_mut(&base_insertion.id).unwrap().push( + InsertionSplit { fragment_id: base_fragment_id.clone(), extent: base_insertion.text.len(), - }); - fragments.push(Fragment { - id: base_fragment_id, - text: base_insertion.text.clone(), - insertion: base_insertion, - deletions: Default::default(), - max_undos: Default::default(), - visible: true, - }); + }, + &(), + ); + fragments.push( + Fragment { + id: base_fragment_id, + text: base_insertion.text.clone(), + insertion: base_insertion, + deletions: Default::default(), + max_undos: Default::default(), + visible: true, + }, + &(), + ); } Self { @@ -507,22 +516,22 @@ impl Buffer { let mut summary = TextSummary::default(); let mut cursor = self.fragments.cursor::(); - cursor.seek(&range.start, SeekBias::Right); + cursor.seek(&range.start, SeekBias::Right, &()); if let Some(fragment) = cursor.item() { let summary_start = cmp::max(*cursor.start(), range.start) - cursor.start(); let summary_end = cmp::min(range.end - cursor.start(), fragment.len()); - summary += &fragment.text.slice(summary_start..summary_end).summary(); + summary += fragment.text.slice(summary_start..summary_end).summary(); cursor.next(); } if range.end > *cursor.start() { - summary += &cursor.summary::(&range.end, SeekBias::Right); + summary += cursor.summary::(&range.end, SeekBias::Right, &()); if let Some(fragment) = cursor.item() { let summary_start = cmp::max(*cursor.start(), range.start) - cursor.start(); let summary_end = cmp::min(range.end - cursor.start(), fragment.len()); - summary += &fragment.text.slice(summary_start..summary_end).summary(); + summary += fragment.text.slice(summary_start..summary_end).summary(); } } @@ -552,22 +561,22 @@ impl Buffer { let mut summary = TextSummary::default(); let mut cursor = self.fragments.cursor::(); - cursor.seek(&range.start, SeekBias::Right); + cursor.seek(&range.start, SeekBias::Right, &()); if let Some(fragment) = cursor.item() { let summary_start = cmp::max(*cursor.start(), range.start) - cursor.start(); let summary_end = cmp::min(range.end - cursor.start(), fragment.len()); - summary += &fragment.text.slice(summary_start..summary_end).summary(); + summary += fragment.text.slice(summary_start..summary_end).summary(); cursor.next(); } if range.end > *cursor.start() { - summary += &cursor.summary::(&range.end, SeekBias::Right); + summary += cursor.summary::(&range.end, SeekBias::Right, &()); if let Some(fragment) = cursor.item() { let summary_start = cmp::max(*cursor.start(), range.start) - cursor.start(); let summary_end = cmp::min(range.end - cursor.start(), fragment.len()); - summary += &fragment.text.slice(summary_start..summary_end).summary(); + summary += fragment.text.slice(summary_start..summary_end).summary(); } } @@ -970,10 +979,10 @@ impl Buffer { let mut cursor = old_fragments.cursor::(); let mut new_fragments = - cursor.slice(&FragmentIdRef::new(&start_fragment_id), SeekBias::Left); + cursor.slice(&FragmentIdRef::new(&start_fragment_id), SeekBias::Left, &()); if start_offset == cursor.item().unwrap().end_offset() { - new_fragments.push(cursor.item().unwrap().clone()); + new_fragments.push(cursor.item().unwrap().clone(), &()); cursor.next(); } @@ -1012,30 +1021,33 @@ impl Buffer { None }; if let Some(fragment) = before_range { - new_fragments.push(fragment); + new_fragments.push(fragment, &()); } if let Some(fragment) = insertion { - new_fragments.push(fragment); + new_fragments.push(fragment, &()); } if let Some(mut fragment) = within_range { if fragment.was_visible(&version_in_range, &self.undo_map) { fragment.deletions.insert(local_timestamp); fragment.visible = false; } - new_fragments.push(fragment); + new_fragments.push(fragment, &()); } if let Some(fragment) = after_range { - new_fragments.push(fragment); + new_fragments.push(fragment, &()); } } else { if new_text.is_some() && lamport_timestamp > fragment.insertion.lamport_timestamp { - new_fragments.push(self.build_fragment_to_insert( - cursor.prev_item().as_ref().unwrap(), - Some(&fragment), - new_text.take().unwrap(), - local_timestamp, - lamport_timestamp, - )); + new_fragments.push( + self.build_fragment_to_insert( + cursor.prev_item().as_ref().unwrap(), + Some(&fragment), + new_text.take().unwrap(), + local_timestamp, + lamport_timestamp, + ), + &(), + ); } if fragment.id < end_fragment_id @@ -1044,23 +1056,26 @@ impl Buffer { fragment.deletions.insert(local_timestamp); fragment.visible = false; } - new_fragments.push(fragment); + new_fragments.push(fragment, &()); } cursor.next(); } if let Some(new_text) = new_text { - new_fragments.push(self.build_fragment_to_insert( - cursor.prev_item().as_ref().unwrap(), - None, - new_text, - local_timestamp, - lamport_timestamp, - )); + new_fragments.push( + self.build_fragment_to_insert( + cursor.prev_item().as_ref().unwrap(), + None, + new_text, + local_timestamp, + lamport_timestamp, + ), + &(), + ); } - new_fragments.push_tree(cursor.slice(&last_id_ref, SeekBias::Right)); + new_fragments.push_tree(cursor.slice(&last_id_ref, SeekBias::Right, &()), &()); self.fragments = new_fragments; self.local_clock.observe(local_timestamp); self.lamport_clock.observe(lamport_timestamp); @@ -1148,23 +1163,26 @@ impl Buffer { let mut insertion_splits = splits.cursor::<(), ()>().map(|s| &s.fragment_id).peekable(); let first_split_id = insertion_splits.next().unwrap(); - new_fragments = cursor.slice(&FragmentIdRef::new(first_split_id), SeekBias::Left); + new_fragments = cursor.slice(&FragmentIdRef::new(first_split_id), SeekBias::Left, &()); loop { let mut fragment = cursor.item().unwrap().clone(); fragment.visible = fragment.is_visible(&self.undo_map); fragment.max_undos.observe(undo.id); - new_fragments.push(fragment); + new_fragments.push(fragment, &()); cursor.next(); if let Some(split_id) = insertion_splits.next() { - new_fragments - .push_tree(cursor.slice(&FragmentIdRef::new(split_id), SeekBias::Left)); + new_fragments.push_tree( + cursor.slice(&FragmentIdRef::new(split_id), SeekBias::Left, &()), + &(), + ); } else { break; } } } else { - new_fragments = cursor.slice(&FragmentIdRef::new(&start_fragment_id), SeekBias::Left); + new_fragments = + cursor.slice(&FragmentIdRef::new(&start_fragment_id), SeekBias::Left, &()); while let Some(fragment) = cursor.item() { if fragment.id > end_fragment_id { break; @@ -1176,13 +1194,13 @@ impl Buffer { fragment.visible = fragment.is_visible(&self.undo_map); fragment.max_undos.observe(undo.id); } - new_fragments.push(fragment); + new_fragments.push(fragment, &()); cursor.next(); } } } - new_fragments.push_tree(cursor.suffix()); + new_fragments.push_tree(cursor.suffix(&()), &()); drop(cursor); self.fragments = new_fragments; @@ -1246,7 +1264,7 @@ impl Buffer { .get(&edit_id) .ok_or_else(|| anyhow!("invalid operation"))?; let mut cursor = split_tree.cursor::(); - cursor.seek(&offset, SeekBias::Left); + cursor.seek(&offset, SeekBias::Left, &()); Ok(cursor .item() .ok_or_else(|| anyhow!("invalid operation"))? @@ -1268,7 +1286,10 @@ impl Buffer { let old_fragments = self.fragments.clone(); let mut cursor = old_fragments.cursor::(); let mut new_fragments = SumTree::new(); - new_fragments.push_tree(cursor.slice(&cur_range.as_ref().unwrap().start, SeekBias::Right)); + new_fragments.push_tree( + cursor.slice(&cur_range.as_ref().unwrap().start, SeekBias::Right, &()), + &(), + ); let mut start_id = None; let mut start_offset = None; @@ -1290,7 +1311,8 @@ impl Buffer { .remove(&fragment.insertion.id) .unwrap(); let mut splits_cursor = old_split_tree.cursor::(); - let mut new_split_tree = splits_cursor.slice(&fragment.start_offset(), SeekBias::Right); + let mut new_split_tree = + splits_cursor.slice(&fragment.start_offset(), SeekBias::Right, &()); // Find all splices that start or end within the current fragment. Then, split the // fragment and reassemble it in both trees accounting for the deleted and the newly @@ -1303,11 +1325,14 @@ impl Buffer { prefix.id = FragmentId::between(&new_fragments.last().unwrap().id, &fragment.id); fragment.set_start_offset(prefix.end_offset()); - new_fragments.push(prefix.clone()); - new_split_tree.push(InsertionSplit { - extent: prefix.end_offset() - prefix.start_offset(), - fragment_id: prefix.id, - }); + new_fragments.push(prefix.clone(), &()); + new_split_tree.push( + InsertionSplit { + extent: prefix.end_offset() - prefix.start_offset(), + fragment_id: prefix.id, + }, + &(), + ); fragment_start = range.start; } @@ -1331,7 +1356,7 @@ impl Buffer { local_timestamp, lamport_timestamp, ); - new_fragments.push(new_fragment); + new_fragments.push(new_fragment, &()); } } @@ -1347,11 +1372,14 @@ impl Buffer { prefix.visible = false; } fragment.set_start_offset(prefix.end_offset()); - new_fragments.push(prefix.clone()); - new_split_tree.push(InsertionSplit { - extent: prefix.end_offset() - prefix.start_offset(), - fragment_id: prefix.id, - }); + new_fragments.push(prefix.clone(), &()); + new_split_tree.push( + InsertionSplit { + extent: prefix.end_offset() - prefix.start_offset(), + fragment_id: prefix.id, + }, + &(), + ); fragment_start = range.end; end_id = Some(fragment.insertion.id); end_offset = Some(fragment.start_offset()); @@ -1395,16 +1423,21 @@ impl Buffer { break; } } - new_split_tree.push(InsertionSplit { - extent: fragment.end_offset() - fragment.start_offset(), - fragment_id: fragment.id.clone(), - }); + new_split_tree.push( + InsertionSplit { + extent: fragment.end_offset() - fragment.start_offset(), + fragment_id: fragment.id.clone(), + }, + &(), + ); splits_cursor.next(); - new_split_tree - .push_tree(splits_cursor.slice(&old_split_tree.extent::(), SeekBias::Right)); + new_split_tree.push_tree( + splits_cursor.slice(&old_split_tree.extent::(), SeekBias::Right, &()), + &(), + ); self.insertion_splits .insert(fragment.insertion.id, new_split_tree); - new_fragments.push(fragment); + new_fragments.push(fragment, &()); // Scan forward until we find a fragment that is not fully contained by the current splice. cursor.next(); @@ -1420,7 +1453,7 @@ impl Buffer { new_fragment.deletions.insert(local_timestamp); new_fragment.visible = false; } - new_fragments.push(new_fragment); + new_fragments.push(new_fragment, &()); cursor.next(); if range.end == fragment_end { @@ -1462,7 +1495,8 @@ impl Buffer { // and push all the fragments in between into the new tree. if cur_range.as_ref().map_or(false, |r| r.start > fragment_end) { new_fragments.push_tree( - cursor.slice(&cur_range.as_ref().unwrap().start, SeekBias::Right), + cursor.slice(&cur_range.as_ref().unwrap().start, SeekBias::Right, &()), + &(), ); } } @@ -1494,11 +1528,13 @@ impl Buffer { local_timestamp, lamport_timestamp, ); - new_fragments.push(new_fragment); + new_fragments.push(new_fragment, &()); } } else { - new_fragments - .push_tree(cursor.slice(&old_fragments.extent::(), SeekBias::Right)); + new_fragments.push_tree( + cursor.slice(&old_fragments.extent::(), SeekBias::Right, &()), + &(), + ); } self.fragments = new_fragments; @@ -1556,32 +1592,43 @@ impl Buffer { .remove(&fragment.insertion.id) .unwrap(); let mut cursor = old_split_tree.cursor::(); - let mut new_split_tree = cursor.slice(&fragment.start_offset(), SeekBias::Right); + let mut new_split_tree = cursor.slice(&fragment.start_offset(), SeekBias::Right, &()); if let Some(ref fragment) = before_range { - new_split_tree.push(InsertionSplit { - extent: range.start - fragment.start_offset(), - fragment_id: fragment.id.clone(), - }); + new_split_tree.push( + InsertionSplit { + extent: range.start - fragment.start_offset(), + fragment_id: fragment.id.clone(), + }, + &(), + ); } if let Some(ref fragment) = within_range { - new_split_tree.push(InsertionSplit { - extent: range.end - range.start, - fragment_id: fragment.id.clone(), - }); + new_split_tree.push( + InsertionSplit { + extent: range.end - range.start, + fragment_id: fragment.id.clone(), + }, + &(), + ); } if let Some(ref fragment) = after_range { - new_split_tree.push(InsertionSplit { - extent: fragment.end_offset() - range.end, - fragment_id: fragment.id.clone(), - }); + new_split_tree.push( + InsertionSplit { + extent: fragment.end_offset() - range.end, + fragment_id: fragment.id.clone(), + }, + &(), + ); } cursor.next(); - new_split_tree - .push_tree(cursor.slice(&old_split_tree.extent::(), SeekBias::Right)); + new_split_tree.push_tree( + cursor.slice(&old_split_tree.extent::(), SeekBias::Right, &()), + &(), + ); self.insertion_splits .insert(fragment.insertion.id, new_split_tree); @@ -1606,10 +1653,13 @@ impl Buffer { ); let mut split_tree = SumTree::new(); - split_tree.push(InsertionSplit { - extent: text.len(), - fragment_id: new_fragment_id.clone(), - }); + split_tree.push( + InsertionSplit { + extent: text.len(), + fragment_id: new_fragment_id.clone(), + }, + &(), + ); self.insertion_splits.insert(local_timestamp, split_tree); Fragment::new( @@ -1658,7 +1708,7 @@ impl Buffer { }; let mut cursor = self.fragments.cursor::(); - cursor.seek(&offset, seek_bias); + cursor.seek(&offset, seek_bias, &()); let fragment = cursor.item().unwrap(); let offset_in_fragment = offset - cursor.start(); let offset_in_insertion = fragment.start_offset() + offset_in_fragment; @@ -1690,7 +1740,7 @@ impl Buffer { .get(&insertion_id) .ok_or_else(|| anyhow!("split does not exist for insertion id"))?; let mut splits_cursor = splits.cursor::(); - splits_cursor.seek(offset, seek_bias); + splits_cursor.seek(offset, seek_bias, &()); splits_cursor .item() .ok_or_else(|| anyhow!("split offset is out of range")) @@ -1718,13 +1768,13 @@ impl Buffer { .get(&insertion_id) .ok_or_else(|| anyhow!("split does not exist for insertion id"))?; let mut splits_cursor = splits.cursor::(); - splits_cursor.seek(offset, seek_bias); + splits_cursor.seek(offset, seek_bias, &()); let split = splits_cursor .item() .ok_or_else(|| anyhow!("split offset is out of range"))?; let mut fragments_cursor = self.fragments.cursor::(); - fragments_cursor.seek(&FragmentIdRef::new(&split.fragment_id), SeekBias::Left); + fragments_cursor.seek(&FragmentIdRef::new(&split.fragment_id), SeekBias::Left, &()); let fragment = fragments_cursor .item() .ok_or_else(|| anyhow!("fragment id does not exist"))?; @@ -1744,7 +1794,7 @@ impl Buffer { #[allow(dead_code)] pub fn point_for_offset(&self, offset: usize) -> Result { let mut fragments_cursor = self.fragments.cursor::(); - fragments_cursor.seek(&offset, SeekBias::Left); + fragments_cursor.seek(&offset, SeekBias::Left, &()); fragments_cursor .item() .ok_or_else(|| anyhow!("offset is out of range")) @@ -1810,7 +1860,7 @@ impl<'a> sum_tree::Dimension<'a, FragmentSummary> for Point { impl<'a> CharIter<'a> { fn new(fragments: &'a SumTree, offset: usize) -> Self { let mut fragments_cursor = fragments.cursor::(); - fragments_cursor.seek(&offset, SeekBias::Right); + fragments_cursor.seek(&offset, SeekBias::Right, &()); let fragment_chars = fragments_cursor.item().map_or("".chars(), |fragment| { let offset_in_fragment = offset - fragments_cursor.start(); fragment.text[offset_in_fragment..].chars() @@ -1847,7 +1897,7 @@ impl<'a> Iterator for CharIter<'a> { impl<'a> FragmentIter<'a> { fn new(fragments: &'a SumTree) -> Self { let mut cursor = fragments.cursor::(); - cursor.seek(&0, SeekBias::Right); + cursor.seek(&0, SeekBias::Right, &()); Self { cursor, started: false, @@ -2140,8 +2190,10 @@ impl sum_tree::Item for Fragment { } } -impl<'a> AddAssign<&'a FragmentSummary> for FragmentSummary { - fn add_assign(&mut self, other: &Self) { +impl sum_tree::Summary for FragmentSummary { + type Context = (); + + fn add_summary(&mut self, other: &Self, _: &()) { self.text_summary += &other.text_summary; debug_assert!(self.max_fragment_id <= other.max_fragment_id); self.max_fragment_id = other.max_fragment_id.clone(); @@ -2204,8 +2256,10 @@ impl sum_tree::Item for InsertionSplit { } } -impl<'a> AddAssign<&'a InsertionSplitSummary> for InsertionSplitSummary { - fn add_assign(&mut self, other: &Self) { +impl sum_tree::Summary for InsertionSplitSummary { + type Context = (); + + fn add_summary(&mut self, other: &Self, _: &()) { self.extent += other.extent; } } @@ -2262,7 +2316,7 @@ pub trait ToOffset { impl ToOffset for Point { fn to_offset(&self, buffer: &Buffer) -> Result { let mut fragments_cursor = buffer.fragments.cursor::(); - fragments_cursor.seek(self, SeekBias::Left); + fragments_cursor.seek(self, SeekBias::Left, &()); fragments_cursor .item() .ok_or_else(|| anyhow!("point is out of range")) @@ -2306,7 +2360,7 @@ impl ToPoint for Anchor { impl ToPoint for usize { fn to_point(&self, buffer: &Buffer) -> Result { let mut fragments_cursor = buffer.fragments.cursor::(); - fragments_cursor.seek(&self, SeekBias::Left); + fragments_cursor.seek(&self, SeekBias::Left, &()); fragments_cursor .item() .ok_or_else(|| anyhow!("offset is out of range")) diff --git a/zed/src/editor/buffer/selection.rs b/zed/src/editor/buffer/selection.rs index 431f8224c4..8f436a04e7 100644 --- a/zed/src/editor/buffer/selection.rs +++ b/zed/src/editor/buffer/selection.rs @@ -75,6 +75,7 @@ impl Selection { pub fn buffer_rows_for_display_rows( &self, + include_end_if_at_line_start: bool, map: &DisplayMap, ctx: &AppContext, ) -> (Range, Range) { @@ -84,7 +85,8 @@ impl Selection { .unwrap(); let mut display_end = self.end.to_display_point(map, ctx).unwrap(); - if display_end.row() != map.max_point(ctx).row() + if !include_end_if_at_line_start + && display_end.row() != map.max_point(ctx).row() && display_start.row() != display_end.row() && display_end.column() == 0 { diff --git a/zed/src/editor/buffer/text.rs b/zed/src/editor/buffer/text.rs index 0fff5c81d1..03b8b52854 100644 --- a/zed/src/editor/buffer/text.rs +++ b/zed/src/editor/buffer/text.rs @@ -58,6 +58,14 @@ pub struct TextSummary { pub rightmost_point: Point, } +impl sum_tree::Summary for TextSummary { + type Context = (); + + fn add_summary(&mut self, other: &Self, _: &()) { + *self += other; + } +} + impl<'a> std::ops::AddAssign<&'a Self> for TextSummary { fn add_assign(&mut self, other: &'a Self) { let joined_line_len = self.lines.column + other.first_line_len; @@ -85,8 +93,8 @@ impl std::ops::AddAssign for TextSummary { } impl<'a> sum_tree::Dimension<'a, TextSummary> for TextSummary { - fn add_summary(&mut self, summary: &TextSummary) { - *self += summary; + fn add_summary(&mut self, other: &TextSummary) { + *self += other; } } @@ -157,7 +165,7 @@ impl From> for Text { } let mut tree = SumTree::new(); - tree.extend(runs); + tree.extend(runs, &()); Text { text, runs: tree, @@ -231,13 +239,14 @@ impl Text { pub fn line_len(&self, row: u32) -> u32 { let mut cursor = self.runs.cursor::(); - cursor.seek(&self.range.start, SeekBias::Right); + cursor.seek(&self.range.start, SeekBias::Right, &()); let absolute_row = cursor.start().row + row; let mut cursor = self.runs.cursor::(); - cursor.seek(&Point::new(absolute_row, 0), SeekBias::Right); + cursor.seek(&Point::new(absolute_row, 0), SeekBias::Right, &()); let prefix_len = self.range.start.saturating_sub(*cursor.start()); - let line_len = cursor.summary::(&Point::new(absolute_row + 1, 0), SeekBias::Left); + let line_len = + cursor.summary::(&Point::new(absolute_row + 1, 0), SeekBias::Left, &()); let suffix_len = cursor.start().saturating_sub(self.range.end); line_len @@ -262,14 +271,15 @@ impl Text { candidates.push(Point::new(0, self.line_len(0))); if lines.row > 1 { let mut cursor = self.runs.cursor::(); - cursor.seek(&self.range.start, SeekBias::Right); + cursor.seek(&self.range.start, SeekBias::Right, &()); let absolute_start_row = cursor.start().row; let mut cursor = self.runs.cursor::(); - cursor.seek(&Point::new(absolute_start_row + 1, 0), SeekBias::Right); + cursor.seek(&Point::new(absolute_start_row + 1, 0), SeekBias::Right, &()); let summary = cursor.summary::( &Point::new(absolute_start_row + lines.row, 0), SeekBias::Left, + &(), ); candidates.push(Point::new(1, 0) + &summary.rightmost_point); @@ -287,7 +297,7 @@ impl Text { pub fn offset_for_point(&self, point: Point) -> usize { let mut cursor = self.runs.cursor::(); let abs_point = self.abs_point_for_offset(self.range.start) + &point; - cursor.seek(&abs_point, SeekBias::Right); + cursor.seek(&abs_point, SeekBias::Right, &()); let overshoot = abs_point - &cursor.start().lines; let abs_offset = cursor.start().chars + overshoot.column as usize; abs_offset - self.range.start @@ -307,14 +317,14 @@ impl Text { fn abs_point_for_offset(&self, offset: usize) -> Point { let mut cursor = self.runs.cursor::(); - cursor.seek(&offset, SeekBias::Right); + cursor.seek(&offset, SeekBias::Right, &()); let overshoot = (offset - cursor.start().chars) as u32; cursor.start().lines + &Point::new(0, overshoot) } fn abs_byte_offset_for_offset(&self, offset: usize) -> usize { let mut cursor = self.runs.cursor::(); - cursor.seek(&offset, SeekBias::Right); + cursor.seek(&offset, SeekBias::Right, &()); let overshoot = offset - cursor.start().chars; cursor.start().bytes + overshoot * cursor.item().map_or(0, |run| run.char_size()) as usize } diff --git a/zed/src/editor/buffer_view.rs b/zed/src/editor/buffer_view.rs index 6006763991..605744b37a 100644 --- a/zed/src/editor/buffer_view.rs +++ b/zed/src/editor/buffer_view.rs @@ -138,6 +138,12 @@ pub fn init(app: &mut MutableAppContext) { ), Binding::new("cmd-shift-down", "buffer:select_to_end", Some("BufferView")), Binding::new("cmd-a", "buffer:select_all", Some("BufferView")), + Binding::new("cmd-l", "buffer:select_line", Some("BufferView")), + Binding::new( + "cmd-shift-L", + "buffer:split_selection_into_lines", + Some("BufferView"), + ), Binding::new("pageup", "buffer:page_up", Some("BufferView")), Binding::new("pagedown", "buffer:page_down", Some("BufferView")), Binding::new("alt-cmd-[", "buffer:fold", Some("BufferView")), @@ -228,6 +234,11 @@ pub fn init(app: &mut MutableAppContext) { ); app.add_action("buffer:select_to_end", BufferView::select_to_end); app.add_action("buffer:select_all", BufferView::select_all); + app.add_action("buffer:select_line", BufferView::select_line); + app.add_action( + "buffer:split_selection_into_lines", + BufferView::split_selection_into_lines, + ); app.add_action("buffer:page_up", BufferView::page_up); app.add_action("buffer:page_down", BufferView::page_down); app.add_action("buffer:fold", BufferView::fold); @@ -704,7 +715,8 @@ impl BufferView { let mut selections = self.selections(app).iter().peekable(); while let Some(selection) = selections.next() { - let (mut rows, _) = selection.buffer_rows_for_display_rows(&self.display_map, app); + let (mut rows, _) = + selection.buffer_rows_for_display_rows(false, &self.display_map, app); let goal_display_column = selection .head() .to_display_point(&self.display_map, app) @@ -714,7 +726,7 @@ impl BufferView { // Accumulate contiguous regions of rows that we want to delete. while let Some(next_selection) = selections.peek() { let (next_rows, _) = - next_selection.buffer_rows_for_display_rows(&self.display_map, app); + next_selection.buffer_rows_for_display_rows(false, &self.display_map, app); if next_rows.start <= rows.end { rows.end = next_rows.end; selections.next().unwrap(); @@ -795,10 +807,11 @@ impl BufferView { let mut selections_iter = selections.iter_mut().peekable(); while let Some(selection) = selections_iter.next() { // Avoid duplicating the same lines twice. - let (mut rows, _) = selection.buffer_rows_for_display_rows(&self.display_map, app); + let (mut rows, _) = + selection.buffer_rows_for_display_rows(false, &self.display_map, app); while let Some(next_selection) = selections_iter.peek() { let (next_rows, _) = - next_selection.buffer_rows_for_display_rows(&self.display_map, app); + next_selection.buffer_rows_for_display_rows(false, &self.display_map, app); if next_rows.start <= rows.end - 1 { rows.end = next_rows.end; selections_iter.next().unwrap(); @@ -852,10 +865,10 @@ impl BufferView { // Accumulate contiguous regions of rows that we want to move. contiguous_selections.push(selection.range(buffer)); let (mut buffer_rows, mut display_rows) = - selection.buffer_rows_for_display_rows(&self.display_map, app); + selection.buffer_rows_for_display_rows(false, &self.display_map, app); while let Some(next_selection) = selections.peek() { let (next_buffer_rows, next_display_rows) = - next_selection.buffer_rows_for_display_rows(&self.display_map, app); + next_selection.buffer_rows_for_display_rows(false, &self.display_map, app); if next_buffer_rows.start <= buffer_rows.end { buffer_rows.end = next_buffer_rows.end; display_rows.end = next_display_rows.end; @@ -942,10 +955,10 @@ impl BufferView { // Accumulate contiguous regions of rows that we want to move. contiguous_selections.push(selection.range(buffer)); let (mut buffer_rows, mut display_rows) = - selection.buffer_rows_for_display_rows(&self.display_map, app); + selection.buffer_rows_for_display_rows(false, &self.display_map, app); while let Some(next_selection) = selections.peek() { let (next_buffer_rows, next_display_rows) = - next_selection.buffer_rows_for_display_rows(&self.display_map, app); + next_selection.buffer_rows_for_display_rows(false, &self.display_map, app); if next_buffer_rows.start <= buffer_rows.end { buffer_rows.end = next_buffer_rows.end; display_rows.end = next_display_rows.end; @@ -1654,6 +1667,63 @@ impl BufferView { self.update_selections(vec![selection], false, ctx); } + pub fn select_line(&mut self, _: &(), ctx: &mut ViewContext) { + let app = ctx.as_ref(); + let buffer = self.buffer.read(app); + let mut selections = self.selections(app).to_vec(); + let max_point = buffer.max_point(); + for selection in &mut selections { + let (rows, _) = selection.buffer_rows_for_display_rows(true, &self.display_map, app); + selection.start = buffer.anchor_before(Point::new(rows.start, 0)).unwrap(); + selection.end = buffer + .anchor_before(cmp::min(max_point, Point::new(rows.end, 0))) + .unwrap(); + selection.reversed = false; + } + self.update_selections(selections, true, ctx); + } + + pub fn split_selection_into_lines(&mut self, _: &(), ctx: &mut ViewContext) { + use super::RangeExt; + + let app = ctx.as_ref(); + let buffer = self.buffer.read(app); + + let mut to_unfold = Vec::new(); + let mut new_selections = Vec::new(); + for selection in self.selections(app) { + let range = selection.range(buffer).sorted(); + if range.start.row != range.end.row { + new_selections.push(Selection { + start: selection.start.clone(), + end: selection.start.clone(), + reversed: false, + goal_column: None, + }); + } + for row in range.start.row + 1..range.end.row { + let cursor = buffer + .anchor_before(Point::new(row, buffer.line_len(row).unwrap())) + .unwrap(); + new_selections.push(Selection { + start: cursor.clone(), + end: cursor, + reversed: false, + goal_column: None, + }); + } + new_selections.push(Selection { + start: selection.end.clone(), + end: selection.end.clone(), + reversed: false, + goal_column: None, + }); + to_unfold.push(range); + } + self.unfold_ranges(to_unfold, ctx); + self.update_selections(new_selections, true, ctx); + } + pub fn selections_in_range<'a>( &'a self, range: Range, @@ -1874,9 +1944,8 @@ impl BufferView { .selections(ctx.as_ref()) .iter() .map(|s| s.range(buffer).sorted()) - .collect::>(); - self.display_map.fold(ranges, ctx.as_ref()).unwrap(); - ctx.notify(); + .collect(); + self.fold_ranges(ranges, ctx); } fn fold_ranges(&mut self, ranges: Vec>, ctx: &mut ViewContext) { @@ -3292,6 +3361,124 @@ mod tests { }); } + #[test] + fn test_select_line() { + App::test((), |app| { + let settings = settings::channel(&app.font_cache()).unwrap().1; + let buffer = app.add_model(|ctx| Buffer::new(0, sample_text(6, 5), ctx)); + let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx)); + view.update(app, |view, ctx| { + view.select_display_ranges( + &[ + DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1), + DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2), + DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0), + DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2), + ], + ctx, + ) + .unwrap(); + view.select_line(&(), ctx); + }); + assert_eq!( + view.read(app).selection_ranges(app.as_ref()), + vec![ + DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0), + DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0), + ] + ); + + view.update(app, |view, ctx| view.select_line(&(), ctx)); + assert_eq!( + view.read(app).selection_ranges(app.as_ref()), + vec![ + DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0), + DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5), + ] + ); + + view.update(app, |view, ctx| view.select_line(&(), ctx)); + assert_eq!( + view.read(app).selection_ranges(app.as_ref()), + vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)] + ); + }); + } + + #[test] + fn test_split_selection_into_lines() { + App::test((), |app| { + let settings = settings::channel(&app.font_cache()).unwrap().1; + let buffer = app.add_model(|ctx| Buffer::new(0, sample_text(9, 5), ctx)); + let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx)); + view.update(app, |view, ctx| { + view.fold_ranges( + vec![ + Point::new(0, 2)..Point::new(1, 2), + Point::new(2, 3)..Point::new(4, 1), + Point::new(7, 0)..Point::new(8, 4), + ], + ctx, + ); + view.select_display_ranges( + &[ + DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1), + DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2), + DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0), + DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2), + ], + ctx, + ) + .unwrap(); + }); + assert_eq!( + view.read(app).text(app.as_ref()), + "aa…bbb\nccc…eeee\nfffff\nggggg\n…i" + ); + + view.update(app, |view, ctx| view.split_selection_into_lines(&(), ctx)); + assert_eq!( + view.read(app).text(app.as_ref()), + "aa…bbb\nccc…eeee\nfffff\nggggg\n…i" + ); + assert_eq!( + view.read(app).selection_ranges(app.as_ref()), + [ + DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1), + DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2), + DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0), + DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2) + ] + ); + + view.update(app, |view, ctx| { + view.select_display_ranges( + &[DisplayPoint::new(4, 0)..DisplayPoint::new(0, 1)], + ctx, + ) + .unwrap(); + view.split_selection_into_lines(&(), ctx); + }); + assert_eq!( + view.read(app).text(app.as_ref()), + "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\n…i" + ); + assert_eq!( + view.read(app).selection_ranges(app.as_ref()), + [ + DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1), + DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5), + DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5), + DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5), + DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5), + DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5), + DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5), + DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0) + ] + ); + }); + } + impl BufferView { fn selection_ranges(&self, app: &AppContext) -> Vec> { self.selections_in_range(DisplayPoint::zero()..self.max_point(app), app) diff --git a/zed/src/editor/display_map/fold_map.rs b/zed/src/editor/display_map/fold_map.rs index 8240954345..e7f538c686 100644 --- a/zed/src/editor/display_map/fold_map.rs +++ b/zed/src/editor/display_map/fold_map.rs @@ -1,10 +1,10 @@ use super::{ - buffer, Anchor, AnchorRangeExt, Buffer, DisplayPoint, Edit, Point, TextSummary, ToOffset, + buffer::{self, AnchorRangeExt}, + Anchor, Buffer, DisplayPoint, Edit, Point, TextSummary, ToOffset, }; use crate::{ - sum_tree::{self, Cursor, SumTree}, + sum_tree::{self, Cursor, FilterCursor, SeekBias, SumTree}, time, - util::find_insertion_index, }; use anyhow::{anyhow, Result}; use gpui::{AppContext, ModelHandle}; @@ -14,12 +14,11 @@ use std::{ iter::Take, ops::Range, }; -use sum_tree::{Dimension, SeekBias}; pub struct FoldMap { buffer: ModelHandle, transforms: Mutex>, - folds: Vec>, + folds: SumTree, last_sync: Mutex, } @@ -29,14 +28,17 @@ impl FoldMap { let text_summary = buffer.text_summary(); Self { buffer: buffer_handle, - folds: Vec::new(), - transforms: Mutex::new(SumTree::from_item(Transform { - summary: TransformSummary { - buffer: text_summary.clone(), - display: text_summary, + folds: Default::default(), + transforms: Mutex::new(SumTree::from_item( + Transform { + summary: TransformSummary { + buffer: text_summary.clone(), + display: text_summary, + }, + display_text: None, }, - display_text: None, - })), + &(), + )), last_sync: Mutex::new(buffer.version()), } } @@ -76,17 +78,12 @@ impl FoldMap { pub fn folds_in_range<'a, T>( &'a self, range: Range, - app: &'a AppContext, + ctx: &'a AppContext, ) -> Result>> where T: ToOffset, { - let buffer = self.buffer.read(app); - let range = buffer.anchor_before(range.start)?..buffer.anchor_before(range.end)?; - Ok(self.folds.iter().filter(move |fold| { - range.start.cmp(&fold.end, buffer).unwrap() == Ordering::Less - && range.end.cmp(&fold.start, buffer).unwrap() == Ordering::Greater - })) + Ok(self.intersecting_folds(range, ctx)?.map(|f| &f.0)) } pub fn fold( @@ -97,19 +94,22 @@ impl FoldMap { let _ = self.sync(ctx); let mut edits = Vec::new(); + let mut folds = Vec::new(); let buffer = self.buffer.read(ctx); for range in ranges.into_iter() { - let start = range.start.to_offset(buffer)?; - let end = range.end.to_offset(buffer)?; - edits.push(Edit { - old_range: start..end, - new_range: start..end, - }); - - let fold = buffer.anchor_after(start)?..buffer.anchor_before(end)?; - let ix = find_insertion_index(&self.folds, |probe| probe.cmp(&fold, buffer))?; - self.folds.insert(ix, fold); + let range = range.start.to_offset(buffer)?..range.end.to_offset(buffer)?; + if range.start != range.end { + let fold = + Fold(buffer.anchor_after(range.start)?..buffer.anchor_before(range.end)?); + folds.push(fold); + edits.push(Edit { + old_range: range.clone(), + new_range: range.clone(), + }); + } } + + folds.sort_unstable_by(|a, b| sum_tree::SeekDimension::cmp(a, b, buffer)); edits.sort_unstable_by(|a, b| { a.old_range .start @@ -117,6 +117,16 @@ impl FoldMap { .then_with(|| b.old_range.end.cmp(&a.old_range.end)) }); + self.folds = { + let mut new_tree = SumTree::new(); + let mut cursor = self.folds.cursor::<_, ()>(); + for fold in folds { + new_tree.push_tree(cursor.slice(&fold, SeekBias::Right, buffer), buffer); + new_tree.push(fold, buffer); + } + new_tree.push_tree(cursor.suffix(buffer), buffer); + new_tree + }; self.apply_edits(edits, ctx); Ok(()) } @@ -131,36 +141,66 @@ impl FoldMap { let buffer = self.buffer.read(ctx); let mut edits = Vec::new(); + let mut fold_ixs_to_delete = Vec::new(); for range in ranges.into_iter() { - let start = buffer.anchor_before(range.start.to_offset(buffer)?)?; - let end = buffer.anchor_after(range.end.to_offset(buffer)?)?; - - // Remove intersecting folds and add their ranges to edits that are passed to apply_edits - self.folds.retain(|fold| { - if fold.start.cmp(&end, buffer).unwrap() > Ordering::Equal - || fold.end.cmp(&start, buffer).unwrap() < Ordering::Equal - { - true - } else { - let offset_range = - fold.start.to_offset(buffer).unwrap()..fold.end.to_offset(buffer).unwrap(); - edits.push(Edit { - old_range: offset_range.clone(), - new_range: offset_range, - }); - false - } - }); + // Remove intersecting folds and add their ranges to edits that are passed to apply_edits. + let mut folds_cursor = self.intersecting_folds(range, ctx)?; + while let Some(fold) = folds_cursor.item() { + let offset_range = + fold.0.start.to_offset(buffer).unwrap()..fold.0.end.to_offset(buffer).unwrap(); + edits.push(Edit { + old_range: offset_range.clone(), + new_range: offset_range, + }); + fold_ixs_to_delete.push(*folds_cursor.start()); + folds_cursor.next(); + } } + fold_ixs_to_delete.sort_unstable(); + fold_ixs_to_delete.dedup(); + edits.sort_unstable_by(|a, b| { + a.old_range + .start + .cmp(&b.old_range.start) + .then_with(|| b.old_range.end.cmp(&a.old_range.end)) + }); + + self.folds = { + let mut cursor = self.folds.cursor::<_, ()>(); + let mut folds = SumTree::new(); + for fold_ix in fold_ixs_to_delete { + folds.push_tree(cursor.slice(&fold_ix, SeekBias::Right, buffer), buffer); + cursor.next(); + } + folds.push_tree(cursor.suffix(buffer), buffer); + folds + }; self.apply_edits(edits, ctx); Ok(()) } + fn intersecting_folds<'a, T>( + &self, + range: Range, + ctx: &'a AppContext, + ) -> Result bool, Fold, usize>> + where + T: ToOffset, + { + let buffer = self.buffer.read(ctx); + let start = buffer.anchor_before(range.start.to_offset(buffer)?)?; + let end = buffer.anchor_after(range.end.to_offset(buffer)?)?; + Ok(self.folds.filter::<_, usize>(move |summary| { + start.cmp(&summary.max_end, buffer).unwrap() == Ordering::Less + && end.cmp(&summary.min_start, buffer).unwrap() == Ordering::Greater + })) + } + pub fn is_line_folded(&self, display_row: u32, ctx: &AppContext) -> bool { let transforms = self.sync(ctx); let mut cursor = transforms.cursor::(); - cursor.seek(&DisplayPoint::new(display_row, 0), SeekBias::Right); + cursor.seek(&DisplayPoint::new(display_row, 0), SeekBias::Right, &()); while let Some(transform) = cursor.item() { if transform.display_text.is_some() { return true; @@ -177,7 +217,7 @@ impl FoldMap { pub fn to_buffer_offset(&self, point: DisplayPoint, ctx: &AppContext) -> Result { let transforms = self.sync(ctx); let mut cursor = transforms.cursor::(); - cursor.seek(&point, SeekBias::Right); + cursor.seek(&point, SeekBias::Right, &()); let overshoot = point.0 - cursor.start().display.lines; (cursor.start().buffer.lines + overshoot).to_offset(self.buffer.read(ctx)) } @@ -193,7 +233,7 @@ impl FoldMap { pub fn to_buffer_point(&self, display_point: DisplayPoint, ctx: &AppContext) -> Point { let transforms = self.sync(ctx); let mut cursor = transforms.cursor::(); - cursor.seek(&display_point, SeekBias::Right); + cursor.seek(&display_point, SeekBias::Right, &()); let overshoot = display_point.0 - cursor.start().display.lines; cursor.start().buffer.lines + overshoot } @@ -201,7 +241,7 @@ impl FoldMap { pub fn to_display_point(&self, point: Point, ctx: &AppContext) -> DisplayPoint { let transforms = self.sync(ctx); let mut cursor = transforms.cursor::(); - cursor.seek(&point, SeekBias::Right); + cursor.seek(&point, SeekBias::Right, &()); let overshoot = point - cursor.start().buffer.lines; DisplayPoint(cmp::min( cursor.start().display.lines + overshoot, @@ -226,14 +266,17 @@ impl FoldMap { let mut new_transforms = SumTree::new(); let mut transforms = self.transforms.lock(); let mut cursor = transforms.cursor::(); - cursor.seek(&0, SeekBias::Right); + cursor.seek(&0, SeekBias::Right, &()); while let Some(mut edit) = edits.next() { - new_transforms.push_tree(cursor.slice(&edit.old_range.start, SeekBias::Left)); + new_transforms.push_tree( + cursor.slice(&edit.old_range.start, SeekBias::Left, &()), + &(), + ); edit.new_range.start -= edit.old_range.start - cursor.start(); edit.old_range.start = *cursor.start(); - cursor.seek(&edit.old_range.end, SeekBias::Right); + cursor.seek(&edit.old_range.end, SeekBias::Right, &()); cursor.next(); let mut delta = edit.delta(); @@ -250,7 +293,7 @@ impl FoldMap { if next_edit.old_range.end >= edit.old_range.end { edit.old_range.end = next_edit.old_range.end; - cursor.seek(&edit.old_range.end, SeekBias::Right); + cursor.seek(&edit.old_range.end, SeekBias::Right, &()); cursor.next(); } } else { @@ -262,14 +305,10 @@ impl FoldMap { ((edit.new_range.start + edit.old_extent()) as isize + delta) as usize; let anchor = buffer.anchor_before(edit.new_range.start).unwrap(); - let folds_start = - find_insertion_index(&self.folds, |probe| probe.start.cmp(&anchor, buffer)) - .unwrap(); - let mut folds = self.folds[folds_start..] - .iter() - .map(|fold| { - fold.start.to_offset(buffer).unwrap()..fold.end.to_offset(buffer).unwrap() - }) + let mut folds_cursor = self.folds.cursor::<_, ()>(); + folds_cursor.seek(&Fold(anchor..Anchor::End), SeekBias::Left, buffer); + let mut folds = folds_cursor + .map(|f| f.0.start.to_offset(buffer).unwrap()..f.0.end.to_offset(buffer).unwrap()) .peekable(); while folds @@ -293,29 +332,35 @@ impl FoldMap { if fold.start > sum.buffer.chars { let text_summary = buffer.text_summary_for_range(sum.buffer.chars..fold.start); - new_transforms.push(Transform { - summary: TransformSummary { - display: text_summary.clone(), - buffer: text_summary, + new_transforms.push( + Transform { + summary: TransformSummary { + display: text_summary.clone(), + buffer: text_summary, + }, + display_text: None, }, - display_text: None, - }); + &(), + ); } if fold.end > fold.start { - new_transforms.push(Transform { - summary: TransformSummary { - display: TextSummary { - chars: 1, - bytes: '…'.len_utf8(), - lines: Point::new(0, 1), - first_line_len: 1, - rightmost_point: Point::new(0, 1), + new_transforms.push( + Transform { + summary: TransformSummary { + display: TextSummary { + chars: 1, + bytes: '…'.len_utf8(), + lines: Point::new(0, 1), + first_line_len: 1, + rightmost_point: Point::new(0, 1), + }, + buffer: buffer.text_summary_for_range(fold.start..fold.end), }, - buffer: buffer.text_summary_for_range(fold.start..fold.end), + display_text: Some('…'), }, - display_text: Some('…'), - }); + &(), + ); } } @@ -323,26 +368,32 @@ impl FoldMap { if sum.buffer.chars < edit.new_range.end { let text_summary = buffer.text_summary_for_range(sum.buffer.chars..edit.new_range.end); - new_transforms.push(Transform { + new_transforms.push( + Transform { + summary: TransformSummary { + display: text_summary.clone(), + buffer: text_summary, + }, + display_text: None, + }, + &(), + ); + } + } + + new_transforms.push_tree(cursor.suffix(&()), &()); + if new_transforms.is_empty() { + let text_summary = buffer.text_summary(); + new_transforms.push( + Transform { summary: TransformSummary { display: text_summary.clone(), buffer: text_summary, }, display_text: None, - }); - } - } - - new_transforms.push_tree(cursor.suffix()); - if new_transforms.is_empty() { - let text_summary = buffer.text_summary(); - new_transforms.push(Transform { - summary: TransformSummary { - display: text_summary.clone(), - buffer: text_summary, }, - display_text: None, - }); + &(), + ); } drop(cursor); @@ -363,7 +414,7 @@ impl FoldMapSnapshot { let display_point = Point::new(start_row, 0); let mut cursor = self.transforms.cursor(); - cursor.seek(&DisplayPoint(display_point), SeekBias::Left); + cursor.seek(&DisplayPoint(display_point), SeekBias::Left, &()); Ok(BufferRows { display_point, @@ -374,7 +425,7 @@ impl FoldMapSnapshot { pub fn chars_at<'a>(&'a self, point: DisplayPoint, ctx: &'a AppContext) -> Result> { let offset = self.to_display_offset(point, ctx)?; let mut cursor = self.transforms.cursor(); - cursor.seek(&offset, SeekBias::Right); + cursor.seek(&offset, SeekBias::Right, &()); Ok(Chars { cursor, offset: offset.0, @@ -385,7 +436,7 @@ impl FoldMapSnapshot { fn to_display_offset(&self, point: DisplayPoint, ctx: &AppContext) -> Result { let mut cursor = self.transforms.cursor::(); - cursor.seek(&point, SeekBias::Right); + cursor.seek(&point, SeekBias::Right, &()); let overshoot = point.0 - cursor.start().display.lines; let mut offset = cursor.start().display.chars; if !overshoot.is_zero() { @@ -421,16 +472,106 @@ impl sum_tree::Item for Transform { } } -impl<'a> std::ops::AddAssign<&'a Self> for TransformSummary { - fn add_assign(&mut self, other: &'a Self) { +impl sum_tree::Summary for TransformSummary { + type Context = (); + + fn add_summary(&mut self, other: &Self, _: &()) { self.buffer += &other.buffer; self.display += &other.display; } } -impl<'a> Dimension<'a, TransformSummary> for TransformSummary { +impl<'a> sum_tree::Dimension<'a, TransformSummary> for TransformSummary { fn add_summary(&mut self, summary: &'a TransformSummary) { - *self += summary; + sum_tree::Summary::add_summary(self, summary, &()); + } +} + +#[derive(Clone, Debug)] +struct Fold(Range); + +impl Default for Fold { + fn default() -> Self { + Self(Anchor::Start..Anchor::End) + } +} + +impl sum_tree::Item for Fold { + type Summary = FoldSummary; + + fn summary(&self) -> Self::Summary { + FoldSummary { + start: self.0.start.clone(), + end: self.0.end.clone(), + min_start: self.0.start.clone(), + max_end: self.0.end.clone(), + count: 1, + } + } +} + +#[derive(Clone, Debug)] +struct FoldSummary { + start: Anchor, + end: Anchor, + min_start: Anchor, + max_end: Anchor, + count: usize, +} + +impl Default for FoldSummary { + fn default() -> Self { + Self { + start: Anchor::Start, + end: Anchor::End, + min_start: Anchor::End, + max_end: Anchor::Start, + count: 0, + } + } +} + +impl sum_tree::Summary for FoldSummary { + type Context = Buffer; + + fn add_summary(&mut self, other: &Self, buffer: &Buffer) { + if other.min_start.cmp(&self.min_start, buffer).unwrap() == Ordering::Less { + self.min_start = other.min_start.clone(); + } + if other.max_end.cmp(&self.max_end, buffer).unwrap() == Ordering::Greater { + self.max_end = other.max_end.clone(); + } + + #[cfg(debug_assertions)] + { + let start_comparison = self.start.cmp(&other.start, buffer).unwrap(); + assert!(start_comparison <= Ordering::Equal); + if start_comparison == Ordering::Equal { + assert!(self.end.cmp(&other.end, buffer).unwrap() >= Ordering::Equal); + } + } + self.start = other.start.clone(); + self.end = other.end.clone(); + self.count += other.count; + } +} + +impl<'a> sum_tree::Dimension<'a, FoldSummary> for Fold { + fn add_summary(&mut self, summary: &'a FoldSummary) { + self.0.start = summary.start.clone(); + self.0.end = summary.end.clone(); + } +} + +impl<'a> sum_tree::SeekDimension<'a, FoldSummary> for Fold { + fn cmp(&self, other: &Self, buffer: &Buffer) -> Ordering { + self.0.cmp(&other.0, buffer).unwrap() + } +} + +impl<'a> sum_tree::Dimension<'a, FoldSummary> for usize { + fn add_summary(&mut self, summary: &'a FoldSummary) { + *self += summary.count; } } @@ -498,7 +639,7 @@ impl<'a> Iterator for Chars<'a> { } } -impl<'a> Dimension<'a, TransformSummary> for DisplayPoint { +impl<'a> sum_tree::Dimension<'a, TransformSummary> for DisplayPoint { fn add_summary(&mut self, summary: &'a TransformSummary) { self.0 += &summary.display.lines; } @@ -507,19 +648,19 @@ impl<'a> Dimension<'a, TransformSummary> for DisplayPoint { #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)] pub struct DisplayOffset(usize); -impl<'a> Dimension<'a, TransformSummary> for DisplayOffset { +impl<'a> sum_tree::Dimension<'a, TransformSummary> for DisplayOffset { fn add_summary(&mut self, summary: &'a TransformSummary) { self.0 += &summary.display.chars; } } -impl<'a> Dimension<'a, TransformSummary> for Point { +impl<'a> sum_tree::Dimension<'a, TransformSummary> for Point { fn add_summary(&mut self, summary: &'a TransformSummary) { *self += &summary.buffer.lines; } } -impl<'a> Dimension<'a, TransformSummary> for usize { +impl<'a> sum_tree::Dimension<'a, TransformSummary> for usize { fn add_summary(&mut self, summary: &'a TransformSummary) { *self += &summary.buffer.chars; } @@ -571,7 +712,7 @@ mod tests { }); assert_eq!(map.text(app.as_ref()), "123a…c123456eee"); - map.unfold(Some(Point::new(0, 4)..Point::new(0, 4)), app.as_ref()) + map.unfold(Some(Point::new(0, 4)..Point::new(0, 5)), app.as_ref()) .unwrap(); assert_eq!(map.text(app.as_ref()), "123aaaaa\nbbbbbb\nccc123456eee"); }); @@ -719,7 +860,7 @@ mod tests { }; for seed in seed_range { - println!("{:?}", seed); + dbg!(seed); let mut rng = StdRng::seed_from_u64(seed); App::test((), |app| { @@ -732,26 +873,38 @@ mod tests { for _ in 0..operations { log::info!("text: {:?}", buffer.read(app).text()); - if rng.gen() { - let buffer = buffer.read(app); - - let fold_count = rng.gen_range(1..=5); - let mut fold_ranges: Vec> = Vec::new(); - for _ in 0..fold_count { - let end = rng.gen_range(0..buffer.len() + 1); - let start = rng.gen_range(0..end + 1); - fold_ranges.push(start..end); + match rng.gen_range(0..=100) { + 0..=34 => { + let buffer = buffer.read(app); + let mut to_fold = Vec::new(); + for _ in 0..rng.gen_range(1..=5) { + let end = rng.gen_range(0..=buffer.len()); + let start = rng.gen_range(0..=end); + to_fold.push(start..end); + } + log::info!("folding {:?}", to_fold); + map.fold(to_fold, app.as_ref()).unwrap(); + } + 35..=59 if !map.folds.is_empty() => { + let buffer = buffer.read(app); + let mut to_unfold = Vec::new(); + for _ in 0..rng.gen_range(1..=3) { + let end = rng.gen_range(0..=buffer.len()); + let start = rng.gen_range(0..=end); + to_unfold.push(start..end); + } + log::info!("unfolding {:?}", to_unfold); + map.unfold(to_unfold, app.as_ref()).unwrap(); + } + _ => { + let edits = buffer.update(app, |buffer, ctx| { + let start_version = buffer.version.clone(); + let edit_count = rng.gen_range(1..=5); + buffer.randomly_edit(&mut rng, edit_count, Some(ctx)); + buffer.edits_since(start_version).collect::>() + }); + log::info!("editing {:?}", edits); } - log::info!("folding {:?}", fold_ranges); - map.fold(fold_ranges.clone(), app.as_ref()).unwrap(); - } else { - let edits = buffer.update(app, |buffer, ctx| { - let start_version = buffer.version.clone(); - let edit_count = rng.gen_range(1..=5); - buffer.randomly_edit(&mut rng, edit_count, Some(ctx)); - buffer.edits_since(start_version).collect::>() - }); - log::info!("editing {:?}", edits); } map.check_invariants(app.as_ref()); @@ -844,6 +997,31 @@ mod tests { ); assert!(map.is_line_folded(display_point.row(), app.as_ref())); } + + for _ in 0..5 { + let end = rng.gen_range(0..=buffer.len()); + let start = rng.gen_range(0..=end); + let expected_folds = map + .folds + .items() + .into_iter() + .filter(|fold| { + let start = buffer.anchor_before(start).unwrap(); + let end = buffer.anchor_after(end).unwrap(); + start.cmp(&fold.0.end, buffer).unwrap() == Ordering::Less + && end.cmp(&fold.0.start, buffer).unwrap() == Ordering::Greater + }) + .map(|fold| fold.0) + .collect::>(); + + assert_eq!( + map.folds_in_range(start..end, app.as_ref()) + .unwrap() + .cloned() + .collect::>(), + expected_folds + ); + } } }); } @@ -894,13 +1072,13 @@ mod tests { fn merged_fold_ranges(&self, app: &AppContext) -> Vec> { let buffer = self.buffer.read(app); - let mut folds = self.folds.clone(); + let mut folds = self.folds.items(); // Ensure sorting doesn't change how folds get merged and displayed. - folds.sort_by(|a, b| a.cmp(b, buffer).unwrap()); + folds.sort_by(|a, b| a.0.cmp(&b.0, buffer).unwrap()); let mut fold_ranges = folds .iter() .map(|fold| { - fold.start.to_offset(buffer).unwrap()..fold.end.to_offset(buffer).unwrap() + fold.0.start.to_offset(buffer).unwrap()..fold.0.end.to_offset(buffer).unwrap() }) .peekable(); diff --git a/zed/src/editor/display_map/mod.rs b/zed/src/editor/display_map/mod.rs index 96392610d0..97c1c0891b 100644 --- a/zed/src/editor/display_map/mod.rs +++ b/zed/src/editor/display_map/mod.rs @@ -1,6 +1,6 @@ mod fold_map; -use super::{buffer, Anchor, AnchorRangeExt, Buffer, Edit, Point, TextSummary, ToOffset, ToPoint}; +use super::{buffer, Anchor, Buffer, Edit, Point, TextSummary, ToOffset, ToPoint}; use anyhow::Result; pub use fold_map::BufferRows; use fold_map::{FoldMap, FoldMapSnapshot}; diff --git a/zed/src/operation_queue.rs b/zed/src/operation_queue.rs index 0603d5b9ff..2c0e234fe9 100644 --- a/zed/src/operation_queue.rs +++ b/zed/src/operation_queue.rs @@ -1,11 +1,8 @@ use crate::{ - sum_tree::{Cursor, Dimension, Edit, Item, KeyedItem, SumTree}, + sum_tree::{Cursor, Dimension, Edit, Item, KeyedItem, SumTree, Summary}, time, }; -use std::{ - fmt::Debug, - ops::{Add, AddAssign}, -}; +use std::{fmt::Debug, ops::Add}; pub trait Operation: Clone + Debug + Eq { fn timestamp(&self) -> time::Lamport; @@ -35,7 +32,8 @@ impl OperationQueue { pub fn insert(&mut self, mut ops: Vec) { ops.sort_by_key(|op| op.timestamp()); ops.dedup_by_key(|op| op.timestamp()); - self.0.edit(ops.into_iter().map(Edit::Insert).collect()); + self.0 + .edit(ops.into_iter().map(Edit::Insert).collect(), &()); } pub fn drain(&mut self) -> Self { @@ -68,8 +66,10 @@ impl KeyedItem for T { } } -impl<'a> AddAssign<&'a Self> for OperationSummary { - fn add_assign(&mut self, other: &Self) { +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; diff --git a/zed/src/sum_tree/cursor.rs b/zed/src/sum_tree/cursor.rs index 8b2e9e78b7..3d65d3f9c3 100644 --- a/zed/src/sum_tree/cursor.rs +++ b/zed/src/sum_tree/cursor.rs @@ -199,9 +199,6 @@ where } pub fn next(&mut self) { - if !self.did_seek { - self.descend_to_first_item(self.tree, |_| true) - } self.next_internal(|_| true) } @@ -209,67 +206,88 @@ where where F: Fn(&T::Summary) -> bool, { - assert!(self.did_seek, "Must seek before calling this method"); + let mut descend = false; - if self.stack.is_empty() { - if !self.at_end { - self.descend_to_first_item(self.tree, filter_node); - } - } else { - while self.stack.len() > 0 { - let new_subtree = { - let entry = self.stack.last_mut().unwrap(); - match entry.tree.0.as_ref() { - Node::Internal { - child_trees, - child_summaries, - .. - } => { - while entry.index < child_summaries.len() { - entry - .seek_dimension - .add_summary(&child_summaries[entry.index]); - entry - .sum_dimension - .add_summary(&child_summaries[entry.index]); + if self.stack.is_empty() && !self.at_end { + self.stack.push(StackEntry { + tree: self.tree, + index: 0, + seek_dimension: S::default(), + sum_dimension: U::default(), + }); + descend = true; + self.did_seek = true; + } - entry.index += 1; - if let Some(next_summary) = child_summaries.get(entry.index) { - if filter_node(next_summary) { - break; - } else { - self.seek_dimension.add_summary(next_summary); - self.sum_dimension.add_summary(next_summary); - } - } - } - - child_trees.get(entry.index) + while self.stack.len() > 0 { + let new_subtree = { + let entry = self.stack.last_mut().unwrap(); + match entry.tree.0.as_ref() { + Node::Internal { + child_trees, + child_summaries, + .. + } => { + if !descend { + let summary = &child_summaries[entry.index]; + entry.seek_dimension.add_summary(summary); + entry.sum_dimension.add_summary(summary); + entry.index += 1; } - Node::Leaf { item_summaries, .. } => loop { + + while entry.index < child_summaries.len() { + let next_summary = &child_summaries[entry.index]; + if filter_node(next_summary) { + break; + } else { + self.seek_dimension.add_summary(next_summary); + self.sum_dimension.add_summary(next_summary); + } + entry.index += 1; + } + + child_trees.get(entry.index) + } + Node::Leaf { item_summaries, .. } => { + if !descend { let item_summary = &item_summaries[entry.index]; self.seek_dimension.add_summary(item_summary); entry.seek_dimension.add_summary(item_summary); self.sum_dimension.add_summary(item_summary); entry.sum_dimension.add_summary(item_summary); entry.index += 1; + } + + loop { if let Some(next_item_summary) = item_summaries.get(entry.index) { if filter_node(next_item_summary) { return; + } else { + self.seek_dimension.add_summary(next_item_summary); + entry.seek_dimension.add_summary(next_item_summary); + self.sum_dimension.add_summary(next_item_summary); + entry.sum_dimension.add_summary(next_item_summary); + entry.index += 1; } } else { break None; } - }, + } } - }; - - if let Some(subtree) = new_subtree { - self.descend_to_first_item(subtree, filter_node); - break; - } else { - self.stack.pop(); } + }; + + if let Some(subtree) = new_subtree { + descend = true; + self.stack.push(StackEntry { + tree: subtree, + index: 0, + seek_dimension: self.seek_dimension.clone(), + sum_dimension: self.sum_dimension.clone(), + }); + } else { + descend = false; + self.stack.pop(); } } @@ -277,67 +295,6 @@ where debug_assert!(self.stack.is_empty() || self.stack.last().unwrap().tree.0.is_leaf()); } - pub fn descend_to_first_item(&mut self, mut subtree: &'a SumTree, filter_node: F) - where - F: Fn(&T::Summary) -> bool, - { - self.did_seek = true; - loop { - subtree = match *subtree.0 { - Node::Internal { - ref child_trees, - ref child_summaries, - .. - } => { - let mut new_index = None; - for (index, summary) in child_summaries.iter().enumerate() { - if filter_node(summary) { - new_index = Some(index); - break; - } - self.seek_dimension.add_summary(summary); - self.sum_dimension.add_summary(summary); - } - - if let Some(new_index) = new_index { - self.stack.push(StackEntry { - tree: subtree, - index: new_index, - seek_dimension: self.seek_dimension.clone(), - sum_dimension: self.sum_dimension.clone(), - }); - &child_trees[new_index] - } else { - break; - } - } - Node::Leaf { - ref item_summaries, .. - } => { - let mut new_index = None; - for (index, item_summary) in item_summaries.iter().enumerate() { - if filter_node(item_summary) { - new_index = Some(index); - break; - } - self.seek_dimension.add_summary(item_summary); - self.sum_dimension.add_summary(item_summary); - } - - if let Some(new_index) = new_index { - self.stack.push(StackEntry { - tree: subtree, - index: new_index, - seek_dimension: self.seek_dimension.clone(), - sum_dimension: self.sum_dimension.clone(), - }); - } - break; - } - } - } - } - fn descend_to_last_item(&mut self, mut subtree: &'a SumTree) { self.did_seek = true; loop { @@ -382,22 +339,36 @@ where impl<'a, T, S, U> Cursor<'a, T, S, U> where T: Item, - S: Dimension<'a, T::Summary> + Ord, + S: SeekDimension<'a, T::Summary>, U: Dimension<'a, T::Summary>, { - pub fn seek(&mut self, pos: &S, bias: SeekBias) -> bool { + pub fn seek( + &mut self, + pos: &S, + bias: SeekBias, + ctx: &::Context, + ) -> bool { self.reset(); - self.seek_internal::<()>(pos, bias, &mut SeekAggregate::None) + self.seek_internal::<()>(pos, bias, &mut SeekAggregate::None, ctx) } - #[allow(unused)] - pub fn seek_forward(&mut self, pos: &S, bias: SeekBias) -> bool { - self.seek_internal::<()>(pos, bias, &mut SeekAggregate::None) + pub fn seek_forward( + &mut self, + pos: &S, + bias: SeekBias, + ctx: &::Context, + ) -> bool { + self.seek_internal::<()>(pos, bias, &mut SeekAggregate::None, ctx) } - pub fn slice(&mut self, end: &S, bias: SeekBias) -> SumTree { + pub fn slice( + &mut self, + end: &S, + bias: SeekBias, + ctx: &::Context, + ) -> SumTree { let mut slice = SeekAggregate::Slice(SumTree::new()); - self.seek_internal::<()>(end, bias, &mut slice); + self.seek_internal::<()>(end, bias, &mut slice, ctx); if let SeekAggregate::Slice(slice) = slice { slice } else { @@ -405,10 +376,10 @@ where } } - pub fn suffix(&mut self) -> SumTree { + pub fn suffix(&mut self, ctx: &::Context) -> SumTree { let extent = self.tree.extent::(); let mut slice = SeekAggregate::Slice(SumTree::new()); - self.seek_internal::<()>(&extent, SeekBias::Right, &mut slice); + self.seek_internal::<()>(&extent, SeekBias::Right, &mut slice, ctx); if let SeekAggregate::Slice(slice) = slice { slice } else { @@ -416,12 +387,17 @@ where } } - pub fn summary(&mut self, end: &S, bias: SeekBias) -> D + pub fn summary( + &mut self, + end: &S, + bias: SeekBias, + ctx: &::Context, + ) -> D where D: Dimension<'a, T::Summary>, { let mut summary = SeekAggregate::Summary(D::default()); - self.seek_internal(end, bias, &mut summary); + self.seek_internal(end, bias, &mut summary, ctx); if let SeekAggregate::Summary(summary) = summary { summary } else { @@ -434,11 +410,12 @@ where target: &S, bias: SeekBias, aggregate: &mut SeekAggregate, + ctx: &::Context, ) -> bool where D: Dimension<'a, T::Summary>, { - debug_assert!(target >= &self.seek_dimension); + debug_assert!(target.cmp(&self.seek_dimension, ctx) >= Ordering::Equal); let mut containing_subtree = None; if self.did_seek { @@ -458,7 +435,7 @@ where let mut child_end = self.seek_dimension.clone(); child_end.add_summary(&child_summary); - let comparison = target.cmp(&child_end); + let comparison = target.cmp(&child_end, ctx); if comparison == Ordering::Greater || (comparison == Ordering::Equal && bias == SeekBias::Right) { @@ -467,7 +444,7 @@ where match aggregate { SeekAggregate::None => {} SeekAggregate::Slice(slice) => { - slice.push_tree(child_tree.clone()); + slice.push_tree(child_tree.clone(), ctx); } SeekAggregate::Summary(summary) => { summary.add_summary(child_summary); @@ -500,7 +477,7 @@ where let mut item_end = self.seek_dimension.clone(); item_end.add_summary(item_summary); - let comparison = target.cmp(&item_end); + let comparison = target.cmp(&item_end, ctx); if comparison == Ordering::Greater || (comparison == Ordering::Equal && bias == SeekBias::Right) { @@ -511,7 +488,10 @@ where SeekAggregate::Slice(_) => { slice_items.push(item.clone()); slice_item_summaries.push(item_summary.clone()); - *slice_items_summary.as_mut().unwrap() += item_summary; + slice_items_summary + .as_mut() + .unwrap() + .add_summary(item_summary, ctx); } SeekAggregate::Summary(summary) => { summary.add_summary(item_summary); @@ -520,11 +500,14 @@ where entry.index += 1; } else { if let SeekAggregate::Slice(slice) = aggregate { - slice.push_tree(SumTree(Arc::new(Node::Leaf { - summary: slice_items_summary.unwrap(), - items: slice_items, - item_summaries: slice_item_summaries, - }))); + slice.push_tree( + SumTree(Arc::new(Node::Leaf { + summary: slice_items_summary.unwrap(), + items: slice_items, + item_summaries: slice_item_summaries, + })), + ctx, + ); } break 'outer; } @@ -532,11 +515,14 @@ where if let SeekAggregate::Slice(slice) = aggregate { if !slice_items.is_empty() { - slice.push_tree(SumTree(Arc::new(Node::Leaf { - summary: slice_items_summary.unwrap(), - items: slice_items, - item_summaries: slice_item_summaries, - }))); + slice.push_tree( + SumTree(Arc::new(Node::Leaf { + summary: slice_items_summary.unwrap(), + items: slice_items, + item_summaries: slice_item_summaries, + })), + ctx, + ); } } } @@ -565,7 +551,7 @@ where let mut child_end = self.seek_dimension.clone(); child_end.add_summary(child_summary); - let comparison = target.cmp(&child_end); + let comparison = target.cmp(&child_end, ctx); if comparison == Ordering::Greater || (comparison == Ordering::Equal && bias == SeekBias::Right) { @@ -574,7 +560,7 @@ where match aggregate { SeekAggregate::None => {} SeekAggregate::Slice(slice) => { - slice.push_tree(child_trees[index].clone()); + slice.push_tree(child_trees[index].clone(), ctx); } SeekAggregate::Summary(summary) => { summary.add_summary(child_summary); @@ -611,7 +597,7 @@ where let mut child_end = self.seek_dimension.clone(); child_end.add_summary(item_summary); - let comparison = target.cmp(&child_end); + let comparison = target.cmp(&child_end, ctx); if comparison == Ordering::Greater || (comparison == Ordering::Equal && bias == SeekBias::Right) { @@ -621,7 +607,10 @@ where SeekAggregate::None => {} SeekAggregate::Slice(_) => { slice_items.push(item.clone()); - *slice_items_summary.as_mut().unwrap() += item_summary; + slice_items_summary + .as_mut() + .unwrap() + .add_summary(item_summary, ctx); slice_item_summaries.push(item_summary.clone()); } SeekAggregate::Summary(summary) => { @@ -641,11 +630,14 @@ where if let SeekAggregate::Slice(slice) = aggregate { if !slice_items.is_empty() { - slice.push_tree(SumTree(Arc::new(Node::Leaf { - summary: slice_items_summary.unwrap(), - items: slice_items, - item_summaries: slice_item_summaries, - }))); + slice.push_tree( + SumTree(Arc::new(Node::Leaf { + summary: slice_items_summary.unwrap(), + items: slice_items, + item_summaries: slice_item_summaries, + })), + ctx, + ); } } } @@ -666,9 +658,9 @@ where if let Some(summary) = self.item_summary() { end.add_summary(summary); } - *target == end + target.cmp(&end, ctx) == Ordering::Equal } else { - *target == self.seek_dimension + target.cmp(&self.seek_dimension, ctx) == Ordering::Equal } } } @@ -683,7 +675,7 @@ where fn next(&mut self) -> Option { if !self.did_seek { - self.descend_to_first_item(self.tree, |_| true); + self.next(); } if let Some(item) = self.item() { @@ -708,13 +700,7 @@ where { pub fn new(tree: &'a SumTree, filter_node: F) -> Self { let mut cursor = tree.cursor::<(), U>(); - if filter_node(&tree.summary()) { - cursor.descend_to_first_item(tree, &filter_node); - } else { - cursor.did_seek = true; - cursor.at_end = true; - } - + cursor.next_internal(&filter_node); Self { cursor, filter_node, diff --git a/zed/src/sum_tree/mod.rs b/zed/src/sum_tree/mod.rs index fd104a3b12..e70440f16f 100644 --- a/zed/src/sum_tree/mod.rs +++ b/zed/src/sum_tree/mod.rs @@ -3,7 +3,7 @@ mod cursor; use arrayvec::ArrayVec; pub use cursor::Cursor; pub use cursor::FilterCursor; -use std::{fmt, iter::FromIterator, ops::AddAssign, sync::Arc}; +use std::{cmp::Ordering, fmt, iter::FromIterator, sync::Arc}; #[cfg(test)] const TREE_BASE: usize = 2; @@ -11,7 +11,7 @@ const TREE_BASE: usize = 2; const TREE_BASE: usize = 6; pub trait Item: Clone + fmt::Debug { - type Summary: for<'a> AddAssign<&'a Self::Summary> + Default + Clone + fmt::Debug; + type Summary: Summary; fn summary(&self) -> Self::Summary; } @@ -22,14 +22,30 @@ pub trait KeyedItem: Item { fn key(&self) -> Self::Key; } -pub trait Dimension<'a, Summary: Default>: Clone + fmt::Debug + Default { - fn add_summary(&mut self, summary: &'a Summary); +pub trait Summary: Default + Clone + fmt::Debug { + type Context; + + fn add_summary(&mut self, summary: &Self, ctx: &Self::Context); } -impl<'a, T: Default> Dimension<'a, T> for () { +pub trait Dimension<'a, S: Summary>: Clone + fmt::Debug + Default { + fn add_summary(&mut self, _summary: &'a S); +} + +impl<'a, T: Summary> Dimension<'a, T> for () { fn add_summary(&mut self, _: &'a T) {} } +pub trait SeekDimension<'a, T: Summary>: Dimension<'a, T> { + fn cmp(&self, other: &Self, ctx: &T::Context) -> Ordering; +} + +impl<'a, S: Summary, T: Dimension<'a, S> + Ord> SeekDimension<'a, S> for T { + fn cmp(&self, other: &Self, _ctx: &S::Context) -> Ordering { + Ord::cmp(self, other) + } +} + #[derive(Copy, Clone, Eq, PartialEq)] pub enum SeekBias { Left, @@ -48,16 +64,15 @@ impl SumTree { })) } - pub fn from_item(item: T) -> Self { + pub fn from_item(item: T, ctx: &::Context) -> Self { let mut tree = Self::new(); - tree.push(item); + tree.push(item, ctx); tree } #[allow(unused)] pub fn items(&self) -> Vec { let mut cursor = self.cursor::<(), ()>(); - cursor.descend_to_first_item(self, |_| true); cursor.cloned().collect() } @@ -90,7 +105,7 @@ impl SumTree { let mut extent = D::default(); match self.0.as_ref() { Node::Internal { summary, .. } | Node::Leaf { summary, .. } => { - extent.add_summary(summary) + extent.add_summary(summary); } } extent @@ -110,7 +125,7 @@ impl SumTree { } } - pub fn extend(&mut self, iter: I) + pub fn extend(&mut self, iter: I, ctx: &::Context) where I: IntoIterator, { @@ -118,7 +133,7 @@ impl SumTree { for item in iter { if leaf.is_some() && leaf.as_ref().unwrap().items().len() == 2 * TREE_BASE { - self.push_tree(SumTree(Arc::new(leaf.take().unwrap()))); + self.push_tree(SumTree(Arc::new(leaf.take().unwrap())), ctx); } if leaf.is_none() { @@ -136,7 +151,7 @@ impl SumTree { }) = leaf.as_mut() { let item_summary = item.summary(); - *summary += &item_summary; + summary.add_summary(&item_summary, ctx); items.push(item); item_summaries.push(item_summary); } else { @@ -145,35 +160,43 @@ impl SumTree { } if leaf.is_some() { - self.push_tree(SumTree(Arc::new(leaf.take().unwrap()))); + self.push_tree(SumTree(Arc::new(leaf.take().unwrap())), ctx); } } - pub fn push(&mut self, item: T) { + pub fn push(&mut self, item: T, ctx: &::Context) { let summary = item.summary(); - self.push_tree(SumTree::from_child_trees(vec![SumTree(Arc::new( - Node::Leaf { - summary: summary.clone(), - items: ArrayVec::from_iter(Some(item)), - item_summaries: ArrayVec::from_iter(Some(summary)), - }, - ))])) + self.push_tree( + SumTree::from_child_trees( + vec![SumTree(Arc::new(Node::Leaf { + summary: summary.clone(), + items: ArrayVec::from_iter(Some(item)), + item_summaries: ArrayVec::from_iter(Some(summary)), + }))], + ctx, + ), + ctx, + ) } - pub fn push_tree(&mut self, other: Self) { + pub fn push_tree(&mut self, other: Self, ctx: &::Context) { let other_node = other.0.clone(); if !other_node.is_leaf() || other_node.items().len() > 0 { if self.0.height() < other_node.height() { for tree in other_node.child_trees() { - self.push_tree(tree.clone()); + self.push_tree(tree.clone(), ctx); } - } else if let Some(split_tree) = self.push_tree_recursive(other) { - *self = Self::from_child_trees(vec![self.clone(), split_tree]); + } else if let Some(split_tree) = self.push_tree_recursive(other, ctx) { + *self = Self::from_child_trees(vec![self.clone(), split_tree], ctx); } } } - fn push_tree_recursive(&mut self, other: SumTree) -> Option> { + fn push_tree_recursive( + &mut self, + other: SumTree, + ctx: &::Context, + ) -> Option> { match Arc::make_mut(&mut self.0) { Node::Internal { height, @@ -183,7 +206,7 @@ impl SumTree { .. } => { let other_node = other.0.clone(); - *summary += other_node.summary(); + summary.add_summary(other_node.summary(), ctx); let height_delta = *height - other_node.height(); let mut summaries_to_append = ArrayVec::<[T::Summary; 2 * TREE_BASE]>::new(); @@ -195,7 +218,10 @@ impl SumTree { summaries_to_append.push(other_node.summary().clone()); trees_to_append.push(other) } else { - let tree_to_append = child_trees.last_mut().unwrap().push_tree_recursive(other); + let tree_to_append = child_trees + .last_mut() + .unwrap() + .push_tree_recursive(other, ctx); *child_summaries.last_mut().unwrap() = child_trees.last().unwrap().0.summary().clone(); @@ -225,13 +251,13 @@ impl SumTree { left_trees = all_trees.by_ref().take(midpoint).collect(); right_trees = all_trees.collect(); } - *summary = sum(left_summaries.iter()); + *summary = sum(left_summaries.iter(), ctx); *child_summaries = left_summaries; *child_trees = left_trees; Some(SumTree(Arc::new(Node::Internal { height: *height, - summary: sum(right_summaries.iter()), + summary: sum(right_summaries.iter(), ctx), child_summaries: right_summaries, child_trees: right_trees, }))) @@ -270,14 +296,14 @@ impl SumTree { } *items = left_items; *item_summaries = left_summaries; - *summary = sum(item_summaries.iter()); + *summary = sum(item_summaries.iter(), ctx); Some(SumTree(Arc::new(Node::Leaf { items: right_items, - summary: sum(right_summaries.iter()), + summary: sum(right_summaries.iter(), ctx), item_summaries: right_summaries, }))) } else { - *summary += other_node.summary(); + summary.add_summary(other_node.summary(), ctx); items.extend(other_node.items().iter().cloned()); item_summaries.extend(other_node.child_summaries().iter().cloned()); None @@ -286,13 +312,16 @@ impl SumTree { } } - fn from_child_trees(child_trees: Vec>) -> Self { + fn from_child_trees( + child_trees: Vec>, + ctx: &::Context, + ) -> Self { let height = child_trees[0].0.height() + 1; let mut child_summaries = ArrayVec::new(); for child in &child_trees { child_summaries.push(child.0.summary().clone()); } - let summary = sum(child_summaries.iter()); + let summary = sum(child_summaries.iter(), ctx); SumTree(Arc::new(Node::Internal { height, summary, @@ -322,17 +351,21 @@ impl SumTree { impl SumTree { #[allow(unused)] - pub fn insert(&mut self, item: T) { + pub fn insert(&mut self, item: T, ctx: &::Context) { *self = { let mut cursor = self.cursor::(); - let mut new_tree = cursor.slice(&item.key(), SeekBias::Left); - new_tree.push(item); - new_tree.push_tree(cursor.suffix()); + let mut new_tree = cursor.slice(&item.key(), SeekBias::Left, ctx); + new_tree.push(item, ctx); + new_tree.push_tree(cursor.suffix(ctx), ctx); new_tree }; } - pub fn edit(&mut self, mut edits: Vec>) -> Vec { + pub fn edit( + &mut self, + mut edits: Vec>, + ctx: &::Context, + ) -> Vec { if edits.is_empty() { return Vec::new(); } @@ -345,7 +378,7 @@ impl SumTree { let mut new_tree = SumTree::new(); let mut buffered_items = Vec::new(); - cursor.seek(&T::Key::default(), SeekBias::Left); + cursor.seek(&T::Key::default(), SeekBias::Left, ctx); for edit in edits { let new_key = edit.key(); let mut old_item = cursor.item(); @@ -354,9 +387,9 @@ impl SumTree { .as_ref() .map_or(false, |old_item| old_item.key() < new_key) { - new_tree.extend(buffered_items.drain(..)); - let slice = cursor.slice(&new_key, SeekBias::Left); - new_tree.push_tree(slice); + new_tree.extend(buffered_items.drain(..), ctx); + let slice = cursor.slice(&new_key, SeekBias::Left, ctx); + new_tree.push_tree(slice, ctx); old_item = cursor.item(); } @@ -375,17 +408,17 @@ impl SumTree { } } - new_tree.extend(buffered_items); - new_tree.push_tree(cursor.suffix()); + new_tree.extend(buffered_items, ctx); + new_tree.push_tree(cursor.suffix(ctx), ctx); new_tree }; removed } - pub fn get(&self, key: &T::Key) -> Option<&T> { + pub fn get(&self, key: &T::Key, ctx: &::Context) -> Option<&T> { let mut cursor = self.cursor::(); - if cursor.seek(key, SeekBias::Left) { + if cursor.seek(key, SeekBias::Left, ctx) { cursor.item() } else { None @@ -482,14 +515,14 @@ impl Edit { } } -fn sum<'a, T, I>(iter: I) -> T +fn sum<'a, T, I>(iter: I, ctx: &T::Context) -> T where - T: 'a + Default + AddAssign<&'a T>, + T: 'a + Summary, I: Iterator, { let mut sum = T::default(); for value in iter { - sum += value; + sum.add_summary(value, ctx); } sum } @@ -503,12 +536,12 @@ mod tests { #[test] fn test_extend_and_push_tree() { let mut tree1 = SumTree::new(); - tree1.extend(0..20); + tree1.extend(0..20, &()); let mut tree2 = SumTree::new(); - tree2.extend(50..100); + tree2.extend(50..100, &()); - tree1.push_tree(tree2); + tree1.push_tree(tree2, &()); assert_eq!(tree1.items(), (0..20).chain(50..100).collect::>()); } @@ -517,11 +550,12 @@ mod tests { for seed in 0..100 { use rand::{distributions, prelude::*}; + dbg!(seed); let rng = &mut StdRng::seed_from_u64(seed); let mut tree = SumTree::::new(); let count = rng.gen_range(0..10); - tree.extend(rng.sample_iter(distributions::Standard).take(count)); + tree.extend(rng.sample_iter(distributions::Standard).take(count), &()); for _ in 0..5 { let splice_end = rng.gen_range(0..tree.extent::().0 + 1); @@ -538,10 +572,10 @@ mod tests { tree = { let mut cursor = tree.cursor::(); - let mut new_tree = cursor.slice(&Count(splice_start), SeekBias::Right); - new_tree.extend(new_items); - cursor.seek(&Count(splice_end), SeekBias::Right); - new_tree.push_tree(cursor.slice(&tree_end, SeekBias::Right)); + let mut new_tree = cursor.slice(&Count(splice_start), SeekBias::Right, &()); + new_tree.extend(new_items, &()); + cursor.seek(&Count(splice_end), SeekBias::Right, &()); + new_tree.push_tree(cursor.slice(&tree_end, SeekBias::Right, &()), &()); new_tree }; @@ -564,7 +598,7 @@ mod tests { let mut pos = rng.gen_range(0..tree.extent::().0 + 1); let mut before_start = false; let mut cursor = tree.cursor::(); - cursor.seek(&Count(pos), SeekBias::Right); + cursor.seek(&Count(pos), SeekBias::Right, &()); for i in 0..10 { assert_eq!(cursor.start().0, pos); @@ -612,11 +646,11 @@ mod tests { }; let mut cursor = tree.cursor::(); - cursor.seek(&Count(start), start_bias); - let slice = cursor.slice(&Count(end), end_bias); + cursor.seek(&Count(start), start_bias, &()); + let slice = cursor.slice(&Count(end), end_bias, &()); - cursor.seek(&Count(start), start_bias); - let summary = cursor.summary::(&Count(end), end_bias); + cursor.seek(&Count(start), start_bias, &()); + let summary = cursor.summary::(&Count(end), end_bias, &()); assert_eq!(summary, slice.summary().sum); } @@ -629,7 +663,7 @@ mod tests { let tree = SumTree::::new(); let mut cursor = tree.cursor::(); assert_eq!( - cursor.slice(&Count(0), SeekBias::Right).items(), + cursor.slice(&Count(0), SeekBias::Right, &()).items(), Vec::::new() ); assert_eq!(cursor.item(), None); @@ -638,10 +672,10 @@ mod tests { // Single-element tree let mut tree = SumTree::::new(); - tree.extend(vec![1]); + tree.extend(vec![1], &()); let mut cursor = tree.cursor::(); assert_eq!( - cursor.slice(&Count(0), SeekBias::Right).items(), + cursor.slice(&Count(0), SeekBias::Right, &()).items(), Vec::::new() ); assert_eq!(cursor.item(), Some(&1)); @@ -659,15 +693,15 @@ mod tests { assert_eq!(cursor.start(), &Sum(0)); let mut cursor = tree.cursor::(); - assert_eq!(cursor.slice(&Count(1), SeekBias::Right).items(), [1]); + assert_eq!(cursor.slice(&Count(1), SeekBias::Right, &()).items(), [1]); assert_eq!(cursor.item(), None); assert_eq!(cursor.prev_item(), Some(&1)); assert_eq!(cursor.start(), &Sum(1)); - cursor.seek(&Count(0), SeekBias::Right); + cursor.seek(&Count(0), SeekBias::Right, &()); assert_eq!( cursor - .slice(&tree.extent::(), SeekBias::Right) + .slice(&tree.extent::(), SeekBias::Right, &()) .items(), [1] ); @@ -677,10 +711,13 @@ mod tests { // Multiple-element tree let mut tree = SumTree::new(); - tree.extend(vec![1, 2, 3, 4, 5, 6]); + tree.extend(vec![1, 2, 3, 4, 5, 6], &()); let mut cursor = tree.cursor::(); - assert_eq!(cursor.slice(&Count(2), SeekBias::Right).items(), [1, 2]); + assert_eq!( + cursor.slice(&Count(2), SeekBias::Right, &()).items(), + [1, 2] + ); assert_eq!(cursor.item(), Some(&3)); assert_eq!(cursor.prev_item(), Some(&2)); assert_eq!(cursor.start(), &Sum(3)); @@ -749,7 +786,7 @@ mod tests { let mut cursor = tree.cursor::(); assert_eq!( cursor - .slice(&tree.extent::(), SeekBias::Right) + .slice(&tree.extent::(), SeekBias::Right, &()) .items(), tree.items() ); @@ -757,10 +794,10 @@ mod tests { assert_eq!(cursor.prev_item(), Some(&6)); assert_eq!(cursor.start(), &Sum(21)); - cursor.seek(&Count(3), SeekBias::Right); + cursor.seek(&Count(3), SeekBias::Right, &()); assert_eq!( cursor - .slice(&tree.extent::(), SeekBias::Right) + .slice(&tree.extent::(), SeekBias::Right, &()) .items(), [4, 5, 6] ); @@ -769,37 +806,46 @@ mod tests { assert_eq!(cursor.start(), &Sum(21)); // Seeking can bias left or right - cursor.seek(&Count(1), SeekBias::Left); + cursor.seek(&Count(1), SeekBias::Left, &()); assert_eq!(cursor.item(), Some(&1)); - cursor.seek(&Count(1), SeekBias::Right); + cursor.seek(&Count(1), SeekBias::Right, &()); assert_eq!(cursor.item(), Some(&2)); // Slicing without resetting starts from where the cursor is parked at. - cursor.seek(&Count(1), SeekBias::Right); - assert_eq!(cursor.slice(&Count(3), SeekBias::Right).items(), vec![2, 3]); - assert_eq!(cursor.slice(&Count(6), SeekBias::Left).items(), vec![4, 5]); - assert_eq!(cursor.slice(&Count(6), SeekBias::Right).items(), vec![6]); + cursor.seek(&Count(1), SeekBias::Right, &()); + assert_eq!( + cursor.slice(&Count(3), SeekBias::Right, &()).items(), + vec![2, 3] + ); + assert_eq!( + cursor.slice(&Count(6), SeekBias::Left, &()).items(), + vec![4, 5] + ); + assert_eq!( + cursor.slice(&Count(6), SeekBias::Right, &()).items(), + vec![6] + ); } #[test] fn test_edit() { let mut tree = SumTree::::new(); - let removed = tree.edit(vec![Edit::Insert(1), Edit::Insert(2), Edit::Insert(0)]); + let removed = tree.edit(vec![Edit::Insert(1), Edit::Insert(2), Edit::Insert(0)], &()); assert_eq!(tree.items(), vec![0, 1, 2]); assert_eq!(removed, Vec::::new()); - assert_eq!(tree.get(&0), Some(&0)); - assert_eq!(tree.get(&1), Some(&1)); - assert_eq!(tree.get(&2), Some(&2)); - assert_eq!(tree.get(&4), None); + assert_eq!(tree.get(&0, &()), Some(&0)); + assert_eq!(tree.get(&1, &()), Some(&1)); + assert_eq!(tree.get(&2, &()), Some(&2)); + assert_eq!(tree.get(&4, &()), None); - let removed = tree.edit(vec![Edit::Insert(2), Edit::Insert(4), Edit::Remove(0)]); + let removed = tree.edit(vec![Edit::Insert(2), Edit::Insert(4), Edit::Remove(0)], &()); assert_eq!(tree.items(), vec![1, 2, 4]); assert_eq!(removed, vec![0, 2]); - assert_eq!(tree.get(&0), None); - assert_eq!(tree.get(&1), Some(&1)); - assert_eq!(tree.get(&2), Some(&2)); - assert_eq!(tree.get(&4), Some(&4)); + assert_eq!(tree.get(&0, &()), None); + assert_eq!(tree.get(&1, &()), Some(&1)); + assert_eq!(tree.get(&2, &()), Some(&2)); + assert_eq!(tree.get(&4, &()), Some(&4)); } #[derive(Clone, Default, Debug)] @@ -837,14 +883,10 @@ mod tests { } } - impl<'a> Dimension<'a, IntegersSummary> for u8 { - fn add_summary(&mut self, summary: &IntegersSummary) { - *self = summary.max; - } - } + impl Summary for IntegersSummary { + type Context = (); - impl<'a> AddAssign<&'a Self> for IntegersSummary { - fn add_assign(&mut self, other: &Self) { + fn add_summary(&mut self, other: &Self, _: &()) { self.count.0 += &other.count.0; self.sum.0 += &other.sum.0; self.contains_even |= other.contains_even; @@ -852,6 +894,12 @@ mod tests { } } + impl<'a> Dimension<'a, IntegersSummary> for u8 { + fn add_summary(&mut self, summary: &IntegersSummary) { + *self = summary.max; + } + } + impl<'a> Dimension<'a, IntegersSummary> for Count { fn add_summary(&mut self, summary: &IntegersSummary) { self.0 += summary.count.0; diff --git a/zed/src/util.rs b/zed/src/util.rs index 09ce2f87e1..1ce914ddd4 100644 --- a/zed/src/util.rs +++ b/zed/src/util.rs @@ -30,37 +30,6 @@ where } } -pub fn find_insertion_index<'a, F, T, E>(slice: &'a [T], mut f: F) -> Result -where - F: FnMut(&'a T) -> Result, -{ - use Ordering::*; - - let s = slice; - let mut size = s.len(); - if size == 0 { - return Ok(0); - } - let mut base = 0usize; - while size > 1 { - let half = size / 2; - let mid = base + half; - // mid is always in [0, size), that means mid is >= 0 and < size. - // mid >= 0: by definition - // mid < size: mid = size / 2 + size / 4 + size / 8 ... - let cmp = f(unsafe { s.get_unchecked(mid) })?; - base = if cmp == Greater { base } else { mid }; - size -= half; - } - // base is always in [0, size) because base <= mid. - let cmp = f(unsafe { s.get_unchecked(base) })?; - if cmp == Equal { - Ok(base) - } else { - Ok(base + (cmp == Less) as usize) - } -} - pub struct RandomCharIter(T); impl RandomCharIter { @@ -85,14 +54,6 @@ impl Iterator for RandomCharIter { mod tests { use super::*; - #[test] - fn test_find_insertion_index() { - assert_eq!( - find_insertion_index(&[0, 4, 8], |probe| Ok::(probe.cmp(&2))), - Ok(1) - ); - } - #[test] fn test_extend_sorted() { let mut vec = vec![]; diff --git a/zed/src/worktree.rs b/zed/src/worktree.rs index ba6c37bac1..135fb3bedf 100644 --- a/zed/src/worktree.rs +++ b/zed/src/worktree.rs @@ -24,7 +24,7 @@ use std::{ fmt, fs, future::Future, io::{self, Read, Write}, - ops::{AddAssign, Deref}, + ops::Deref, os::unix::{ffi::OsStrExt, fs::MetadataExt}, path::{Path, PathBuf}, sync::{Arc, Weak}, @@ -249,9 +249,10 @@ impl Snapshot { #[cfg(test)] pub fn paths(&self) -> impl Iterator> { - let mut cursor = self.entries.cursor::<(), ()>(); - cursor.next(); - cursor.map(|entry| entry.path()) + self.entries + .cursor::<(), ()>() + .skip(1) + .map(|entry| entry.path()) } pub fn visible_files(&self, start: usize) -> FileIter { @@ -274,7 +275,7 @@ impl Snapshot { fn entry_for_path(&self, path: impl AsRef) -> Option<&Entry> { let mut cursor = self.entries.cursor::<_, ()>(); - if cursor.seek(&PathSearch::Exact(path.as_ref()), SeekBias::Left) { + if cursor.seek(&PathSearch::Exact(path.as_ref()), SeekBias::Left, &()) { cursor.item() } else { None @@ -296,7 +297,7 @@ impl Snapshot { self.ignores .insert(ignore_dir_path.into(), (Arc::new(ignore), self.scan_id)); } - self.entries.insert(entry); + self.entries.insert(entry, &()); } fn populate_dir( @@ -309,7 +310,7 @@ impl Snapshot { let mut parent_entry = self .entries - .get(&PathKey(parent_path.clone())) + .get(&PathKey(parent_path.clone()), &()) .unwrap() .clone(); if let Some(ignore) = ignore { @@ -325,15 +326,15 @@ impl Snapshot { for entry in entries { edits.push(Edit::Insert(entry)); } - self.entries.edit(edits); + self.entries.edit(edits, &()); } fn remove_path(&mut self, path: &Path) { let new_entries = { let mut cursor = self.entries.cursor::<_, ()>(); - let mut new_entries = cursor.slice(&PathSearch::Exact(path), SeekBias::Left); - cursor.seek_forward(&PathSearch::Successor(path), SeekBias::Left); - new_entries.push_tree(cursor.suffix()); + let mut new_entries = cursor.slice(&PathSearch::Exact(path), SeekBias::Left, &()); + cursor.seek_forward(&PathSearch::Successor(path), SeekBias::Left, &()); + new_entries.push_tree(cursor.suffix(&()), &()); new_entries }; self.entries = new_entries; @@ -543,8 +544,10 @@ impl Default for EntrySummary { } } -impl<'a> AddAssign<&'a EntrySummary> for EntrySummary { - fn add_assign(&mut self, rhs: &'a EntrySummary) { +impl sum_tree::Summary for EntrySummary { + type Context = (); + + fn add_summary(&mut self, rhs: &Self, _: &()) { self.max_path = rhs.max_path.clone(); self.file_count += rhs.file_count; self.visible_file_count += rhs.visible_file_count; @@ -1073,7 +1076,7 @@ impl BackgroundScanner { edits.push(Edit::Insert(entry)); } } - self.snapshot.lock().entries.edit(edits); + self.snapshot.lock().entries.edit(edits, &()); } fn fs_entry_for_path(&self, path: Arc, abs_path: &Path) -> Result> { @@ -1176,13 +1179,13 @@ pub enum FileIter<'a> { impl<'a> FileIter<'a> { fn all(snapshot: &'a Snapshot, start: usize) -> Self { let mut cursor = snapshot.entries.cursor(); - cursor.seek(&FileCount(start), SeekBias::Right); + cursor.seek(&FileCount(start), SeekBias::Right, &()); Self::All(cursor) } fn visible(snapshot: &'a Snapshot, start: usize) -> Self { let mut cursor = snapshot.entries.cursor(); - cursor.seek(&VisibleFileCount(start), SeekBias::Right); + cursor.seek(&VisibleFileCount(start), SeekBias::Right, &()); Self::Visible(cursor) } @@ -1190,11 +1193,11 @@ impl<'a> FileIter<'a> { match self { Self::All(cursor) => { let ix = *cursor.start(); - cursor.seek_forward(&FileCount(ix.0 + 1), SeekBias::Right); + cursor.seek_forward(&FileCount(ix.0 + 1), SeekBias::Right, &()); } Self::Visible(cursor) => { let ix = *cursor.start(); - cursor.seek_forward(&VisibleFileCount(ix.0 + 1), SeekBias::Right); + cursor.seek_forward(&VisibleFileCount(ix.0 + 1), SeekBias::Right, &()); } } } @@ -1228,7 +1231,7 @@ struct ChildEntriesIter<'a> { impl<'a> ChildEntriesIter<'a> { fn new(parent_path: &'a Path, snapshot: &'a Snapshot) -> Self { let mut cursor = snapshot.entries.cursor(); - cursor.seek(&PathSearch::Exact(parent_path), SeekBias::Right); + cursor.seek(&PathSearch::Exact(parent_path), SeekBias::Right, &()); Self { parent_path, cursor, @@ -1243,7 +1246,7 @@ impl<'a> Iterator for ChildEntriesIter<'a> { if let Some(item) = self.cursor.item() { if item.path().starts_with(self.parent_path) { self.cursor - .seek_forward(&PathSearch::Successor(item.path()), SeekBias::Left); + .seek_forward(&PathSearch::Successor(item.path()), SeekBias::Left, &()); Some(item) } else { None