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

View file

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

View file

@ -94,6 +94,12 @@ pub struct SelectDownByLines {
pub(super) lines: u32,
}
#[derive(PartialEq, Clone, Deserialize, Default)]
pub struct DuplicateLine {
#[serde(default)]
pub move_upwards: bool,
}
impl_actions!(
editor,
[
@ -112,7 +118,8 @@ impl_actions!(
MoveUpByLines,
MoveDownByLines,
SelectUpByLines,
SelectDownByLines
SelectDownByLines,
DuplicateLine
]
);
@ -152,7 +159,6 @@ gpui::actions!(
DeleteToPreviousSubwordStart,
DeleteToPreviousWordStart,
DisplayCursorNames,
DuplicateLine,
ExpandMacroRecursively,
FindAllReferences,
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 buffer = &display_map.buffer_snapshot;
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 end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
let text = buffer
.text_for_range(start..end)
.chain(Some("\n"))
.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| {

View file

@ -3118,7 +3118,7 @@ fn test_duplicate_line(cx: &mut TestAppContext) {
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.selections.display_ranges(cx),
@ -3142,7 +3142,7 @@ fn test_duplicate_line(cx: &mut TestAppContext) {
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.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]

View file

@ -99,7 +99,10 @@ 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),
MenuItem::action(
"Duplicate Selection",
editor::actions::DuplicateLine::default(),
),
],
},
Menu {