helix: Further cleanups to helix paste in line mode (#38694)

Jakub Konka created

I noticed that after we paste in line mode, the cursor position is
positioned at the beginning of the next logical line which is somewhat
undesirable since then inserting/appending will position the cursor
after the selection. This does not match helix behaviour which we should
further investigate.

Follow-up to https://github.com/zed-industries/zed/pull/38663

Release Notes:

- N/A

Change summary

crates/vim/src/helix/paste.rs | 61 ++++++++++++++++++++----------------
1 file changed, 34 insertions(+), 27 deletions(-)

Detailed changes

crates/vim/src/helix/paste.rs 🔗

@@ -84,21 +84,14 @@ impl Vim {
                     let display_point = if line_mode {
                         if action.before {
                             movement::line_beginning(&display_map, sel.start, false)
-                        } else if sel.start.column() > 0
-                            && sel.end.column() == 0
-                            && sel.start != sel.end
-                        {
-                            sel.end
                         } else {
-                            let point = movement::line_end(&display_map, sel.end, false);
-                            if sel.end.column() == 0 && point.column() > 0 {
-                                // If the selection ends at the beginning of the next line, and the current line
-                                // under the cursor is not empty, we paste at the selection's end.
-                                sel.end
+                            if sel.start == sel.end {
+                                movement::right(
+                                    &display_map,
+                                    movement::line_end(&display_map, sel.end, false),
+                                )
                             } else {
-                                // If however the current line under the cursor is empty, we need to move
-                                // to the beginning of the next line to avoid pasting above the end of current selection.
-                                movement::right(&display_map, point)
+                                sel.end
                             }
                         }
                     } else if action.before {
@@ -132,12 +125,6 @@ impl Vim {
                         let offset = anchor.to_offset(&snapshot);
                         if action.before {
                             offset.saturating_sub(len)..offset
-                        } else if line_mode {
-                            // In line mode, we always move the cursor to the end of the inserted text.
-                            // Otherwise, while it looks fine visually, inserting/appending ends up
-                            // in the next logical line which is not desirable.
-                            debug_assert!(len > 0);
-                            offset..(offset + len - 1)
                         } else {
                             offset..(offset + len)
                         }
@@ -401,8 +388,8 @@ mod test {
             indoc! {"
             The quick brown
             fox jumps over
-            «nˇ»
-            the lazy dog."},
+            «n
+            ˇ»the lazy dog."},
             Mode::HelixNormal,
         );
 
@@ -411,8 +398,8 @@ mod test {
         cx.set_state(
             indoc! {"
             The quick brown
-            fox jumps over
-            ˇthe lazy dog."},
+            fox jumps overˇ
+            the lazy dog."},
             Mode::HelixNormal,
         );
         cx.simulate_keystrokes("p");
@@ -420,8 +407,8 @@ mod test {
             indoc! {"
             The quick brown
             fox jumps over
-            «nˇ»
-            the lazy dog."},
+            «n
+            ˇ»the lazy dog."},
             Mode::HelixNormal,
         );
 
@@ -437,11 +424,31 @@ mod test {
         cx.assert_state(
             indoc! {"
 
-            «fox jumps overˇ»
-            The quick brown
+            «fox jumps over
+            ˇ»The quick brown
             fox jumps over
             the lazy dog."},
             Mode::HelixNormal,
         );
+
+        cx.set_state(
+            indoc! {"
+            «The quick brown
+            fox jumps over
+            ˇ»the lazy dog."},
+            Mode::HelixNormal,
+        );
+        cx.simulate_keystrokes("y p p");
+        cx.assert_state(
+            indoc! {"
+            The quick brown
+            fox jumps over
+            The quick brown
+            fox jumps over
+            «The quick brown
+            fox jumps over
+            ˇ»the lazy dog."},
+            Mode::HelixNormal,
+        );
     }
 }