From 8cd451f3ca49ff65cf20feb923dcb7080f92ebc1 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 3 May 2021 11:32:29 +0200 Subject: [PATCH 1/7] Implement `move_line_up` and `move_line_down` This does not restore folds yet. --- zed/src/editor/buffer/selection.rs | 11 +- zed/src/editor/buffer_view.rs | 176 +++++++++++++++++++++++-- zed/src/editor/display_map/fold_map.rs | 7 + zed/src/editor/display_map/mod.rs | 5 + 4 files changed, 188 insertions(+), 11 deletions(-) diff --git a/zed/src/editor/buffer/selection.rs b/zed/src/editor/buffer/selection.rs index 1d7459482c22a16407bf379ddff3017357c51566..0999298357758cb00d29f155eb24a98a8907a8b6 100644 --- a/zed/src/editor/buffer/selection.rs +++ b/zed/src/editor/buffer/selection.rs @@ -73,7 +73,11 @@ impl Selection { } } - pub fn buffer_rows_for_display_rows(&self, map: &DisplayMap, ctx: &AppContext) -> Range { + pub fn buffer_rows_for_display_rows( + &self, + map: &DisplayMap, + ctx: &AppContext, + ) -> (Range, Range) { let display_start = self.start.to_display_point(map, ctx).unwrap(); let buffer_start = DisplayPoint::new(display_start.row(), 0) .to_buffer_point(map, Bias::Left, ctx) @@ -93,6 +97,9 @@ impl Selection { .to_buffer_point(map, Bias::Left, ctx) .unwrap(); - buffer_start.row..buffer_end.row + 1 + ( + buffer_start.row..buffer_end.row + 1, + display_start.row()..display_end.row() + 1, + ) } } diff --git a/zed/src/editor/buffer_view.rs b/zed/src/editor/buffer_view.rs index b48c16c23b941a6cab44dca439ede1406e1e855c..6bd727dc4fc93532ac7511d0976d37800681c77c 100644 --- a/zed/src/editor/buffer_view.rs +++ b/zed/src/editor/buffer_view.rs @@ -46,6 +46,8 @@ pub fn init(app: &mut MutableAppContext) { Some("BufferView"), ), Binding::new("cmd-shift-D", "buffer:duplicate_line", Some("BufferView")), + Binding::new("ctrl-cmd-up", "buffer:move_line_up", Some("BufferView")), + Binding::new("ctrl-cmd-down", "buffer:move_line_down", Some("BufferView")), Binding::new("cmd-x", "buffer:cut", Some("BufferView")), Binding::new("cmd-c", "buffer:copy", Some("BufferView")), Binding::new("cmd-v", "buffer:paste", Some("BufferView")), @@ -133,6 +135,8 @@ pub fn init(app: &mut MutableAppContext) { BufferView::delete_to_end_of_line, ); app.add_action("buffer:duplicate_line", BufferView::duplicate_line); + app.add_action("buffer:move_line_up", BufferView::move_line_up); + app.add_action("buffer:move_line_down", BufferView::move_line_down); app.add_action("buffer:cut", BufferView::cut); app.add_action("buffer:copy", BufferView::copy); app.add_action("buffer:paste", BufferView::paste); @@ -639,7 +643,7 @@ 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(map, app); + let (mut rows, _) = selection.buffer_rows_for_display_rows(map, app); let goal_display_column = selection .head() .to_display_point(map, app) @@ -648,7 +652,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(map, app); + let (next_rows, _) = next_selection.buffer_rows_for_display_rows(map, app); if next_rows.start <= rows.end { rows.end = next_rows.end; selections.next().unwrap(); @@ -696,10 +700,10 @@ impl BufferView { goal_column: None, }) .collect(); - self.update_selections(new_selections, true, ctx); self.buffer .update(ctx, |buffer, ctx| buffer.edit(edit_ranges, "", Some(ctx))) .unwrap(); + self.update_selections(new_selections, true, ctx); self.end_transaction(ctx); } @@ -726,9 +730,9 @@ 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(map, app); + let (mut rows, _) = selection.buffer_rows_for_display_rows(map, app); while let Some(next_selection) = selections_iter.peek() { - let next_rows = next_selection.buffer_rows_for_display_rows(map, app); + let (next_rows, _) = next_selection.buffer_rows_for_display_rows(map, app); if next_rows.start <= rows.end - 1 { rows.end = next_rows.end; selections_iter.next().unwrap(); @@ -765,6 +769,156 @@ impl BufferView { self.end_transaction(ctx); } + pub fn move_line_up(&mut self, _: &(), ctx: &mut ViewContext) { + self.start_transaction(ctx); + + let app = ctx.as_ref(); + let buffer = self.buffer.read(ctx); + let map = self.display_map.read(ctx); + + let mut edits = Vec::new(); + let selections = self.selections(ctx.as_ref()).to_vec(); + let mut selections_iter = selections.iter().peekable(); + while let Some(selection) = selections_iter.next() { + // Accumulate contiguous regions of rows that we want to move. + let (mut buffer_rows, mut display_rows) = + selection.buffer_rows_for_display_rows(map, app); + while let Some(next_selection) = selections_iter.peek() { + let (next_buffer_rows, next_display_rows) = + next_selection.buffer_rows_for_display_rows(map, app); + if next_buffer_rows.start <= buffer_rows.end { + buffer_rows.end = next_buffer_rows.end; + display_rows.end = next_display_rows.end; + selections_iter.next().unwrap(); + } else { + break; + } + } + + // Cut the text from the previous line and paste it at the end of the selected region. + if display_rows.start != 0 { + let selection_line_end = Point::new( + buffer_rows.end - 1, + buffer.line_len(buffer_rows.end - 1).unwrap(), + ) + .to_offset(buffer) + .unwrap(); + let prev_line_display_start = DisplayPoint::new(display_rows.start - 1, 0); + let prev_line_display_end = DisplayPoint::new( + prev_line_display_start.row(), + map.line_len(prev_line_display_start.row(), app).unwrap(), + ); + let prev_line_start = prev_line_display_start + .to_buffer_offset(map, Bias::Left, app) + .unwrap(); + let prev_line_end = prev_line_display_end + .to_buffer_offset(map, Bias::Right, app) + .unwrap(); + + let mut text = String::new(); + text.push('\n'); + text.extend( + buffer + .text_for_range(prev_line_start..prev_line_end) + .unwrap(), + ); + edits.push((prev_line_start..prev_line_end + 1, String::new())); + edits.push((selection_line_end..selection_line_end, text)); + } + } + + self.buffer.update(ctx, |buffer, ctx| { + for (range, text) in edits.into_iter().rev() { + buffer.edit(Some(range), text, Some(ctx)).unwrap(); + } + }); + self.update_selections(selections, true, ctx); + self.end_transaction(ctx); + } + + pub fn move_line_down(&mut self, _: &(), ctx: &mut ViewContext) { + self.start_transaction(ctx); + + let mut selections = self.selections(ctx.as_ref()).to_vec(); + { + // Temporarily bias selections right to allow moved lines to push them down when the + // selections are at the beginning of a line. + let buffer = self.buffer.read(ctx); + for selection in &mut selections { + selection.start = selection.start.bias_right(buffer).unwrap(); + selection.end = selection.end.bias_right(buffer).unwrap(); + } + } + self.update_selections(selections.clone(), false, ctx); + + let app = ctx.as_ref(); + let buffer = self.buffer.read(ctx); + let map = self.display_map.read(ctx); + + let mut edits = Vec::new(); + let selections = self.selections(ctx.as_ref()).to_vec(); + let mut selections_iter = selections.iter().peekable(); + while let Some(selection) = selections_iter.next() { + // Accumulate contiguous regions of rows that we want to move. + let (mut buffer_rows, mut display_rows) = + selection.buffer_rows_for_display_rows(map, app); + while let Some(next_selection) = selections_iter.peek() { + let (next_buffer_rows, next_display_rows) = + next_selection.buffer_rows_for_display_rows(map, app); + if next_buffer_rows.start <= buffer_rows.end { + buffer_rows.end = next_buffer_rows.end; + display_rows.end = next_display_rows.end; + selections_iter.next().unwrap(); + } else { + break; + } + } + + // Cut the text from the following line and paste it at the start of the selected region. + if buffer_rows.end <= buffer.max_point().row { + let selection_line_start = + Point::new(buffer_rows.start, 0).to_offset(buffer).unwrap(); + let next_line_display_end = DisplayPoint::new( + display_rows.end, + map.line_len(display_rows.end, app).unwrap(), + ); + let next_line_start = Point::new(buffer_rows.end, 0).to_offset(buffer).unwrap(); + let next_line_end = next_line_display_end + .to_buffer_offset(map, Bias::Right, app) + .unwrap(); + + let mut text = String::new(); + text.extend( + buffer + .text_for_range(next_line_start..next_line_end) + .unwrap(), + ); + text.push('\n'); + edits.push((selection_line_start..selection_line_start, text)); + edits.push((next_line_start - 1..next_line_end, String::new())); + } + } + + self.buffer.update(ctx, |buffer, ctx| { + for (range, text) in edits.into_iter().rev() { + buffer.edit(Some(range), text, Some(ctx)).unwrap(); + } + }); + + let mut selections = self.selections(ctx.as_ref()).to_vec(); + { + // Restore bias on selections. + let buffer = self.buffer.read(ctx); + for selection in &mut selections { + selection.start = selection.start.bias_left(buffer).unwrap(); + selection.end = selection.end.bias_left(buffer).unwrap(); + } + } + self.update_selections(selections, true, ctx); + + self.end_transaction(ctx); + } + pub fn cut(&mut self, _: &(), ctx: &mut ViewContext) { self.start_transaction(ctx); let mut text = String::new(); @@ -1175,9 +1329,11 @@ impl BufferView { } pub fn move_to_beginning(&mut self, _: &(), ctx: &mut ViewContext) { + let buffer = self.buffer.read(ctx); + let cursor = buffer.anchor_before(Point::new(0, 0)).unwrap(); let selection = Selection { - start: Anchor::Start, - end: Anchor::Start, + start: cursor.clone(), + end: cursor, reversed: false, goal_column: None, }; @@ -1191,9 +1347,11 @@ impl BufferView { } pub fn move_to_end(&mut self, _: &(), ctx: &mut ViewContext) { + let buffer = self.buffer.read(ctx); + let cursor = buffer.anchor_before(buffer.max_point()).unwrap(); let selection = Selection { - start: Anchor::End, - end: Anchor::End, + start: cursor.clone(), + end: cursor, reversed: false, goal_column: None, }; diff --git a/zed/src/editor/display_map/fold_map.rs b/zed/src/editor/display_map/fold_map.rs index 536971a87d13cffc33fc9e63a0d64ae3e2f02099..fd63a3e2ec478acb0b32c4bca19d6d4b83a93b95 100644 --- a/zed/src/editor/display_map/fold_map.rs +++ b/zed/src/editor/display_map/fold_map.rs @@ -169,6 +169,13 @@ impl FoldMap { false } + pub fn to_buffer_offset(&self, point: DisplayPoint, app: &AppContext) -> Result { + let mut cursor = self.transforms.cursor::(); + cursor.seek(&point, SeekBias::Right); + let overshoot = point.0 - cursor.start().display.lines; + (cursor.start().buffer.lines + overshoot).to_offset(self.buffer.read(app)) + } + pub fn to_display_offset( &self, point: DisplayPoint, diff --git a/zed/src/editor/display_map/mod.rs b/zed/src/editor/display_map/mod.rs index e8d2b6c6e5e199eb50111edb1d70cc43c29d7586..77a3defb124faf98aed9304b5b1b561bb9af92e8 100644 --- a/zed/src/editor/display_map/mod.rs +++ b/zed/src/editor/display_map/mod.rs @@ -179,6 +179,11 @@ impl DisplayPoint { .to_buffer_point(self.collapse_tabs(map, bias, app)?.0)) } + pub fn to_buffer_offset(self, map: &DisplayMap, bias: Bias, app: &AppContext) -> Result { + map.fold_map + .to_buffer_offset(self.collapse_tabs(map, bias, app)?.0, app) + } + fn expand_tabs(mut self, map: &DisplayMap, app: &AppContext) -> Result { let chars = map .fold_map From 76b454d34b69e80218fbacf923213b16ee08b29e Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 3 May 2021 14:49:35 +0200 Subject: [PATCH 2/7] Push selections down correctly when moving a line down --- zed/src/editor/buffer/selection.rs | 2 +- zed/src/editor/buffer_view.rs | 93 +++++++++++++++++++----------- 2 files changed, 60 insertions(+), 35 deletions(-) diff --git a/zed/src/editor/buffer/selection.rs b/zed/src/editor/buffer/selection.rs index 0999298357758cb00d29f155eb24a98a8907a8b6..431f8224c425d6e568da07718af36827520f7e64 100644 --- a/zed/src/editor/buffer/selection.rs +++ b/zed/src/editor/buffer/selection.rs @@ -84,7 +84,7 @@ impl Selection { .unwrap(); let mut display_end = self.end.to_display_point(map, ctx).unwrap(); - if display_end != map.max_point(ctx) + if 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_view.rs b/zed/src/editor/buffer_view.rs index 6bd727dc4fc93532ac7511d0976d37800681c77c..d1086f1790406c71cd0239107f013a346749226d 100644 --- a/zed/src/editor/buffer_view.rs +++ b/zed/src/editor/buffer_view.rs @@ -761,8 +761,8 @@ impl BufferView { // Restore bias on selections. let buffer = self.buffer.read(ctx); for selection in &mut selections { - selection.start = selection.start.bias_right(buffer).unwrap(); - selection.end = selection.end.bias_right(buffer).unwrap(); + selection.start = selection.start.bias_left(buffer).unwrap(); + selection.end = selection.end.bias_left(buffer).unwrap(); } self.update_selections(selections, true, ctx); @@ -777,19 +777,22 @@ impl BufferView { let map = self.display_map.read(ctx); let mut edits = Vec::new(); - let selections = self.selections(ctx.as_ref()).to_vec(); - let mut selections_iter = selections.iter().peekable(); - while let Some(selection) = selections_iter.next() { + let mut new_selection_ranges = Vec::new(); + let mut selections = self.selections(app).iter().peekable(); + let mut contiguous_selections = Vec::new(); + while let Some(selection) = selections.next() { // 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(map, app); - while let Some(next_selection) = selections_iter.peek() { + while let Some(next_selection) = selections.peek() { let (next_buffer_rows, next_display_rows) = next_selection.buffer_rows_for_display_rows(map, app); if next_buffer_rows.start <= buffer_rows.end { buffer_rows.end = next_buffer_rows.end; display_rows.end = next_display_rows.end; - selections_iter.next().unwrap(); + contiguous_selections.push(next_selection.range(buffer)); + selections.next().unwrap(); } else { break; } @@ -824,7 +827,14 @@ impl BufferView { ); edits.push((prev_line_start..prev_line_end + 1, String::new())); edits.push((selection_line_end..selection_line_end, text)); + + // Move selections to the previous line. + for range in &mut contiguous_selections { + range.start.row -= 1; + range.end.row -= 1; + } } + new_selection_ranges.extend(contiguous_selections.drain(..)); } self.buffer.update(ctx, |buffer, ctx| { @@ -832,43 +842,48 @@ impl BufferView { buffer.edit(Some(range), text, Some(ctx)).unwrap(); } }); - self.update_selections(selections, true, ctx); + + let buffer = self.buffer.read(ctx); + let mut new_selections = Vec::new(); + for range in new_selection_ranges { + let start = cmp::min(range.start, range.end); + let end = cmp::max(range.start, range.end); + new_selections.push(Selection { + start: buffer.anchor_before(start).unwrap(), + end: buffer.anchor_before(end).unwrap(), + reversed: range.start > range.end, + goal_column: None, + }); + } + self.update_selections(new_selections, true, ctx); + self.end_transaction(ctx); } pub fn move_line_down(&mut self, _: &(), ctx: &mut ViewContext) { self.start_transaction(ctx); - let mut selections = self.selections(ctx.as_ref()).to_vec(); - { - // Temporarily bias selections right to allow moved lines to push them down when the - // selections are at the beginning of a line. - let buffer = self.buffer.read(ctx); - for selection in &mut selections { - selection.start = selection.start.bias_right(buffer).unwrap(); - selection.end = selection.end.bias_right(buffer).unwrap(); - } - } - self.update_selections(selections.clone(), false, ctx); - let app = ctx.as_ref(); let buffer = self.buffer.read(ctx); let map = self.display_map.read(ctx); let mut edits = Vec::new(); - let selections = self.selections(ctx.as_ref()).to_vec(); - let mut selections_iter = selections.iter().peekable(); - while let Some(selection) = selections_iter.next() { + let mut new_selection_ranges = Vec::new(); + let mut selections = self.selections(app).iter().peekable(); + let mut contiguous_selections = Vec::new(); + while let Some(selection) = selections.next() { // 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(map, app); - while let Some(next_selection) = selections_iter.peek() { + while let Some(next_selection) = selections.peek() { let (next_buffer_rows, next_display_rows) = next_selection.buffer_rows_for_display_rows(map, app); if next_buffer_rows.start <= buffer_rows.end { buffer_rows.end = next_buffer_rows.end; display_rows.end = next_display_rows.end; - selections_iter.next().unwrap(); + contiguous_selections.push(next_selection.range(buffer)); + selections.next().unwrap(); } else { break; } @@ -896,7 +911,14 @@ impl BufferView { text.push('\n'); edits.push((selection_line_start..selection_line_start, text)); edits.push((next_line_start - 1..next_line_end, String::new())); + + // Move selections to the next line. + for range in &mut contiguous_selections { + range.start.row += 1; + range.end.row += 1; + } } + new_selection_ranges.extend(contiguous_selections.drain(..)); } self.buffer.update(ctx, |buffer, ctx| { @@ -905,16 +927,19 @@ impl BufferView { } }); - let mut selections = self.selections(ctx.as_ref()).to_vec(); - { - // Restore bias on selections. - let buffer = self.buffer.read(ctx); - for selection in &mut selections { - selection.start = selection.start.bias_left(buffer).unwrap(); - selection.end = selection.end.bias_left(buffer).unwrap(); - } + let buffer = self.buffer.read(ctx); + let mut new_selections = Vec::new(); + for range in new_selection_ranges { + let start = cmp::min(range.start, range.end); + let end = cmp::max(range.start, range.end); + new_selections.push(Selection { + start: buffer.anchor_before(start).unwrap(), + end: buffer.anchor_before(end).unwrap(), + reversed: range.start > range.end, + goal_column: None, + }); } - self.update_selections(selections, true, ctx); + self.update_selections(new_selections, true, ctx); self.end_transaction(ctx); } From 49dc0407863f4a6324d6af04bcff9654ed0f8450 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 3 May 2021 15:10:20 +0200 Subject: [PATCH 3/7] Use a more direct manipulation for moving lines up or down --- zed/src/editor/buffer_view.rs | 54 ++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/zed/src/editor/buffer_view.rs b/zed/src/editor/buffer_view.rs index d1086f1790406c71cd0239107f013a346749226d..f971377af14312ecfa86c0c8506644d3f4861df9 100644 --- a/zed/src/editor/buffer_view.rs +++ b/zed/src/editor/buffer_view.rs @@ -798,35 +798,31 @@ impl BufferView { } } - // Cut the text from the previous line and paste it at the end of the selected region. + // Cut the text from the selected rows and paste it at the start of the previous line. if display_rows.start != 0 { - let selection_line_end = Point::new( + let selection_row_start = + Point::new(buffer_rows.start, 0).to_offset(buffer).unwrap(); + let selection_row_end = Point::new( buffer_rows.end - 1, buffer.line_len(buffer_rows.end - 1).unwrap(), ) .to_offset(buffer) .unwrap(); - let prev_line_display_start = DisplayPoint::new(display_rows.start - 1, 0); - let prev_line_display_end = DisplayPoint::new( - prev_line_display_start.row(), - map.line_len(prev_line_display_start.row(), app).unwrap(), - ); - let prev_line_start = prev_line_display_start + + let prev_row_display_start = DisplayPoint::new(display_rows.start - 1, 0); + let prev_row_start = prev_row_display_start .to_buffer_offset(map, Bias::Left, app) .unwrap(); - let prev_line_end = prev_line_display_end - .to_buffer_offset(map, Bias::Right, app) - .unwrap(); let mut text = String::new(); - text.push('\n'); text.extend( buffer - .text_for_range(prev_line_start..prev_line_end) + .text_for_range(selection_row_start..selection_row_end) .unwrap(), ); - edits.push((prev_line_start..prev_line_end + 1, String::new())); - edits.push((selection_line_end..selection_line_end, text)); + text.push('\n'); + edits.push((prev_row_start..prev_row_start, text)); + edits.push((selection_row_start - 1..selection_row_end, String::new())); // Move selections to the previous line. for range in &mut contiguous_selections { @@ -889,28 +885,34 @@ impl BufferView { } } - // Cut the text from the following line and paste it at the start of the selected region. - if buffer_rows.end <= buffer.max_point().row { - let selection_line_start = + // Cut the text from the selected rows and paste it at the end of the next line. + if display_rows.end <= map.max_point(app).row() { + let selection_row_start = Point::new(buffer_rows.start, 0).to_offset(buffer).unwrap(); - let next_line_display_end = DisplayPoint::new( + let selection_row_end = Point::new( + buffer_rows.end - 1, + buffer.line_len(buffer_rows.end - 1).unwrap(), + ) + .to_offset(buffer) + .unwrap(); + + let next_row_display_end = DisplayPoint::new( display_rows.end, map.line_len(display_rows.end, app).unwrap(), ); - let next_line_start = Point::new(buffer_rows.end, 0).to_offset(buffer).unwrap(); - let next_line_end = next_line_display_end - .to_buffer_offset(map, Bias::Right, app) + let next_row_end = next_row_display_end + .to_buffer_offset(map, Bias::Left, app) .unwrap(); let mut text = String::new(); + text.push('\n'); text.extend( buffer - .text_for_range(next_line_start..next_line_end) + .text_for_range(selection_row_start..selection_row_end) .unwrap(), ); - text.push('\n'); - edits.push((selection_line_start..selection_line_start, text)); - edits.push((next_line_start - 1..next_line_end, String::new())); + edits.push((selection_row_start..selection_row_end + 1, String::new())); + edits.push((next_row_end..next_row_end, text)); // Move selections to the next line. for range in &mut contiguous_selections { From 4c4657515e89fcbf20c814ca99fa55caea832ba4 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 3 May 2021 16:13:09 +0200 Subject: [PATCH 4/7] Account for folds when moving selections up/down --- zed/src/editor/buffer_view.rs | 87 ++++++++++++++++------------------- 1 file changed, 39 insertions(+), 48 deletions(-) diff --git a/zed/src/editor/buffer_view.rs b/zed/src/editor/buffer_view.rs index f971377af14312ecfa86c0c8506644d3f4861df9..c37ae4818f53def10ff184c35f92d813d62224ed 100644 --- a/zed/src/editor/buffer_view.rs +++ b/zed/src/editor/buffer_view.rs @@ -19,6 +19,7 @@ use std::{ cmp::{self, Ordering}, fmt::Write, iter::FromIterator, + mem, ops::Range, path::Path, sync::Arc, @@ -468,23 +469,30 @@ impl BufferView { self.pending_selection.is_some() } - #[cfg(test)] - fn select_ranges<'a, T>(&mut self, ranges: T, ctx: &mut ViewContext) -> Result<()> + fn select_ranges(&mut self, ranges: I, autoscroll: bool, ctx: &mut ViewContext) where - T: IntoIterator>, + I: IntoIterator>, + T: ToOffset, { let buffer = self.buffer.read(ctx); let mut selections = Vec::new(); for range in ranges { + let mut start = range.start.to_offset(buffer).unwrap(); + let mut end = range.end.to_offset(buffer).unwrap(); + let reversed = if start > end { + mem::swap(&mut start, &mut end); + true + } else { + false + }; selections.push(Selection { - start: buffer.anchor_before(range.start)?, - end: buffer.anchor_before(range.end)?, - reversed: false, + start: buffer.anchor_before(start).unwrap(), + end: buffer.anchor_before(end).unwrap(), + reversed, goal_column: None, }); } - self.update_selections(selections, false, ctx); - Ok(()) + self.update_selections(selections, autoscroll, ctx); } #[cfg(test)] @@ -492,8 +500,6 @@ impl BufferView { where T: IntoIterator>, { - use std::mem; - let map = self.display_map.read(ctx); let mut selections = Vec::new(); for range in ranges { @@ -824,10 +830,15 @@ impl BufferView { edits.push((prev_row_start..prev_row_start, text)); edits.push((selection_row_start - 1..selection_row_end, String::new())); - // Move selections to the previous line. + // Move selections up. + let row_delta = buffer_rows.start + - prev_row_display_start + .to_buffer_point(map, Bias::Left, app) + .unwrap() + .row; for range in &mut contiguous_selections { - range.start.row -= 1; - range.end.row -= 1; + range.start.row -= row_delta; + range.end.row -= row_delta; } } new_selection_ranges.extend(contiguous_selections.drain(..)); @@ -838,20 +849,7 @@ impl BufferView { buffer.edit(Some(range), text, Some(ctx)).unwrap(); } }); - - let buffer = self.buffer.read(ctx); - let mut new_selections = Vec::new(); - for range in new_selection_ranges { - let start = cmp::min(range.start, range.end); - let end = cmp::max(range.start, range.end); - new_selections.push(Selection { - start: buffer.anchor_before(start).unwrap(), - end: buffer.anchor_before(end).unwrap(), - reversed: range.start > range.end, - goal_column: None, - }); - } - self.update_selections(new_selections, true, ctx); + self.select_ranges(new_selection_ranges, true, ctx); self.end_transaction(ctx); } @@ -914,10 +912,16 @@ impl BufferView { edits.push((selection_row_start..selection_row_end + 1, String::new())); edits.push((next_row_end..next_row_end, text)); - // Move selections to the next line. + // Move selections down. + let row_delta = next_row_display_end + .to_buffer_point(map, Bias::Right, app) + .unwrap() + .row + - buffer_rows.end + + 1; for range in &mut contiguous_selections { - range.start.row += 1; - range.end.row += 1; + range.start.row += row_delta; + range.end.row += row_delta; } } new_selection_ranges.extend(contiguous_selections.drain(..)); @@ -928,20 +932,7 @@ impl BufferView { buffer.edit(Some(range), text, Some(ctx)).unwrap(); } }); - - let buffer = self.buffer.read(ctx); - let mut new_selections = Vec::new(); - for range in new_selection_ranges { - let start = cmp::min(range.start, range.end); - let end = cmp::max(range.start, range.end); - new_selections.push(Selection { - start: buffer.anchor_before(start).unwrap(), - end: buffer.anchor_before(end).unwrap(), - reversed: range.start > range.end, - goal_column: None, - }); - } - self.update_selections(new_selections, true, ctx); + self.select_ranges(new_selection_ranges, true, ctx); self.end_transaction(ctx); } @@ -2597,14 +2588,14 @@ mod tests { // Cut with three selections. Clipboard text is divided into three slices. view.update(app, |view, ctx| { - view.select_ranges(&[0..4, 8..14, 19..24], ctx).unwrap(); + view.select_ranges(vec![0..4, 8..14, 19..24], false, ctx); view.cut(&(), ctx); }); assert_eq!(view.read(app).text(app.as_ref()), "two four six "); // Paste with three cursors. Each cursor pastes one slice of the clipboard text. view.update(app, |view, ctx| { - view.select_ranges(&[4..4, 9..9, 13..13], ctx).unwrap(); + view.select_ranges(vec![4..4, 9..9, 13..13], false, ctx); view.paste(&(), ctx); }); assert_eq!( @@ -2624,7 +2615,7 @@ mod tests { // match the number of slices in the clipboard, the entire clipboard text // is pasted at each cursor. view.update(app, |view, ctx| { - view.select_ranges(&[0..0, 28..28], ctx).unwrap(); + view.select_ranges(vec![0..0, 28..28], false, ctx); view.insert(&"( ".to_string(), ctx); view.paste(&(), ctx); view.insert(&") ".to_string(), ctx); @@ -2635,7 +2626,7 @@ mod tests { ); view.update(app, |view, ctx| { - view.select_ranges(&[0..0], ctx).unwrap(); + view.select_ranges(vec![0..0], false, ctx); view.insert(&"123\n4567\n89\n".to_string(), ctx); }); assert_eq!( From 4b38f2850d75db9703067c64355c4efc64a159a7 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 3 May 2021 18:58:39 +0200 Subject: [PATCH 5/7] 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>, From 189ee7c140688cc4168ee8cb9848acbfccc7d9e4 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 3 May 2021 12:39:47 -0700 Subject: [PATCH 6/7] Add failing unit test for adjacent folds --- zed/src/editor/display_map/fold_map.rs | 64 ++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 10 deletions(-) diff --git a/zed/src/editor/display_map/fold_map.rs b/zed/src/editor/display_map/fold_map.rs index 0e3626578be8edbf473e6b391549c0796f377e22..e81d2ee84a4dc0bf7cc8512d7d27b5607f4ed3e5 100644 --- a/zed/src/editor/display_map/fold_map.rs +++ b/zed/src/editor/display_map/fold_map.rs @@ -553,6 +553,50 @@ mod tests { }); } + #[test] + fn test_adjacent_folds() { + App::test((), |app| { + let buffer = app.add_model(|ctx| Buffer::new(0, "abcdefghijkl", ctx)); + + { + let mut map = FoldMap::new(buffer.clone(), app.as_ref()); + + map.fold(vec![5..8], app.as_ref()).unwrap(); + map.check_invariants(app.as_ref()); + assert_eq!(map.text(app.as_ref()), "abcde…ijkl"); + + // Create an fold adjacent to the start of the first fold. + map.fold(vec![1..1, 2..5], app.as_ref()).unwrap(); + map.check_invariants(app.as_ref()); + assert_eq!(map.text(app.as_ref()), "ab…ijkl"); + + // Create an fold adjacent to the end of the first fold. + map.fold(vec![11..11, 8..10], app.as_ref()).unwrap(); + map.check_invariants(app.as_ref()); + assert_eq!(map.text(app.as_ref()), "ab…kl"); + } + + { + let mut map = FoldMap::new(buffer.clone(), app.as_ref()); + + // Create two adjacent folds. + map.fold(vec![0..2, 2..5], app.as_ref()).unwrap(); + map.check_invariants(app.as_ref()); + assert_eq!(map.text(app.as_ref()), "…fghijkl"); + + // Edit within one of the folds. + let edits = buffer.update(app, |buffer, ctx| { + let version = buffer.version(); + buffer.edit(vec![0..1], "12345", Some(ctx)).unwrap(); + buffer.edits_since(version).collect::>() + }); + map.apply_edits(edits.as_slice(), app.as_ref()).unwrap(); + map.check_invariants(app.as_ref()); + assert_eq!(map.text(app.as_ref()), "12345…fghijkl"); + } + }); + } + #[test] fn test_overlapping_folds() { App::test((), |app| { @@ -621,8 +665,6 @@ 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); @@ -650,11 +692,8 @@ mod tests { 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()); + map.check_invariants(app.as_ref()); let mut expected_text = buffer.text(); for fold_range in map.merged_fold_ranges(app.as_ref()).into_iter().rev() { @@ -677,10 +716,7 @@ mod tests { }); log::info!("Editing {:?}", edits); map.apply_edits(&edits, app.as_ref()).unwrap(); - assert_eq!( - map.transforms.summary().buffer.chars, - buffer.read(app).len() - ); + map.check_invariants(app.as_ref()); let buffer = map.buffer.read(app); let mut expected_text = buffer.text(); @@ -772,5 +808,13 @@ mod tests { } merged_ranges } + + fn check_invariants(&self, app: &AppContext) { + assert_eq!( + self.transforms.summary().buffer.chars, + self.buffer.read(app).len(), + "transform tree does not match buffer's length" + ); + } } } From 837f34a498ccd81a5a5cc4abad7dbfbd7cbabd97 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 3 May 2021 14:30:50 -0600 Subject: [PATCH 7/7] Fix cases where new folds that end where existing folds start Co-Authored-By: Max Brunsfeld --- zed/src/editor/display_map/fold_map.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/zed/src/editor/display_map/fold_map.rs b/zed/src/editor/display_map/fold_map.rs index e81d2ee84a4dc0bf7cc8512d7d27b5607f4ed3e5..98c47ff08a84ea1a79ded4a0edf03da7ad0a681a 100644 --- a/zed/src/editor/display_map/fold_map.rs +++ b/zed/src/editor/display_map/fold_map.rs @@ -269,7 +269,7 @@ impl FoldMap { let next_edit = edits.next().unwrap(); delta += next_edit.delta(); - if next_edit.old_range.end > edit.old_range.end { + 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.next(); @@ -566,14 +566,14 @@ mod tests { assert_eq!(map.text(app.as_ref()), "abcde…ijkl"); // Create an fold adjacent to the start of the first fold. - map.fold(vec![1..1, 2..5], app.as_ref()).unwrap(); + map.fold(vec![0..1, 2..5], app.as_ref()).unwrap(); map.check_invariants(app.as_ref()); - assert_eq!(map.text(app.as_ref()), "ab…ijkl"); + assert_eq!(map.text(app.as_ref()), "…b…ijkl"); // Create an fold adjacent to the end of the first fold. map.fold(vec![11..11, 8..10], app.as_ref()).unwrap(); map.check_invariants(app.as_ref()); - assert_eq!(map.text(app.as_ref()), "ab…kl"); + assert_eq!(map.text(app.as_ref()), "…b…kl"); } { @@ -677,10 +677,8 @@ mod tests { }); let mut map = FoldMap::new(buffer.clone(), app.as_ref()); - for op_ix in 0..operations { - dbg!(op_ix); - - log::info!("Text: {:?}", buffer.read(app).text()); + for _ in 0..operations { + log::info!("text: {:?}", buffer.read(app).text()); { let buffer = buffer.read(app); @@ -691,7 +689,7 @@ mod tests { let start = rng.gen_range(0..end + 1); fold_ranges.push(start..end); } - log::info!("Folding {:?}", fold_ranges); + log::info!("folding {:?}", fold_ranges); map.fold(fold_ranges.clone(), app.as_ref()).unwrap(); map.check_invariants(app.as_ref()); @@ -714,7 +712,7 @@ mod tests { buffer.randomly_edit(&mut rng, edit_count, Some(ctx)); buffer.edits_since(start_version).collect::>() }); - log::info!("Editing {:?}", edits); + log::info!("editing {:?}", edits); map.apply_edits(&edits, app.as_ref()).unwrap(); map.check_invariants(app.as_ref());