@@ -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<Self>) {
@@ -1559,11 +1594,7 @@ impl BufferView {
start..end
})
.collect::<Vec<_>>();
-
- 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<T: ToOffset>(&mut self, ranges: Vec<Range<T>>, ctx: &mut ViewContext<Self>) {
+ if !ranges.is_empty() {
+ self.display_map.update(ctx, |map, ctx| {
+ map.fold(ranges, ctx).unwrap();
+ });
+ *self.autoscroll_requested.lock() = true;
+ }
+ }
+
+ fn unfold_ranges<T: ToOffset>(&mut self, ranges: Vec<Range<T>>, ctx: &mut ViewContext<Self>) {
+ 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<String> {
self.display_map.read(app).line(display_row, app)
}
@@ -89,6 +89,33 @@ impl FoldMap {
DisplayPoint(self.transforms.summary().display.rightmost_point)
}
+ pub fn folds_in_range<T>(&self, range: Range<T>, app: &AppContext) -> Result<&[Range<Anchor>]>
+ 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<T: ToOffset>(
&mut self,
ranges: impl IntoIterator<Item = Range<T>>,
@@ -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<Range<usize>> = 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<Range<usize>> = 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::<Vec<_>>()
+ });
+ 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::<Vec<_>>(),
+ 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::<Vec<_>>()
- });
-
- 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::<Vec<_>>(),
- expected_buffer_rows[idx..],
- );
- }
});
}
}
@@ -34,6 +34,13 @@ impl DisplayMap {
}
}
+ pub fn folds_in_range<T>(&self, range: Range<T>, app: &AppContext) -> Result<&[Range<Anchor>]>
+ where
+ T: ToOffset,
+ {
+ self.fold_map.folds_in_range(range, app)
+ }
+
pub fn fold<T: ToOffset>(
&mut self,
ranges: impl IntoIterator<Item = Range<T>>,