diff --git a/assets/keymaps/linux/jetbrains.json b/assets/keymaps/linux/jetbrains.json index 4283cc7a74..268ab9d9b2 100644 --- a/assets/keymaps/linux/jetbrains.json +++ b/assets/keymaps/linux/jetbrains.json @@ -12,7 +12,7 @@ "ctrl->": "zed::IncreaseBufferFontSize", "ctrl-<": "zed::DecreaseBufferFontSize", "ctrl-shift-j": "editor::JoinLines", - "ctrl-d": "editor::DuplicateLineDown", + "ctrl-d": "editor::DuplicateSelection", "ctrl-y": "editor::DeleteLine", "ctrl-m": "editor::ScrollCursorCenter", "ctrl-pagedown": "editor::MovePageDown", diff --git a/assets/keymaps/linux/sublime_text.json b/assets/keymaps/linux/sublime_text.json index 57ef4b876b..e4454d69bb 100644 --- a/assets/keymaps/linux/sublime_text.json +++ b/assets/keymaps/linux/sublime_text.json @@ -15,7 +15,7 @@ "ctrl-shift-m": "editor::SelectLargerSyntaxNode", "ctrl-shift-l": "editor::SplitSelectionIntoLines", "ctrl-shift-a": "editor::SelectLargerSyntaxNode", - "ctrl-shift-d": "editor::DuplicateLineDown", + "ctrl-shift-d": "editor::DuplicateSelection", "alt-f3": "editor::SelectAllMatches", // find_all_under "f12": "editor::GoToDefinition", "ctrl-f12": "editor::GoToDefinitionSplit", diff --git a/assets/keymaps/macos/jetbrains.json b/assets/keymaps/macos/jetbrains.json index 1dd702f9f7..6399c343b4 100644 --- a/assets/keymaps/macos/jetbrains.json +++ b/assets/keymaps/macos/jetbrains.json @@ -11,7 +11,7 @@ "ctrl->": "zed::IncreaseBufferFontSize", "ctrl-<": "zed::DecreaseBufferFontSize", "ctrl-shift-j": "editor::JoinLines", - "cmd-d": "editor::DuplicateLineDown", + "cmd-d": "editor::DuplicateSelection", "cmd-backspace": "editor::DeleteLine", "cmd-pagedown": "editor::MovePageDown", "cmd-pageup": "editor::MovePageUp", diff --git a/assets/keymaps/macos/sublime_text.json b/assets/keymaps/macos/sublime_text.json index f4c09b5144..120dbf4128 100644 --- a/assets/keymaps/macos/sublime_text.json +++ b/assets/keymaps/macos/sublime_text.json @@ -18,7 +18,7 @@ "ctrl-shift-m": "editor::SelectLargerSyntaxNode", "cmd-shift-l": "editor::SplitSelectionIntoLines", "cmd-shift-a": "editor::SelectLargerSyntaxNode", - "cmd-shift-d": "editor::DuplicateLineDown", + "cmd-shift-d": "editor::DuplicateSelection", "ctrl-cmd-g": "editor::SelectAllMatches", // find_all_under "shift-f12": "editor::FindAllReferences", "alt-cmd-down": "editor::GoToDefinition", diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 8be0767edd..7e50b0e97d 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -6135,29 +6135,7 @@ impl Editor { }); } - pub fn duplicate_selection(&mut self, _: &DuplicateSelection, cx: &mut ViewContext) { - let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); - let buffer = &display_map.buffer_snapshot; - let selections = self.selections.all::(cx); - - let mut edits = Vec::new(); - for selection in selections.iter() { - let start = selection.start; - let end = selection.end; - let text = buffer.text_for_range(start..end).collect::(); - edits.push((selection.end..selection.end, text)); - } - - self.transact(cx, |this, cx| { - this.buffer.update(cx, |buffer, cx| { - buffer.edit(edits, None, cx); - }); - - this.request_autoscroll(Autoscroll::fit(), cx); - }); - } - - pub fn duplicate_line(&mut self, upwards: bool, cx: &mut ViewContext) { + pub fn duplicate(&mut self, upwards: bool, whole_lines: bool, cx: &mut ViewContext) { let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); let buffer = &display_map.buffer_snapshot; let selections = self.selections.all::(cx); @@ -6165,36 +6143,44 @@ impl Editor { let mut edits = Vec::new(); 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); - - while let Some(next_selection) = selections_iter.peek() { - let next_rows = next_selection.spanned_rows(false, &display_map); - if next_rows.start < rows.end { - rows.end = next_rows.end; - selections_iter.next().unwrap(); - } else { - break; + // duplicate line-wise + if whole_lines || selection.start == selection.end { + // Avoid duplicating the same lines twice. + while let Some(next_selection) = selections_iter.peek() { + let next_rows = next_selection.spanned_rows(false, &display_map); + if next_rows.start < rows.end { + rows.end = next_rows.end; + selections_iter.next().unwrap(); + } else { + break; + } } - } - // Copy the text from the selected row region and splice it either at the start - // or end of the region. - let start = Point::new(rows.start.0, 0); - let end = Point::new( - rows.end.previous_row().0, - buffer.line_len(rows.end.previous_row()), - ); - let text = buffer - .text_for_range(start..end) - .chain(Some("\n")) - .collect::(); - let insert_location = if upwards { - Point::new(rows.end.0, 0) + // Copy the text from the selected row region and splice it either at the start + // or end of the region. + let start = Point::new(rows.start.0, 0); + let end = Point::new( + rows.end.previous_row().0, + buffer.line_len(rows.end.previous_row()), + ); + let text = buffer + .text_for_range(start..end) + .chain(Some("\n")) + .collect::(); + let insert_location = if upwards { + Point::new(rows.end.0, 0) + } else { + start + }; + edits.push((insert_location..insert_location, text)); } else { - start - }; - edits.push((insert_location..insert_location, text)); + // duplicate character-wise + let start = selection.start; + let end = selection.end; + let text = buffer.text_for_range(start..end).collect::(); + edits.push((selection.end..selection.end, text)); + } } self.transact(cx, |this, cx| { @@ -6207,11 +6193,15 @@ impl Editor { } pub fn duplicate_line_up(&mut self, _: &DuplicateLineUp, cx: &mut ViewContext) { - self.duplicate_line(true, cx); + self.duplicate(true, true, cx); } pub fn duplicate_line_down(&mut self, _: &DuplicateLineDown, cx: &mut ViewContext) { - self.duplicate_line(false, cx); + self.duplicate(false, true, cx); + } + + pub fn duplicate_selection(&mut self, _: &DuplicateSelection, cx: &mut ViewContext) { + self.duplicate(false, false, cx); } pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext) {