From 4b38f2850d75db9703067c64355c4efc64a159a7 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 3 May 2021 18:58:39 +0200 Subject: [PATCH] WIP --- zed/src/editor/buffer_view.rs | 75 ++++++++++--- zed/src/editor/display_map/fold_map.rs | 142 ++++++++++++++++--------- zed/src/editor/display_map/mod.rs | 7 ++ 3 files changed, 162 insertions(+), 62 deletions(-) diff --git a/zed/src/editor/buffer_view.rs b/zed/src/editor/buffer_view.rs index c37ae4818f53def10ff184c35f92d813d62224ed..b13af5a70ebccccfef5d338b41e4b9a8e55dab2d 100644 --- a/zed/src/editor/buffer_view.rs +++ b/zed/src/editor/buffer_view.rs @@ -784,6 +784,9 @@ impl BufferView { let mut edits = Vec::new(); let mut new_selection_ranges = Vec::new(); + let mut old_folds = Vec::new(); + let mut new_folds = Vec::new(); + let mut selections = self.selections(app).iter().peekable(); let mut contiguous_selections = Vec::new(); while let Some(selection) = selections.next() { @@ -830,25 +833,42 @@ impl BufferView { edits.push((prev_row_start..prev_row_start, text)); edits.push((selection_row_start - 1..selection_row_end, String::new())); - // Move selections up. let row_delta = buffer_rows.start - prev_row_display_start .to_buffer_point(map, Bias::Left, app) .unwrap() .row; + + // Move selections up. for range in &mut contiguous_selections { range.start.row -= row_delta; range.end.row -= row_delta; } + + // Move folds up. + old_folds.push(selection_row_start..selection_row_end); + for fold in map + .folds_in_range(selection_row_start..selection_row_end, app) + .unwrap() + { + let mut start = fold.start.to_point(buffer).unwrap(); + let mut end = fold.end.to_point(buffer).unwrap(); + start.row -= row_delta; + end.row -= row_delta; + new_folds.push(start..end); + } } + new_selection_ranges.extend(contiguous_selections.drain(..)); } + self.unfold_ranges(old_folds, ctx); self.buffer.update(ctx, |buffer, ctx| { for (range, text) in edits.into_iter().rev() { buffer.edit(Some(range), text, Some(ctx)).unwrap(); } }); + self.fold_ranges(new_folds, ctx); self.select_ranges(new_selection_ranges, true, ctx); self.end_transaction(ctx); @@ -863,6 +883,9 @@ impl BufferView { let mut edits = Vec::new(); let mut new_selection_ranges = Vec::new(); + let mut old_folds = Vec::new(); + let mut new_folds = Vec::new(); + let mut selections = self.selections(app).iter().peekable(); let mut contiguous_selections = Vec::new(); while let Some(selection) = selections.next() { @@ -912,26 +935,43 @@ impl BufferView { edits.push((selection_row_start..selection_row_end + 1, String::new())); edits.push((next_row_end..next_row_end, text)); - // Move selections down. let row_delta = next_row_display_end .to_buffer_point(map, Bias::Right, app) .unwrap() .row - buffer_rows.end + 1; + + // Move selections down. for range in &mut contiguous_selections { range.start.row += row_delta; range.end.row += row_delta; } + + // Move folds down. + old_folds.push(selection_row_start..selection_row_end); + for fold in map + .folds_in_range(selection_row_start..selection_row_end, app) + .unwrap() + { + let mut start = fold.start.to_point(buffer).unwrap(); + let mut end = fold.end.to_point(buffer).unwrap(); + start.row += row_delta; + end.row += row_delta; + new_folds.push(start..end); + } } + new_selection_ranges.extend(contiguous_selections.drain(..)); } + self.unfold_ranges(old_folds, ctx); self.buffer.update(ctx, |buffer, ctx| { for (range, text) in edits.into_iter().rev() { buffer.edit(Some(range), text, Some(ctx)).unwrap(); } }); + self.fold_ranges(new_folds, ctx); self.select_ranges(new_selection_ranges, true, ctx); self.end_transaction(ctx); @@ -1533,12 +1573,7 @@ impl BufferView { } } - if !fold_ranges.is_empty() { - self.display_map.update(ctx, |map, ctx| { - map.fold(fold_ranges, ctx).unwrap(); - }); - *self.autoscroll_requested.lock() = true; - } + self.fold_ranges(fold_ranges, ctx); } pub fn unfold(&mut self, _: &(), ctx: &mut ViewContext) { @@ -1559,11 +1594,7 @@ impl BufferView { start..end }) .collect::>(); - - self.display_map.update(ctx, |map, ctx| { - map.unfold(ranges, ctx).unwrap(); - }); - *self.autoscroll_requested.lock() = true; + self.unfold_ranges(ranges, ctx); } fn is_line_foldable(&self, display_row: u32, app: &AppContext) -> bool { @@ -1621,6 +1652,24 @@ impl BufferView { }); } + fn fold_ranges(&mut self, ranges: Vec>, ctx: &mut ViewContext) { + if !ranges.is_empty() { + self.display_map.update(ctx, |map, ctx| { + map.fold(ranges, ctx).unwrap(); + }); + *self.autoscroll_requested.lock() = true; + } + } + + fn unfold_ranges(&mut self, ranges: Vec>, ctx: &mut ViewContext) { + if !ranges.is_empty() { + self.display_map.update(ctx, |map, ctx| { + map.unfold(ranges, ctx).unwrap(); + }); + *self.autoscroll_requested.lock() = true; + } + } + pub fn line(&self, display_row: u32, app: &AppContext) -> Result { self.display_map.read(app).line(display_row, app) } diff --git a/zed/src/editor/display_map/fold_map.rs b/zed/src/editor/display_map/fold_map.rs index fd63a3e2ec478acb0b32c4bca19d6d4b83a93b95..0e3626578be8edbf473e6b391549c0796f377e22 100644 --- a/zed/src/editor/display_map/fold_map.rs +++ b/zed/src/editor/display_map/fold_map.rs @@ -89,6 +89,33 @@ impl FoldMap { DisplayPoint(self.transforms.summary().display.rightmost_point) } + pub fn folds_in_range(&self, range: Range, app: &AppContext) -> Result<&[Range]> + where + T: ToOffset, + { + let buffer = self.buffer.read(app); + let range = buffer.anchor_before(range.start)?..buffer.anchor_before(range.end)?; + let mut start_ix = find_insertion_index(&self.folds, |probe| probe.cmp(&range, buffer))?; + let mut end_ix = start_ix; + + for fold in self.folds[..start_ix].iter().rev() { + if fold.end.cmp(&range.start, buffer)? == Ordering::Greater { + start_ix -= 1; + } else { + break; + } + } + for fold in &self.folds[end_ix..] { + if range.end.cmp(&fold.start, buffer)? == Ordering::Greater { + end_ix += 1; + } else { + break; + } + } + + Ok(&self.folds[start_ix..end_ix]) + } + pub fn fold( &mut self, ranges: impl IntoIterator>, @@ -422,7 +449,7 @@ impl<'a> Iterator for Chars<'a> { return Some(c); } - if self.offset == self.cursor.end().display.chars { + while self.offset == self.cursor.end().display.chars && self.cursor.item().is_some() { self.cursor.next(); } @@ -584,6 +611,9 @@ mod tests { let iterations = env::var("ITERATIONS") .map(|i| i.parse().expect("invalid `ITERATIONS` variable")) .unwrap_or(100); + let operations = env::var("OPERATIONS") + .map(|i| i.parse().expect("invalid `OPERATIONS` variable")) + .unwrap_or(10); let seed_range = if let Ok(seed) = env::var("SEED") { let seed = seed.parse().expect("invalid `SEED` variable"); seed..seed + 1 @@ -591,6 +621,8 @@ mod tests { 0..iterations }; + let operations = 2; + let seed_range = 133..=133; for seed in seed_range { println!("{:?}", seed); let mut rng = StdRng::seed_from_u64(seed); @@ -603,66 +635,78 @@ mod tests { }); let mut map = FoldMap::new(buffer.clone(), app.as_ref()); - { - let buffer = buffer.read(app); - - let fold_count = rng.gen_range(0..10); - 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); + for op_ix in 0..operations { + dbg!(op_ix); + + log::info!("Text: {:?}", buffer.read(app).text()); + { + let buffer = buffer.read(app); + + let fold_count = rng.gen_range(0..=2); + 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); + } + log::info!("Folding {:?}", fold_ranges); + if op_ix == 1 { + dbg!("stopping"); + } + map.fold(fold_ranges.clone(), app.as_ref()).unwrap(); + assert_eq!(map.transforms.summary().buffer.chars, buffer.len()); + + let mut expected_text = buffer.text(); + for fold_range in map.merged_fold_ranges(app.as_ref()).into_iter().rev() { + expected_text.replace_range(fold_range.start..fold_range.end, "…"); + } + assert_eq!(map.text(app.as_ref()), expected_text); + + for fold_range in map.merged_fold_ranges(app.as_ref()) { + let display_point = + map.to_display_point(fold_range.start.to_point(buffer).unwrap()); + assert!(map.is_line_folded(display_point.row())); + } } - map.fold(fold_ranges, app.as_ref()).unwrap(); + let edits = buffer.update(app, |buffer, ctx| { + let start_version = buffer.version.clone(); + let edit_count = rng.gen_range(0..=2); + buffer.randomly_edit(&mut rng, edit_count, Some(ctx)); + buffer.edits_since(start_version).collect::>() + }); + log::info!("Editing {:?}", edits); + map.apply_edits(&edits, app.as_ref()).unwrap(); + assert_eq!( + map.transforms.summary().buffer.chars, + buffer.read(app).len() + ); + let buffer = map.buffer.read(app); let mut expected_text = buffer.text(); + let mut expected_buffer_rows = Vec::new(); + let mut next_row = buffer.max_point().row; for fold_range in map.merged_fold_ranges(app.as_ref()).into_iter().rev() { + let fold_start = buffer.point_for_offset(fold_range.start).unwrap(); + let fold_end = buffer.point_for_offset(fold_range.end).unwrap(); + expected_buffer_rows.extend((fold_end.row + 1..=next_row).rev()); + next_row = fold_start.row; + expected_text.replace_range(fold_range.start..fold_range.end, "…"); } + expected_buffer_rows.extend((0..=next_row).rev()); + expected_buffer_rows.reverse(); assert_eq!(map.text(app.as_ref()), expected_text); - for fold_range in map.merged_fold_ranges(app.as_ref()) { - let display_point = - map.to_display_point(fold_range.start.to_point(buffer).unwrap()); - assert!(map.is_line_folded(display_point.row())); + for (idx, buffer_row) in expected_buffer_rows.iter().enumerate() { + let display_row = map.to_display_point(Point::new(*buffer_row, 0)).row(); + assert_eq!( + map.buffer_rows(display_row).unwrap().collect::>(), + expected_buffer_rows[idx..], + ); } } - - let edits = buffer.update(app, |buffer, ctx| { - let start_version = buffer.version.clone(); - let edit_count = rng.gen_range(1..10); - buffer.randomly_edit(&mut rng, edit_count, Some(ctx)); - buffer.edits_since(start_version).collect::>() - }); - - map.apply_edits(&edits, app.as_ref()).unwrap(); - - let buffer = map.buffer.read(app); - let mut expected_text = buffer.text(); - let mut expected_buffer_rows = Vec::new(); - let mut next_row = buffer.max_point().row; - for fold_range in map.merged_fold_ranges(app.as_ref()).into_iter().rev() { - let fold_start = buffer.point_for_offset(fold_range.start).unwrap(); - let fold_end = buffer.point_for_offset(fold_range.end).unwrap(); - expected_buffer_rows.extend((fold_end.row + 1..=next_row).rev()); - next_row = fold_start.row; - - expected_text.replace_range(fold_range.start..fold_range.end, "…"); - } - expected_buffer_rows.extend((0..=next_row).rev()); - expected_buffer_rows.reverse(); - - assert_eq!(map.text(app.as_ref()), expected_text); - - for (idx, buffer_row) in expected_buffer_rows.iter().enumerate() { - let display_row = map.to_display_point(Point::new(*buffer_row, 0)).row(); - assert_eq!( - map.buffer_rows(display_row).unwrap().collect::>(), - expected_buffer_rows[idx..], - ); - } }); } } diff --git a/zed/src/editor/display_map/mod.rs b/zed/src/editor/display_map/mod.rs index 77a3defb124faf98aed9304b5b1b561bb9af92e8..b69a70f3979870eb061f72c0cfdff25931165ccf 100644 --- a/zed/src/editor/display_map/mod.rs +++ b/zed/src/editor/display_map/mod.rs @@ -34,6 +34,13 @@ impl DisplayMap { } } + pub fn folds_in_range(&self, range: Range, app: &AppContext) -> Result<&[Range]> + where + T: ToOffset, + { + self.fold_map.folds_in_range(range, app) + } + pub fn fold( &mut self, ranges: impl IntoIterator>,