From cded00cf291bd1f4c879242e8b53943be08d5d30 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 2 Apr 2021 16:20:40 -0700 Subject: [PATCH] Make backspace work correctly for empty selections --- zed/src/editor/buffer_view.rs | 59 ++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/zed/src/editor/buffer_view.rs b/zed/src/editor/buffer_view.rs index 7d538b88f4..7cb9ba815c 100644 --- a/zed/src/editor/buffer_view.rs +++ b/zed/src/editor/buffer_view.rs @@ -353,9 +353,9 @@ impl BufferView { } #[cfg(test)] - fn select_ranges(&mut self, ranges: T, ctx: &mut ViewContext) -> Result<()> + fn select_ranges<'a, T>(&mut self, ranges: T, ctx: &mut ViewContext) -> Result<()> where - T: IntoIterator>, + T: IntoIterator>, { let buffer = self.buffer.as_ref(ctx); let map = self.display_map.as_ref(ctx); @@ -426,7 +426,23 @@ impl BufferView { } pub fn backspace(&mut self, _: &(), ctx: &mut ViewContext) { - self.select_left(&(), ctx); + let buffer = self.buffer.as_ref(ctx); + let map = self.display_map.as_ref(ctx); + for selection in &mut self.selections { + if selection.range(buffer).is_empty() { + let head = selection.head().to_display_point(map, ctx.app()).unwrap(); + let cursor = map + .anchor_before( + movement::left(map, head, ctx.app()).unwrap(), + Bias::Left, + ctx.app(), + ) + .unwrap(); + selection.set_head(&buffer, cursor); + selection.goal_column = None; + } + } + self.changed_selections(ctx); self.insert(&String::new(), ctx); } @@ -1377,7 +1393,7 @@ mod tests { app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx)); view.update(&mut app, |view, ctx| { - view.select_ranges(Some(DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)), ctx)?; + view.select_ranges(&[DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)], ctx)?; view.fold(&(), ctx); assert_eq!( view.text(ctx.app()), @@ -1477,6 +1493,41 @@ mod tests { }) } + #[test] + fn test_backspace() -> Result<()> { + App::test((), |mut app| async move { + let buffer = app.add_model(|_| { + Buffer::new(0, "one two three\nfour five six\nseven eight nine\nten\n") + }); + let settings = settings::channel(&app.font_cache()).unwrap().1; + let (_, view) = + app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx)); + + view.update(&mut app, |view, ctx| -> Result<()> { + view.select_ranges( + &[ + // an empty selection - the preceding character is deleted + DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2), + // one character selected - it is deleted + DisplayPoint::new(1, 3)..DisplayPoint::new(1, 4), + // a line suffix selected - it is deleted + DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0), + ], + ctx, + )?; + view.backspace(&(), ctx); + Ok(()) + })?; + + buffer.read(&mut app, |buffer, _| -> Result<()> { + assert_eq!(buffer.text(), "oe two three\nfou five six\nseven ten\n"); + Ok(()) + })?; + + Ok(()) + }) + } + impl BufferView { fn selections(&self, app: &AppContext) -> Vec> { self.selections_in_range(DisplayPoint::zero()..self.max_point(app), app)