Split `DuplicateLine` into `DuplicateLineUp` and `DuplicateLineDown` (#9715)

Daniel Zhu created

Fixes #9601

Release Notes:
- `DuplicateLine` is now split into `DuplicateLineUp` and
`DuplicateLineDown`

Change summary

assets/keymaps/default-linux.json |  2 ++
assets/keymaps/default-macos.json |  9 ++-------
assets/keymaps/jetbrains.json     |  2 +-
assets/keymaps/textmate.json      |  2 +-
crates/editor/src/actions.rs      |  9 ++-------
crates/editor/src/editor.rs       | 12 ++++++++++--
crates/editor/src/editor_tests.rs |  8 ++++----
crates/editor/src/element.rs      |  3 ++-
crates/zed/src/zed/app_menus.rs   |  5 +----
9 files changed, 25 insertions(+), 27 deletions(-)

Detailed changes

assets/keymaps/default-linux.json 🔗

@@ -444,6 +444,8 @@
   {
     "context": "Editor",
     "bindings": {
+      "ctrl-shift-k": "editor::DeleteLine",
+      "ctrl-shift-d": "editor::DuplicateLineDown",
       "ctrl-j": "editor::JoinLines",
       "ctrl-alt-backspace": "editor::DeleteToPreviousSubwordStart",
       "ctrl-alt-h": "editor::DeleteToPreviousSubwordStart",

assets/keymaps/default-macos.json 🔗

@@ -318,13 +318,8 @@
       "cmd-shift-k": "editor::DeleteLine",
       "alt-up": "editor::MoveLineUp",
       "alt-down": "editor::MoveLineDown",
-      "alt-shift-up": [
-        "editor::DuplicateLine",
-        {
-          "move_upwards": true
-        }
-      ],
-      "alt-shift-down": "editor::DuplicateLine",
+      "alt-shift-up": "editor::DuplicateLineUp",
+      "alt-shift-down": "editor::DuplicateLineDown",
       "ctrl-shift-right": "editor::SelectLargerSyntaxNode",
       "ctrl-shift-left": "editor::SelectSmallerSyntaxNode",
       "cmd-d": [

assets/keymaps/jetbrains.json 🔗

@@ -11,7 +11,7 @@
       "ctrl->": "zed::IncreaseBufferFontSize",
       "ctrl-<": "zed::DecreaseBufferFontSize",
       "ctrl-shift-j": "editor::JoinLines",
-      "cmd-d": "editor::DuplicateLine",
+      "cmd-d": "editor::DuplicateLineDown",
       "cmd-backspace": "editor::DeleteLine",
       "cmd-pagedown": "editor::MovePageDown",
       "cmd-pageup": "editor::MovePageUp",

assets/keymaps/textmate.json 🔗

@@ -9,7 +9,7 @@
     "context": "Editor",
     "bindings": {
       "cmd-l": "go_to_line::Toggle",
-      "ctrl-shift-d": "editor::DuplicateLine",
+      "ctrl-shift-d": "editor::DuplicateLineDown",
       "cmd-b": "editor::GoToDefinition",
       "cmd-j": "editor::ScrollCursorCenter",
       "cmd-enter": "editor::NewlineBelow",

crates/editor/src/actions.rs 🔗

@@ -94,12 +94,6 @@ pub struct SelectDownByLines {
     pub(super) lines: u32,
 }
 
-#[derive(PartialEq, Clone, Deserialize, Default)]
-pub struct DuplicateLine {
-    #[serde(default)]
-    pub move_upwards: bool,
-}
-
 impl_actions!(
     editor,
     [
@@ -119,7 +113,6 @@ impl_actions!(
         MoveDownByLines,
         SelectUpByLines,
         SelectDownByLines,
-        DuplicateLine
     ]
 );
 
@@ -160,6 +153,8 @@ gpui::actions!(
         DeleteToPreviousSubwordStart,
         DeleteToPreviousWordStart,
         DisplayCursorNames,
+        DuplicateLineUp,
+        DuplicateLineDown,
         ExpandMacroRecursively,
         FindAllReferences,
         Fold,

crates/editor/src/editor.rs 🔗

@@ -5123,7 +5123,7 @@ impl Editor {
         });
     }
 
-    pub fn duplicate_line(&mut self, action: &DuplicateLine, cx: &mut ViewContext<Self>) {
+    pub fn duplicate_line(&mut self, upwards: bool, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let buffer = &display_map.buffer_snapshot;
         let selections = self.selections.all::<Point>(cx);
@@ -5152,7 +5152,7 @@ impl Editor {
                 .text_for_range(start..end)
                 .chain(Some("\n"))
                 .collect::<String>();
-            let insert_location = if action.move_upwards {
+            let insert_location = if upwards {
                 Point::new(rows.end, 0)
             } else {
                 start
@@ -5169,6 +5169,14 @@ impl Editor {
         });
     }
 
+    pub fn duplicate_line_up(&mut self, _: &DuplicateLineUp, cx: &mut ViewContext<Self>) {
+        self.duplicate_line(true, cx);
+    }
+
+    pub fn duplicate_line_down(&mut self, _: &DuplicateLineDown, cx: &mut ViewContext<Self>) {
+        self.duplicate_line(false, cx);
+    }
+
     pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let buffer = self.buffer.read(cx).snapshot(cx);

crates/editor/src/editor_tests.rs 🔗

@@ -3116,7 +3116,7 @@ fn test_duplicate_line(cx: &mut TestAppContext) {
                 DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
             ])
         });
-        view.duplicate_line(&DuplicateLine::default(), cx);
+        view.duplicate_line_down(&DuplicateLineDown, cx);
         assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
         assert_eq!(
             view.selections.display_ranges(cx),
@@ -3140,7 +3140,7 @@ fn test_duplicate_line(cx: &mut TestAppContext) {
                 DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
             ])
         });
-        view.duplicate_line(&DuplicateLine::default(), cx);
+        view.duplicate_line_down(&DuplicateLineDown, cx);
         assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
         assert_eq!(
             view.selections.display_ranges(cx),
@@ -3166,7 +3166,7 @@ fn test_duplicate_line(cx: &mut TestAppContext) {
                 DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
             ])
         });
-        view.duplicate_line(&DuplicateLine { move_upwards: true }, cx);
+        view.duplicate_line_up(&DuplicateLineUp, cx);
         assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
         assert_eq!(
             view.selections.display_ranges(cx),
@@ -3190,7 +3190,7 @@ fn test_duplicate_line(cx: &mut TestAppContext) {
                 DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
             ])
         });
-        view.duplicate_line(&DuplicateLine { move_upwards: true }, cx);
+        view.duplicate_line_up(&DuplicateLineUp, cx);
         assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
         assert_eq!(
             view.selections.display_ranges(cx),

crates/editor/src/element.rs 🔗

@@ -177,7 +177,8 @@ impl EditorElement {
         register_action(view, cx, Editor::delete_to_beginning_of_line);
         register_action(view, cx, Editor::delete_to_end_of_line);
         register_action(view, cx, Editor::cut_to_end_of_line);
-        register_action(view, cx, Editor::duplicate_line);
+        register_action(view, cx, Editor::duplicate_line_up);
+        register_action(view, cx, Editor::duplicate_line_down);
         register_action(view, cx, Editor::move_line_up);
         register_action(view, cx, Editor::move_line_down);
         register_action(view, cx, Editor::transpose);

crates/zed/src/zed/app_menus.rs 🔗

@@ -98,10 +98,7 @@ pub fn app_menus() -> Vec<Menu<'static>> {
                 MenuItem::separator(),
                 MenuItem::action("Move Line Up", editor::actions::MoveLineUp),
                 MenuItem::action("Move Line Down", editor::actions::MoveLineDown),
-                MenuItem::action(
-                    "Duplicate Selection",
-                    editor::actions::DuplicateLine::default(),
-                ),
+                MenuItem::action("Duplicate Selection", editor::actions::DuplicateLineDown),
             ],
         },
         Menu {