Get the Editor crate compiling

Max Brunsfeld created

Change summary

crates/buffer/src/anchor.rs    |  10 
crates/buffer/src/selection.rs |   4 
crates/editor/src/lib.rs       | 643 ++++++++++++++++-------------------
3 files changed, 307 insertions(+), 350 deletions(-)

Detailed changes

crates/buffer/src/anchor.rs 🔗

@@ -185,6 +185,16 @@ impl<T: Debug> Debug for AnchorRangeMap<T> {
     }
 }
 
+impl Debug for AnchorRangeSet {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        let mut f = f.debug_set();
+        for (range, _) in &self.0.entries {
+            f.entry(range);
+        }
+        f.finish()
+    }
+}
+
 impl AnchorRangeSet {
     pub fn len(&self) -> usize {
         self.0.len()

crates/buffer/src/selection.rs 🔗

@@ -37,6 +37,10 @@ pub struct SelectionState {
 }
 
 impl<T: ToOffset + ToPoint + Copy + Ord> Selection<T> {
+    pub fn is_empty(&self) -> bool {
+        self.start == self.end
+    }
+
     pub fn head(&self) -> T {
         if self.reversed {
             self.start

crates/editor/src/lib.rs 🔗

@@ -10,9 +10,9 @@ pub use display_map::DisplayPoint;
 use display_map::*;
 pub use element::*;
 use gpui::{
-    action, color::Color, fonts::TextStyle, geometry::vector::Vector2F, keymap::Binding,
-    text_layout, AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle,
-    MutableAppContext, RenderContext, View, ViewContext, WeakViewHandle,
+    action, geometry::vector::Vector2F, keymap::Binding, text_layout, AppContext, ClipboardItem,
+    Element, ElementBox, Entity, ModelHandle, MutableAppContext, RenderContext, View, ViewContext,
+    WeakViewHandle,
 };
 use language::*;
 use serde::{Deserialize, Serialize};
@@ -20,8 +20,7 @@ use smallvec::SmallVec;
 use smol::Timer;
 use std::{
     cell::RefCell,
-    cmp::{self, Ordering},
-    iter, mem,
+    cmp, iter, mem,
     ops::{Range, RangeInclusive},
     rc::Rc,
     sync::Arc,
@@ -297,7 +296,7 @@ pub struct Editor {
     next_selection_id: usize,
     add_selections_state: Option<AddSelectionsState>,
     autoclose_stack: Vec<BracketPairState>,
-    select_larger_syntax_node_stack: Vec<Arc<[Selection<Point>]>>,
+    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
     scroll_position: Vector2F,
     scroll_top_anchor: Anchor,
     autoscroll_requested: bool,
@@ -324,6 +323,7 @@ struct AddSelectionsState {
     stack: Vec<usize>,
 }
 
+#[derive(Debug)]
 struct BracketPairState {
     ranges: AnchorRangeSet,
     pair: BracketPair,
@@ -512,7 +512,7 @@ impl Editor {
             return false;
         }
 
-        let selections = self.point_selections(cx).peekable();
+        let mut selections = self.point_selections(cx).peekable();
         let first_cursor_top = selections
             .peek()
             .unwrap()
@@ -641,7 +641,6 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let buffer = self.buffer.read(cx);
         let cursor = position.to_buffer_point(&display_map, Bias::Left);
         if let Some(selection) = self.pending_selection.as_mut() {
             selection.set_head(cursor);
@@ -657,7 +656,7 @@ impl Editor {
     fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
         if let Some(selection) = self.pending_selection.take() {
             let mut selections = self.point_selections(cx).collect::<Vec<_>>();
-            let ix = self.selection_insertion_index(&selections, selection.start, cx.as_ref());
+            let ix = self.selection_insertion_index(&selections, selection.start);
             selections.insert(ix, selection);
             self.update_selections(selections, false, cx);
         }
@@ -690,24 +689,26 @@ impl Editor {
         T: ToOffset,
     {
         let buffer = self.buffer.read(cx);
-        let mut selections = Vec::new();
-        for range in ranges {
-            let mut start = range.start.to_offset(buffer);
-            let mut end = range.end.to_offset(buffer);
-            let reversed = if start > end {
-                mem::swap(&mut start, &mut end);
-                true
-            } else {
-                false
-            };
-            selections.push(Selection {
-                id: post_inc(&mut self.next_selection_id),
-                start: buffer.anchor_before(start),
-                end: buffer.anchor_before(end),
-                reversed,
-                goal: SelectionGoal::None,
-            });
-        }
+        let selections = ranges
+            .into_iter()
+            .map(|range| {
+                let mut start = range.start.to_offset(buffer);
+                let mut end = range.end.to_offset(buffer);
+                let reversed = if start > end {
+                    mem::swap(&mut start, &mut end);
+                    true
+                } else {
+                    false
+                };
+                Selection {
+                    id: post_inc(&mut self.next_selection_id),
+                    start: start,
+                    end: end,
+                    reversed,
+                    goal: SelectionGoal::None,
+                }
+            })
+            .collect();
         self.update_selections(selections, autoscroll, cx);
     }
 
@@ -720,26 +721,27 @@ impl Editor {
     where
         T: IntoIterator<Item = &'a Range<DisplayPoint>>,
     {
-        let mut selections = Vec::new();
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        for range in ranges {
-            let mut start = range.start;
-            let mut end = range.end;
-            let reversed = if start > end {
-                mem::swap(&mut start, &mut end);
-                true
-            } else {
-                false
-            };
-
-            selections.push(Selection {
-                id: post_inc(&mut self.next_selection_id),
-                start: display_map.anchor_before(start, Bias::Left),
-                end: display_map.anchor_before(end, Bias::Left),
-                reversed,
-                goal: SelectionGoal::None,
-            });
-        }
+        let selections = ranges
+            .into_iter()
+            .map(|range| {
+                let mut start = range.start;
+                let mut end = range.end;
+                let reversed = if start > end {
+                    mem::swap(&mut start, &mut end);
+                    true
+                } else {
+                    false
+                };
+                Selection {
+                    id: post_inc(&mut self.next_selection_id),
+                    start: start.to_buffer_point(&display_map, Bias::Left),
+                    end: end.to_buffer_point(&display_map, Bias::Left),
+                    reversed,
+                    goal: SelectionGoal::None,
+                }
+            })
+            .collect();
         self.update_selections(selections, false, cx);
         Ok(())
     }
@@ -848,7 +850,7 @@ impl Editor {
                     let start = (range.start as isize + delta) as usize;
                     let end = (range.end as isize + delta) as usize;
                     let text_before_cursor_len = indent as usize + 1;
-                    let anchor = buffer.anchor_before(start + text_before_cursor_len);
+                    let cursor = start + text_before_cursor_len;
                     let text_len = if insert_extra_newline {
                         text_before_cursor_len * 2
                     } else {
@@ -857,8 +859,8 @@ impl Editor {
                     delta += text_len as isize - (end - start) as isize;
                     Selection {
                         id,
-                        start: anchor.clone(),
-                        end: anchor,
+                        start: cursor,
+                        end: cursor,
                         reversed: false,
                         goal: SelectionGoal::None,
                     }
@@ -949,9 +951,12 @@ impl Editor {
                 buffer.edit(selection_ranges, &pair.end, cx);
 
                 if pair.end.len() == 1 {
+                    let mut delta = 0;
                     Some(BracketPairState {
-                        ranges: buffer.anchor_range_set(selections.iter().map(|selection| {
-                            (selection.start, Bias::Left)..(selection.start, Bias::Right)
+                        ranges: buffer.anchor_range_set(selections.iter().map(move |selection| {
+                            let offset = selection.start + delta;
+                            delta += 1;
+                            (offset, Bias::Left)..(offset, Bias::Right)
                         })),
                         pair,
                     })
@@ -965,7 +970,7 @@ impl Editor {
 
     fn skip_autoclose_end(&mut self, text: &str, cx: &mut ViewContext<Self>) -> bool {
         let old_selection_count = self.selection_count(cx);
-        let old_selections = self.offset_selections(cx);
+        let old_selections = self.offset_selections(cx).collect::<Vec<_>>();
         let autoclose_pair_state = if let Some(autoclose_pair_state) = self.autoclose_stack.last() {
             autoclose_pair_state
         } else {
@@ -979,20 +984,21 @@ impl Editor {
 
         let buffer = self.buffer.read(cx);
         if old_selections
-            .zip(&autoclose_pair_state.ranges.to_offset_ranges(buffer))
-            .all(|((_, selection_range), autoclose_range)| {
+            .iter()
+            .zip(autoclose_pair_state.ranges.to_offset_ranges(buffer))
+            .all(|(selection, autoclose_range)| {
                 let autoclose_range_end = autoclose_range.end.to_offset(buffer);
-                selection_range.is_empty() && selection_range.start == autoclose_range_end
+                selection.is_empty() && selection.start == autoclose_range_end
             })
         {
-            let new_selections = old_selection_ranges
+            let new_selections = old_selections
                 .into_iter()
-                .map(|(id, range)| {
-                    let new_head = buffer.anchor_before(range.start + 1);
+                .map(|selection| {
+                    let cursor = selection.start + 1;
                     Selection {
-                        id,
-                        start: new_head.clone(),
-                        end: new_head,
+                        id: selection.id,
+                        start: cursor,
+                        end: cursor,
                         reversed: false,
                         goal: SelectionGoal::None,
                     }
@@ -1015,22 +1021,18 @@ impl Editor {
 
     pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
-        let mut selections = self.selections(cx).to_vec();
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        {
-            let buffer = self.buffer.read(cx);
-            for selection in &mut selections {
-                let range = selection.point_range(buffer);
-                if range.start == range.end {
-                    let head = selection.head().to_display_point(&display_map, Bias::Left);
-                    let cursor = display_map
-                        .anchor_before(movement::left(&display_map, head).unwrap(), Bias::Left);
-                    selection.set_head(&buffer, cursor);
-                    selection.goal = SelectionGoal::None;
-                }
+        for selection in &mut selections {
+            if selection.is_empty() {
+                let head = selection.head().to_display_point(&display_map, Bias::Left);
+                let cursor = movement::left(&display_map, head)
+                    .unwrap()
+                    .to_buffer_point(&display_map, Bias::Left);
+                selection.set_head(cursor);
+                selection.goal = SelectionGoal::None;
             }
         }
-
         self.update_selections(selections, true, cx);
         self.insert("", cx);
         self.end_transaction(cx);
@@ -1039,21 +1041,17 @@ impl Editor {
     pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx).to_vec();
-        {
-            let buffer = self.buffer.read(cx);
-            for selection in &mut selections {
-                let range = selection.point_range(buffer);
-                if range.start == range.end {
-                    let head = selection.head().to_display_point(&display_map, Bias::Left);
-                    let cursor = display_map
-                        .anchor_before(movement::right(&display_map, head).unwrap(), Bias::Right);
-                    selection.set_head(&buffer, cursor);
-                    selection.goal = SelectionGoal::None;
-                }
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
+        for selection in &mut selections {
+            if selection.is_empty() {
+                let head = selection.head().to_display_point(&display_map, Bias::Left);
+                let cursor = movement::right(&display_map, head)
+                    .unwrap()
+                    .to_buffer_point(&display_map, Bias::Right);
+                selection.set_head(cursor);
+                selection.goal = SelectionGoal::None;
             }
         }
-
         self.update_selections(selections, true, cx);
         self.insert(&"", cx);
         self.end_transaction(cx);
@@ -1062,28 +1060,24 @@ impl Editor {
     pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
         let tab_size = self.build_settings.borrow()(cx).tab_size;
-        let mut selections = self.selections(cx).to_vec();
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
         self.buffer.update(cx, |buffer, cx| {
             let mut last_indented_row = None;
             for selection in &mut selections {
-                let mut range = selection.point_range(buffer);
-                if range.is_empty() {
+                if selection.is_empty() {
                     let char_column = buffer
-                        .chars_for_range(Point::new(range.start.row, 0)..range.start)
+                        .chars_for_range(Point::new(selection.start.row, 0)..selection.start)
                         .count();
                     let chars_to_next_tab_stop = tab_size - (char_column % tab_size);
                     buffer.edit(
-                        [range.start..range.start],
+                        [selection.start..selection.start],
                         " ".repeat(chars_to_next_tab_stop),
                         cx,
                     );
-                    range.start.column += chars_to_next_tab_stop as u32;
-
-                    let head = buffer.anchor_before(range.start);
-                    selection.start = head.clone();
-                    selection.end = head;
+                    selection.start.column += chars_to_next_tab_stop as u32;
+                    selection.end = selection.start;
                 } else {
-                    for row in range.start.row..=range.end.row {
+                    for row in selection.start.row..=selection.end.row {
                         if last_indented_row != Some(row) {
                             let char_column = buffer.indent_column_for_line(row) as usize;
                             let chars_to_next_tab_stop = tab_size - (char_column % tab_size);
@@ -1107,13 +1101,13 @@ impl Editor {
     pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
 
-        let selections = self.selections(cx);
+        let selections = self.point_selections(cx).collect::<Vec<_>>();
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let buffer = self.buffer.read(cx);
 
+        let mut row_delta = 0;
         let mut new_cursors = Vec::new();
         let mut edit_ranges = Vec::new();
-
         let mut selections = selections.iter().peekable();
         while let Some(selection) = selections.next() {
             let mut rows = selection.spanned_rows(false, &display_map).buffer_rows;
@@ -1140,7 +1134,7 @@ impl Editor {
                 // If there's a line after the range, delete the \n from the end of the row range
                 // and position the cursor on the next line.
                 edit_end = Point::new(rows.end, 0).to_offset(buffer);
-                cursor_buffer_row = rows.end;
+                cursor_buffer_row = rows.start;
             } else {
                 // If there isn't a line after the range, delete the \n from the line before the
                 // start of the row range and position the cursor there.
@@ -1149,10 +1143,11 @@ impl Editor {
                 cursor_buffer_row = rows.start.saturating_sub(1);
             }
 
-            let mut cursor =
-                Point::new(cursor_buffer_row, 0).to_display_point(&display_map, Bias::Left);
+            let mut cursor = Point::new(cursor_buffer_row - row_delta, 0)
+                .to_display_point(&display_map, Bias::Left);
             *cursor.column_mut() =
                 cmp::min(goal_display_column, display_map.line_len(cursor.row()));
+            row_delta += rows.len() as u32;
 
             new_cursors.push((
                 selection.id,
@@ -1161,18 +1156,15 @@ impl Editor {
             edit_ranges.push(edit_start..edit_end);
         }
 
-        new_cursors.sort_unstable_by_key(|(_, range)| range.clone());
+        new_cursors.sort_unstable_by_key(|(_, point)| point.clone());
         let new_selections = new_cursors
             .into_iter()
-            .map(|(id, cursor)| {
-                let anchor = buffer.anchor_before(cursor);
-                Selection {
-                    id,
-                    start: anchor.clone(),
-                    end: anchor,
-                    reversed: false,
-                    goal: SelectionGoal::None,
-                }
+            .map(|(id, cursor)| Selection {
+                id,
+                start: cursor,
+                end: cursor,
+                reversed: false,
+                goal: SelectionGoal::None,
             })
             .collect();
         self.buffer
@@ -1184,26 +1176,16 @@ impl Editor {
     pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
 
-        let mut selections = self.selections(cx).to_vec();
-        {
-            // Temporarily bias selections right to allow newly duplicate lines to push them down
-            // when the selections are at the beginning of a line.
-            let buffer = self.buffer.read(cx);
-            for selection in &mut selections {
-                selection.start = selection.start.bias_right(buffer);
-                selection.end = selection.end.bias_right(buffer);
-            }
-        }
-        self.update_selections(selections.clone(), false, cx);
-
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let buffer = self.buffer.read(cx);
 
         let mut edits = Vec::new();
-        let mut selections_iter = selections.iter_mut().peekable();
+        let mut selections_iter = selections.iter().peekable();
         while let Some(selection) = selections_iter.next() {
             // Avoid duplicating the same lines twice.
             let mut rows = selection.spanned_rows(false, &display_map).buffer_rows;
+
             while let Some(next_selection) = selections_iter.peek() {
                 let next_rows = next_selection.spanned_rows(false, &display_map).buffer_rows;
                 if next_rows.start <= rows.end - 1 {
@@ -1221,30 +1203,38 @@ impl Editor {
                 .text_for_range(start..end)
                 .chain(Some("\n"))
                 .collect::<String>();
-            edits.push((start, text));
+            edits.push((start, text, rows.len() as u32));
+        }
+
+        let mut edits_iter = edits.iter().peekable();
+        let mut row_delta = 0;
+        for selection in selections.iter_mut() {
+            while let Some((point, _, line_count)) = edits_iter.peek() {
+                if *point <= selection.start {
+                    row_delta += line_count;
+                    edits_iter.next();
+                } else {
+                    break;
+                }
+            }
+            selection.start.row += row_delta;
+            selection.end.row += row_delta;
         }
 
         self.buffer.update(cx, |buffer, cx| {
-            for (offset, text) in edits.into_iter().rev() {
-                buffer.edit(Some(offset..offset), text, cx);
+            for (point, text, _) in edits.into_iter().rev() {
+                buffer.edit(Some(point..point), text, cx);
             }
         });
 
-        // Restore bias on selections.
-        let buffer = self.buffer.read(cx);
-        for selection in &mut selections {
-            selection.start = selection.start.bias_left(buffer);
-            selection.end = selection.end.bias_left(buffer);
-        }
         self.update_selections(selections, true, cx);
-
         self.end_transaction(cx);
     }
 
     pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
 
-        let selections = self.selections(cx);
+        let selections = self.point_selections(cx).collect::<Vec<_>>();
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let buffer = self.buffer.read(cx);
 
@@ -1334,7 +1324,7 @@ impl Editor {
     pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
 
-        let selections = self.selections(cx);
+        let selections = self.point_selections(cx).collect::<Vec<_>>();
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let buffer = self.buffer.read(cx);
 
@@ -1421,23 +1411,19 @@ impl Editor {
     pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
         self.start_transaction(cx);
         let mut text = String::new();
-        let mut selections = self.selections(cx).to_vec();
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
         let mut clipboard_selections = Vec::with_capacity(selections.len());
         {
             let buffer = self.buffer.read(cx);
             let max_point = buffer.max_point();
             for selection in &mut selections {
-                let mut start = selection.start.to_point(buffer);
-                let mut end = selection.end.to_point(buffer);
-                let is_entire_line = start == end;
+                let is_entire_line = selection.is_empty();
                 if is_entire_line {
-                    start = Point::new(start.row, 0);
-                    end = cmp::min(max_point, Point::new(start.row + 1, 0));
-                    selection.start = buffer.anchor_before(start);
-                    selection.end = buffer.anchor_before(end);
+                    selection.start = Point::new(selection.start.row, 0);
+                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
                 }
                 let mut len = 0;
-                for chunk in buffer.text_for_range(start..end) {
+                for chunk in buffer.text_for_range(selection.start..selection.end) {
                     text.push_str(chunk);
                     len += chunk.len();
                 }
@@ -1456,15 +1442,15 @@ impl Editor {
     }
 
     pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
-        let selections = self.selections(cx);
+        let selections = self.point_selections(cx).collect::<Vec<_>>();
         let buffer = self.buffer.read(cx);
         let max_point = buffer.max_point();
         let mut text = String::new();
         let mut clipboard_selections = Vec::with_capacity(selections.len());
         for selection in selections.iter() {
-            let mut start = selection.start.to_point(buffer);
-            let mut end = selection.end.to_point(buffer);
-            let is_entire_line = start == end;
+            let mut start = selection.start;
+            let mut end = selection.end;
+            let is_entire_line = selection.is_empty();
             if is_entire_line {
                 start = Point::new(start.row, 0);
                 end = cmp::min(max_point, Point::new(start.row + 1, 0));
@@ -1488,16 +1474,16 @@ impl Editor {
         if let Some(item) = cx.as_mut().read_from_clipboard() {
             let clipboard_text = item.text();
             if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
-                let selections = self.selections(cx);
+                let mut selections = self.offset_selections(cx).collect::<Vec<_>>();
                 let all_selections_were_entire_line =
                     clipboard_selections.iter().all(|s| s.is_entire_line);
                 if clipboard_selections.len() != selections.len() {
                     clipboard_selections.clear();
                 }
 
+                let mut delta = 0_isize;
                 let mut start_offset = 0;
-                let mut new_selections = Vec::with_capacity(selections.len());
-                for (i, selection) in selections.iter().enumerate() {
+                for (i, selection) in selections.iter_mut().enumerate() {
                     let to_insert;
                     let entire_line;
                     if let Some(clipboard_selection) = clipboard_selections.get(i) {
@@ -1510,33 +1496,29 @@ impl Editor {
                         entire_line = all_selections_were_entire_line;
                     }
 
-                    self.buffer.update(cx, |buffer, cx| {
-                        let selection_start = selection.start.to_point(&*buffer);
-                        let selection_end = selection.end.to_point(&*buffer);
+                    selection.start = (selection.start as isize + delta) as usize;
+                    selection.end = (selection.end as isize + delta) as usize;
 
+                    self.buffer.update(cx, |buffer, cx| {
                         // If the corresponding selection was empty when this slice of the
                         // clipboard text was written, then the entire line containing the
                         // selection was copied. If this selection is also currently empty,
                         // then paste the line before the current line of the buffer.
-                        let new_selection_start = selection.end.bias_right(buffer);
-                        if selection_start == selection_end && entire_line {
-                            let line_start = Point::new(selection_start.row, 0);
-                            buffer.edit(Some(line_start..line_start), to_insert, cx);
+                        let range = if selection.is_empty() && entire_line {
+                            let column = selection.start.to_point(&*buffer).column as usize;
+                            let line_start = selection.start - column;
+                            line_start..line_start
                         } else {
-                            buffer.edit(Some(&selection.start..&selection.end), to_insert, cx);
+                            selection.start..selection.end
                         };
 
-                        let new_selection_start = new_selection_start.bias_left(buffer);
-                        new_selections.push(Selection {
-                            id: selection.id,
-                            start: new_selection_start.clone(),
-                            end: new_selection_start,
-                            reversed: false,
-                            goal: SelectionGoal::None,
-                        });
+                        delta += to_insert.len() as isize - range.len() as isize;
+                        buffer.edit([range], to_insert, cx);
+                        selection.start += to_insert.len();
+                        selection.end = selection.start;
                     });
                 }
-                self.update_selections(new_selections, true, cx);
+                self.update_selections(selections, true, cx);
             } else {
                 self.insert(clipboard_text, cx);
             }
@@ -1553,121 +1535,110 @@ impl Editor {
 
     pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx).to_vec();
-        {
-            for selection in &mut selections {
-                let start = selection.start.to_display_point(&display_map, Bias::Left);
-                let end = selection.end.to_display_point(&display_map, Bias::Left);
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
+        for selection in &mut selections {
+            let start = selection.start.to_display_point(&display_map, Bias::Left);
+            let end = selection.end.to_display_point(&display_map, Bias::Left);
 
-                if start != end {
-                    selection.end = selection.start.clone();
-                } else {
-                    let cursor = display_map
-                        .anchor_before(movement::left(&display_map, start).unwrap(), Bias::Left);
-                    selection.start = cursor.clone();
-                    selection.end = cursor;
-                }
-                selection.reversed = false;
-                selection.goal = SelectionGoal::None;
+            if start != end {
+                selection.end = selection.start.clone();
+            } else {
+                let cursor = movement::left(&display_map, start)
+                    .unwrap()
+                    .to_buffer_point(&display_map, Bias::Left);
+                selection.start = cursor.clone();
+                selection.end = cursor;
             }
+            selection.reversed = false;
+            selection.goal = SelectionGoal::None;
         }
         self.update_selections(selections, true, cx);
     }
 
     pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx).to_vec();
-        {
-            let buffer = self.buffer.read(cx);
-            for selection in &mut selections {
-                let head = selection.head().to_display_point(&display_map, Bias::Left);
-                let cursor = display_map
-                    .anchor_before(movement::left(&display_map, head).unwrap(), Bias::Left);
-                selection.set_head(&buffer, cursor);
-                selection.goal = SelectionGoal::None;
-            }
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
+        for selection in &mut selections {
+            let head = selection.head().to_display_point(&display_map, Bias::Left);
+            let cursor = movement::left(&display_map, head)
+                .unwrap()
+                .to_buffer_point(&display_map, Bias::Left);
+            selection.set_head(cursor);
+            selection.goal = SelectionGoal::None;
         }
         self.update_selections(selections, true, cx);
     }
 
     pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx).to_vec();
-        {
-            for selection in &mut selections {
-                let start = selection.start.to_display_point(&display_map, Bias::Left);
-                let end = selection.end.to_display_point(&display_map, Bias::Left);
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
+        for selection in &mut selections {
+            let start = selection.start.to_display_point(&display_map, Bias::Left);
+            let end = selection.end.to_display_point(&display_map, Bias::Left);
 
-                if start != end {
-                    selection.start = selection.end.clone();
-                } else {
-                    let cursor = display_map
-                        .anchor_before(movement::right(&display_map, end).unwrap(), Bias::Right);
-                    selection.start = cursor.clone();
-                    selection.end = cursor;
-                }
-                selection.reversed = false;
-                selection.goal = SelectionGoal::None;
+            if start != end {
+                selection.start = selection.end.clone();
+            } else {
+                let cursor = movement::right(&display_map, end)
+                    .unwrap()
+                    .to_buffer_point(&display_map, Bias::Right);
+                selection.start = cursor;
+                selection.end = cursor;
             }
+            selection.reversed = false;
+            selection.goal = SelectionGoal::None;
         }
         self.update_selections(selections, true, cx);
     }
 
     pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx).to_vec();
-        {
-            let app = cx.as_ref();
-            let buffer = self.buffer.read(app);
-            for selection in &mut selections {
-                let head = selection.head().to_display_point(&display_map, Bias::Left);
-                let cursor = display_map
-                    .anchor_before(movement::right(&display_map, head).unwrap(), Bias::Right);
-                selection.set_head(&buffer, cursor);
-                selection.goal = SelectionGoal::None;
-            }
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
+        for selection in &mut selections {
+            let head = selection.head().to_display_point(&display_map, Bias::Left);
+            let cursor = movement::right(&display_map, head)
+                .unwrap()
+                .to_buffer_point(&display_map, Bias::Right);
+            selection.set_head(cursor);
+            selection.goal = SelectionGoal::None;
         }
         self.update_selections(selections, true, cx);
     }
 
     pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
-        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         if matches!(self.mode, EditorMode::SingleLine) {
             cx.propagate_action();
-        } else {
-            let mut selections = self.selections(cx).to_vec();
-            {
-                for selection in &mut selections {
-                    let start = selection.start.to_display_point(&display_map, Bias::Left);
-                    let end = selection.end.to_display_point(&display_map, Bias::Left);
-                    if start != end {
-                        selection.goal = SelectionGoal::None;
-                    }
+            return;
+        }
 
-                    let (start, goal) = movement::up(&display_map, start, selection.goal).unwrap();
-                    let cursor = display_map.anchor_before(start, Bias::Left);
-                    selection.start = cursor.clone();
-                    selection.end = cursor;
-                    selection.goal = goal;
-                    selection.reversed = false;
-                }
+        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
+        for selection in &mut selections {
+            let start = selection.start.to_display_point(&display_map, Bias::Left);
+            let end = selection.end.to_display_point(&display_map, Bias::Left);
+            if start != end {
+                selection.goal = SelectionGoal::None;
             }
-            self.update_selections(selections, true, cx);
+
+            let (start, goal) = movement::up(&display_map, start, selection.goal).unwrap();
+            let cursor = start.to_buffer_point(&display_map, Bias::Left);
+            selection.start = cursor;
+            selection.end = cursor;
+            selection.goal = goal;
+            selection.reversed = false;
         }
+        self.update_selections(selections, true, cx);
     }
 
     pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx).to_vec();
-        {
-            let app = cx.as_ref();
-            let buffer = self.buffer.read(app);
-            for selection in &mut selections {
-                let head = selection.head().to_display_point(&display_map, Bias::Left);
-                let (head, goal) = movement::up(&display_map, head, selection.goal).unwrap();
-                selection.set_head(&buffer, display_map.anchor_before(head, Bias::Left));
-                selection.goal = goal;
-            }
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
+        for selection in &mut selections {
+            let head = selection.head().to_display_point(&display_map, Bias::Left);
+            let (head, goal) = movement::up(&display_map, head, selection.goal).unwrap();
+            let cursor = head.to_buffer_point(&display_map, Bias::Left);
+            selection.set_head(cursor);
+            selection.goal = goal;
         }
         self.update_selections(selections, true, cx);
     }
@@ -1675,41 +1646,37 @@ impl Editor {
     pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
         if matches!(self.mode, EditorMode::SingleLine) {
             cx.propagate_action();
-        } else {
-            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-            let mut selections = self.selections(cx).to_vec();
-            {
-                for selection in &mut selections {
-                    let start = selection.start.to_display_point(&display_map, Bias::Left);
-                    let end = selection.end.to_display_point(&display_map, Bias::Left);
-                    if start != end {
-                        selection.goal = SelectionGoal::None;
-                    }
+            return;
+        }
 
-                    let (start, goal) = movement::down(&display_map, end, selection.goal).unwrap();
-                    let cursor = display_map.anchor_before(start, Bias::Right);
-                    selection.start = cursor.clone();
-                    selection.end = cursor;
-                    selection.goal = goal;
-                    selection.reversed = false;
-                }
+        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
+        for selection in &mut selections {
+            let start = selection.start.to_display_point(&display_map, Bias::Left);
+            let end = selection.end.to_display_point(&display_map, Bias::Left);
+            if start != end {
+                selection.goal = SelectionGoal::None;
             }
-            self.update_selections(selections, true, cx);
+
+            let (start, goal) = movement::down(&display_map, end, selection.goal).unwrap();
+            let cursor = start.to_buffer_point(&display_map, Bias::Right);
+            selection.start = cursor;
+            selection.end = cursor;
+            selection.goal = goal;
+            selection.reversed = false;
         }
+        self.update_selections(selections, true, cx);
     }
 
     pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx).to_vec();
-        {
-            let app = cx.as_ref();
-            let buffer = self.buffer.read(app);
-            for selection in &mut selections {
-                let head = selection.head().to_display_point(&display_map, Bias::Left);
-                let (head, goal) = movement::down(&display_map, head, selection.goal).unwrap();
-                selection.set_head(&buffer, display_map.anchor_before(head, Bias::Right));
-                selection.goal = goal;
-            }
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
+        for selection in &mut selections {
+            let head = selection.head().to_display_point(&display_map, Bias::Left);
+            let (head, goal) = movement::down(&display_map, head, selection.goal).unwrap();
+            let cursor = head.to_buffer_point(&display_map, Bias::Right);
+            selection.set_head(cursor);
+            selection.goal = goal;
         }
         self.update_selections(selections, true, cx);
     }
@@ -1720,17 +1687,15 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx).to_vec();
-        {
-            for selection in &mut selections {
-                let head = selection.head().to_display_point(&display_map, Bias::Left);
-                let new_head = movement::prev_word_boundary(&display_map, head).unwrap();
-                let anchor = display_map.anchor_before(new_head, Bias::Left);
-                selection.start = anchor.clone();
-                selection.end = anchor;
-                selection.reversed = false;
-                selection.goal = SelectionGoal::None;
-            }
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
+        for selection in &mut selections {
+            let head = selection.head().to_display_point(&display_map, Bias::Left);
+            let new_head = movement::prev_word_boundary(&display_map, head).unwrap();
+            let cursor = new_head.to_buffer_point(&display_map, Bias::Left);
+            selection.start = cursor.clone();
+            selection.end = cursor;
+            selection.reversed = false;
+            selection.goal = SelectionGoal::None;
         }
         self.update_selections(selections, true, cx);
     }
@@ -1741,16 +1706,13 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx).to_vec();
-        {
-            let buffer = self.buffer.read(cx);
-            for selection in &mut selections {
-                let head = selection.head().to_display_point(&display_map, Bias::Left);
-                let new_head = movement::prev_word_boundary(&display_map, head).unwrap();
-                let anchor = display_map.anchor_before(new_head, Bias::Left);
-                selection.set_head(buffer, anchor);
-                selection.goal = SelectionGoal::None;
-            }
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
+        for selection in &mut selections {
+            let head = selection.head().to_display_point(&display_map, Bias::Left);
+            let new_head = movement::prev_word_boundary(&display_map, head).unwrap();
+            let cursor = new_head.to_buffer_point(&display_map, Bias::Left);
+            selection.set_head(cursor);
+            selection.goal = SelectionGoal::None;
         }
         self.update_selections(selections, true, cx);
     }
@@ -1762,23 +1724,16 @@ impl Editor {
     ) {
         self.start_transaction(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx).to_vec();
-        {
-            let buffer = self.buffer.read(cx);
-            for selection in &mut selections {
-                let range = selection.point_range(buffer);
-                if range.start == range.end {
-                    let head = selection.head().to_display_point(&display_map, Bias::Left);
-                    let cursor = display_map.anchor_before(
-                        movement::prev_word_boundary(&display_map, head).unwrap(),
-                        Bias::Right,
-                    );
-                    selection.set_head(&buffer, cursor);
-                    selection.goal = SelectionGoal::None;
-                }
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
+        for selection in &mut selections {
+            if selection.is_empty() {
+                let head = selection.head().to_display_point(&display_map, Bias::Left);
+                let new_head = movement::prev_word_boundary(&display_map, head).unwrap();
+                let cursor = new_head.to_buffer_point(&display_map, Bias::Right);
+                selection.set_head(cursor);
+                selection.goal = SelectionGoal::None;
             }
         }
-
         self.update_selections(selections, true, cx);
         self.insert("", cx);
         self.end_transaction(cx);
@@ -1790,17 +1745,15 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx).to_vec();
-        {
-            for selection in &mut selections {
-                let head = selection.head().to_display_point(&display_map, Bias::Left);
-                let new_head = movement::next_word_boundary(&display_map, head).unwrap();
-                let anchor = display_map.anchor_before(new_head, Bias::Left);
-                selection.start = anchor.clone();
-                selection.end = anchor;
-                selection.reversed = false;
-                selection.goal = SelectionGoal::None;
-            }
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
+        for selection in &mut selections {
+            let head = selection.head().to_display_point(&display_map, Bias::Left);
+            let new_head = movement::next_word_boundary(&display_map, head).unwrap();
+            let cursor = new_head.to_buffer_point(&display_map, Bias::Left);
+            selection.start = cursor;
+            selection.end = cursor;
+            selection.reversed = false;
+            selection.goal = SelectionGoal::None;
         }
         self.update_selections(selections, true, cx);
     }
@@ -1811,16 +1764,13 @@ impl Editor {
         cx: &mut ViewContext<Self>,
     ) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx).to_vec();
-        {
-            let buffer = self.buffer.read(cx);
-            for selection in &mut selections {
-                let head = selection.head().to_display_point(&display_map, Bias::Left);
-                let new_head = movement::next_word_boundary(&display_map, head).unwrap();
-                let anchor = display_map.anchor_before(new_head, Bias::Left);
-                selection.set_head(buffer, anchor);
-                selection.goal = SelectionGoal::None;
-            }
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
+        for selection in &mut selections {
+            let head = selection.head().to_display_point(&display_map, Bias::Left);
+            let new_head = movement::next_word_boundary(&display_map, head).unwrap();
+            let cursor = new_head.to_buffer_point(&display_map, Bias::Left);
+            selection.set_head(cursor);
+            selection.goal = SelectionGoal::None;
         }
         self.update_selections(selections, true, cx);
     }
@@ -1832,23 +1782,16 @@ impl Editor {
     ) {
         self.start_transaction(cx);
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-        let mut selections = self.selections(cx).to_vec();
-        {
-            let buffer = self.buffer.read(cx);
-            for selection in &mut selections {
-                let range = selection.point_range(buffer);
-                if range.start == range.end {
-                    let head = selection.head().to_display_point(&display_map, Bias::Left);
-                    let cursor = display_map.anchor_before(
-                        movement::next_word_boundary(&display_map, head).unwrap(),
-                        Bias::Right,
-                    );
-                    selection.set_head(&buffer, cursor);
-                    selection.goal = SelectionGoal::None;
-                }
+        let mut selections = self.point_selections(cx).collect::<Vec<_>>();
+        for selection in &mut selections {
+            if selection.is_empty() {
+                let head = selection.head().to_display_point(&display_map, Bias::Left);
+                let new_head = movement::next_word_boundary(&display_map, head).unwrap();
+                let cursor = new_head.to_buffer_point(&display_map, Bias::Right);
+                selection.set_head(cursor);
+                selection.goal = SelectionGoal::None;
             }
         }
-
         self.update_selections(selections, true, cx);
         self.insert("", cx);
         self.end_transaction(cx);