Improve bindings to better match VS-Code (#8584)

Release Notes:

- Changed default keybindings in the VS Code keymap so that
`alt-[up|down]` now move lines up/down and`alt-shift-[up|down]`
duplicate lines up/down. Previous bindings for selecting larger/smaller
syntax nodes are now bound to `ctrl-shift-[left|right]`.
([#4652](https://github.com/zed-industries/zed/issues/4652))([#7151](https://github.com/zed-industries/zed/issues/7151))

---------

Co-authored-by: Thorsten Ball <mrnugget@gmail.com>
This commit is contained in:
Edvard Høiby 2024-03-06 20:16:14 +01:00 committed by GitHub
parent 850ddddcac
commit 8352f39ff9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 87 additions and 14 deletions

View file

@ -315,6 +315,18 @@
"cmd-ctrl-p": "editor::AddSelectionAbove", "cmd-ctrl-p": "editor::AddSelectionAbove",
"cmd-alt-down": "editor::AddSelectionBelow", "cmd-alt-down": "editor::AddSelectionBelow",
"cmd-ctrl-n": "editor::AddSelectionBelow", "cmd-ctrl-n": "editor::AddSelectionBelow",
"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",
"ctrl-shift-right": "editor::SelectLargerSyntaxNode",
"ctrl-shift-left": "editor::SelectSmallerSyntaxNode",
"cmd-d": [ "cmd-d": [
"editor::SelectNext", "editor::SelectNext",
{ {
@ -347,8 +359,6 @@
"advance_downwards": false "advance_downwards": false
} }
], ],
"alt-up": "editor::SelectLargerSyntaxNode",
"alt-down": "editor::SelectSmallerSyntaxNode",
"cmd-u": "editor::UndoSelection", "cmd-u": "editor::UndoSelection",
"cmd-shift-u": "editor::RedoSelection", "cmd-shift-u": "editor::RedoSelection",
"f8": "editor::GoToDiagnostic", "f8": "editor::GoToDiagnostic",
@ -454,11 +464,7 @@
{ {
"context": "Editor", "context": "Editor",
"bindings": { "bindings": {
"ctrl-shift-k": "editor::DeleteLine",
"cmd-shift-d": "editor::DuplicateLine",
"ctrl-j": "editor::JoinLines", "ctrl-j": "editor::JoinLines",
"ctrl-cmd-up": "editor::MoveLineUp",
"ctrl-cmd-down": "editor::MoveLineDown",
"ctrl-alt-backspace": "editor::DeleteToPreviousSubwordStart", "ctrl-alt-backspace": "editor::DeleteToPreviousSubwordStart",
"ctrl-alt-h": "editor::DeleteToPreviousSubwordStart", "ctrl-alt-h": "editor::DeleteToPreviousSubwordStart",
"ctrl-alt-delete": "editor::DeleteToNextSubwordEnd", "ctrl-alt-delete": "editor::DeleteToNextSubwordEnd",

View file

@ -39,6 +39,8 @@
"advance_downwards": true "advance_downwards": true
} }
], ],
"alt-up": "editor::SelectLargerSyntaxNode",
"alt-down": "editor::SelectSmallerSyntaxNode",
"shift-alt-up": "editor::MoveLineUp", "shift-alt-up": "editor::MoveLineUp",
"shift-alt-down": "editor::MoveLineDown", "shift-alt-down": "editor::MoveLineDown",
"cmd-alt-l": "editor::Format", "cmd-alt-l": "editor::Format",

View file

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

View file

@ -5032,7 +5032,7 @@ impl Editor {
}); });
} }
pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) { pub fn duplicate_line(&mut self, action: &DuplicateLine, cx: &mut ViewContext<Self>) {
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let buffer = &display_map.buffer_snapshot; let buffer = &display_map.buffer_snapshot;
let selections = self.selections.all::<Point>(cx); let selections = self.selections.all::<Point>(cx);
@ -5053,14 +5053,20 @@ impl Editor {
} }
} }
// Copy the text from the selected row region and splice it at the start of the region. // 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); let start = Point::new(rows.start, 0);
let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1)); let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
let text = buffer let text = buffer
.text_for_range(start..end) .text_for_range(start..end)
.chain(Some("\n")) .chain(Some("\n"))
.collect::<String>(); .collect::<String>();
edits.push((start..start, text)); let insert_location = if action.move_upwards {
Point::new(rows.end, 0)
} else {
start
};
edits.push((insert_location..insert_location, text));
} }
self.transact(cx, |this, cx| { self.transact(cx, |this, cx| {

View file

@ -3118,7 +3118,7 @@ fn test_duplicate_line(cx: &mut TestAppContext) {
DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0), DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
]) ])
}); });
view.duplicate_line(&DuplicateLine, cx); view.duplicate_line(&DuplicateLine::default(), cx);
assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n"); assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
assert_eq!( assert_eq!(
view.selections.display_ranges(cx), view.selections.display_ranges(cx),
@ -3142,7 +3142,7 @@ fn test_duplicate_line(cx: &mut TestAppContext) {
DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1), DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
]) ])
}); });
view.duplicate_line(&DuplicateLine, cx); view.duplicate_line(&DuplicateLine::default(), cx);
assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n"); assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
assert_eq!( assert_eq!(
view.selections.display_ranges(cx), view.selections.display_ranges(cx),
@ -3152,6 +3152,56 @@ fn test_duplicate_line(cx: &mut TestAppContext) {
] ]
); );
}); });
// With `move_upwards` the selections stay in place, except for
// the lines inserted above them
let view = cx.add_window(|cx| {
let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
build_editor(buffer, cx)
});
_ = view.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
s.select_display_ranges([
DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
])
});
view.duplicate_line(&DuplicateLine { move_upwards: true }, cx);
assert_eq!(view.display_text(cx), "abc\nabc\ndef\ndef\nghi\n\n");
assert_eq!(
view.selections.display_ranges(cx),
vec![
DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
]
);
});
let view = cx.add_window(|cx| {
let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
build_editor(buffer, cx)
});
_ = view.update(cx, |view, cx| {
view.change_selections(None, cx, |s| {
s.select_display_ranges([
DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
])
});
view.duplicate_line(&DuplicateLine { move_upwards: true }, cx);
assert_eq!(view.display_text(cx), "abc\ndef\nghi\nabc\ndef\nghi\n");
assert_eq!(
view.selections.display_ranges(cx),
vec![
DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
]
);
});
} }
#[gpui::test] #[gpui::test]

View file

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