WIP making paste better

Keith Simmons created

Change summary

assets/keymaps/vim.json                    |  3 ++-
crates/editor/src/selections_collection.rs | 24 +++++++++++++++++++++++-
crates/vim/src/normal.rs                   |  4 +++-
crates/vim/src/visual.rs                   |  2 +-
4 files changed, 29 insertions(+), 4 deletions(-)

Detailed changes

assets/keymaps/vim.json 🔗

@@ -140,7 +140,8 @@
             "c": "vim::VisualChange",
             "d": "vim::VisualDelete",
             "x": "vim::VisualDelete",
-            "y": "vim::VisualYank"
+            "y": "vim::VisualYank",
+            "p": "vim::Paste"
         }
     },
     {

crates/editor/src/selections_collection.rs 🔗

@@ -149,6 +149,28 @@ impl SelectionsCollection {
         selections
     }
 
+    pub fn all_adjusted_display(
+        &self,
+        cx: &mut MutableAppContext,
+    ) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) {
+        if self.line_mode {
+            let selections = self.all::<Point>(cx);
+            let map = self.display_map(cx);
+            let result = selections
+                .into_iter()
+                .map(|mut selection| {
+                    let new_range = map.expand_to_line(selection.range());
+                    selection.start = new_range.start;
+                    selection.end = new_range.end;
+                    selection.map(|point| point.to_display_point(&map))
+                })
+                .collect();
+            (map, result)
+        } else {
+            self.all_display(cx)
+        }
+    }
+
     pub fn disjoint_in_range<'a, D>(
         &self,
         range: Range<Anchor>,
@@ -175,7 +197,7 @@ impl SelectionsCollection {
     }
 
     pub fn all_display(
-        &mut self,
+        &self,
         cx: &mut MutableAppContext,
     ) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) {
         let display_map = self.display_map(cx);

crates/vim/src/normal.rs 🔗

@@ -7,6 +7,7 @@ use std::borrow::Cow;
 use crate::{
     motion::Motion,
     state::{Mode, Operator},
+    utils::copy_selections_content,
     Vim,
 };
 use change::init as change_init;
@@ -200,11 +201,12 @@ fn paste(_: &mut Workspace, _: &Paste, cx: &mut ViewContext<Workspace>) {
         vim.update_active_editor(cx, |editor, cx| {
             editor.transact(cx, |editor, cx| {
                 if let Some(item) = cx.as_mut().read_from_clipboard() {
+                    copy_selections_content(editor, editor.selections.line_mode, cx);
                     let mut clipboard_text = Cow::Borrowed(item.text());
                     if let Some(mut clipboard_selections) =
                         item.metadata::<Vec<ClipboardSelection>>()
                     {
-                        let (display_map, selections) = editor.selections.all_display(cx);
+                        let (display_map, selections) = editor.selections.all_adjusted_display(cx);
                         let all_selections_were_entire_line =
                             clipboard_selections.iter().all(|s| s.is_entire_line);
                         if clipboard_selections.len() != selections.len() {

crates/vim/src/visual.rs 🔗

@@ -6,7 +6,7 @@ use workspace::Workspace;
 
 use crate::{motion::Motion, state::Mode, utils::copy_selections_content, Vim};
 
-actions!(vim, [VisualDelete, VisualChange, VisualYank]);
+actions!(vim, [VisualDelete, VisualChange, VisualYank, VisualPaste]);
 
 pub fn init(cx: &mut MutableAppContext) {
     cx.add_action(change);